跳至内容

多区域

示例

多区域是一种微前端方法,它将域名上的大型应用程序拆分为较小的 Next.js 应用程序,每个应用程序服务一组路径。当应用程序中存在与其他页面无关的页面集合时,这很有用。通过将这些页面移动到单独的区域(即单独的应用程序),您可以减少每个应用程序的大小,从而提高构建时间并删除仅对其中一个区域必要的代码。由于应用程序是解耦的,因此多区域还允许域名上的其他应用程序使用它们自己的框架选择。

例如,假设您有一组想要拆分的页面:

  • /blog/* 用于所有博文
  • /dashboard/* 用于用户登录仪表板时的所有页面
  • /* 用于未被其他区域覆盖的网站其余部分

通过多区域支持,您可以创建三个应用程序,这些应用程序都服务于同一个域名,并且对用户来说看起来相同,但是您可以独立地开发和部署每个应用程序。

Three zones: A, B, C. Showing a hard navigation between routes from different zones, and soft navigations between routes within the same zone.

在同一区域内页面之间的导航将执行软导航,这是一种不需要重新加载页面的导航。例如,在此图中,从/ 导航到 /products 将是软导航。

从一个区域中的页面导航到另一个区域中的页面,例如从 //dashboard,将执行硬导航,卸载当前页面的资源并加载新页面的资源。经常一起访问的页面应该位于同一个区域中,以避免硬导航。

如何定义区域

区域是一个普通的 Next.js 应用程序,您还可以配置一个assetPrefix 以避免与其他区域中的页面和静态文件发生冲突。

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  assetPrefix: '/blog-static',
}

Next.js 资产(例如 JavaScript 和 CSS)将在其前缀中添加 assetPrefix,以确保它们不会与来自其他区域的资产发生冲突。这些资产将在每个区域的 /assetPrefix/_next/... 下提供服务。

处理所有未路由到其他更具体区域的路径的默认应用程序不需要 assetPrefix

在低于 Next.js 15 的版本中,您可能还需要其他重写来处理静态资产。在 Next.js 15 中,这不再需要。

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  assetPrefix: '/blog-static',
  async rewrites() {
    return {
      beforeFiles: [
        {
          source: '/blog-static/_next/:path+',
          destination: '/_next/:path+',
        },
      ],
    }
  },
}

如何将请求路由到正确的区域

使用多区域设置后,您需要将路径路由到正确的区域,因为它们由不同的应用程序提供服务。您可以使用任何 HTTP 代理来执行此操作,但其中一个 Next.js 应用程序也可以用于路由整个域名的请求。

要使用 Next.js 应用程序将路由到正确的区域,您可以使用rewrites。对于每个由不同区域提供的路径,您将添加一条重写规则以将该路径发送到另一个区域的域名。例如

next.config.js
async rewrites() {
    return [
        {
            source: '/blog',
            destination: `${process.env.BLOG_DOMAIN}/blog`,
        },
        {
            source: '/blog/:path+',
            destination: `${process.env.BLOG_DOMAIN}/blog/:path+`,
        }
    ];
}

destination 应该是区域提供的 URL,包括方案和域名。这应该指向区域的生产域名,但也可以用于在本地开发中将请求路由到 localhost

注意:URL 路径应对于区域唯一。例如,两个区域试图服务 /blog 将导致路由冲突。

使用中间件路由请求

建议通过rewrites路由请求以最大程度地减少请求的延迟开销,但在需要在路由时进行动态决策时,也可以使用中间件。例如,如果您正在使用功能标记来决定路径应路由到的位置(例如在迁移期间),则可以使用中间件。

middleware.js
export async function middleware(request) {
  const { pathname, search } = req.nextUrl;
  if (pathname === '/your-path' && myFeaturFlag.isEnabled()) {
    return NextResponse.rewrite(`${rewriteDomain}${pathname}${search});
  }
}

区域间链接

指向不同区域中路径的链接应使用a标签而不是Next.js的<Link>组件。这是因为Next.js会尝试预取并软导航到<Link>组件中的任何相对路径,这在区域之间将不起作用。

代码共享

构成不同区域的不同Next.js应用程序可以位于任何存储库中。但是,通常将这些区域放在monorepo中以便更容易地共享代码。对于位于不同存储库中的区域,也可以使用公共或私有NPM包来共享代码。

由于不同区域中的页面可能在不同的时间发布,因此功能标记可用于同步启用或禁用不同区域中的功能。

对于Next.js on Vercel应用程序,您可以使用monorepo通过单个git push部署所有受影响的区域。

服务器操作

在使用服务器操作与多区域时,您必须显式允许面向用户的来源,因为您的面向用户域可能会服务于多个应用程序。在您的next.config.js文件中,添加以下行

next.config.js
const nextConfig = {
  experimental: {
    serverActions: {
      allowedOrigins: ['your-production-domain.com'],
    },
  },
}

有关更多信息,请参阅serverActions.allowedOrigins