Skip to main content

多区域

Examples

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

¥Multi-Zones are an approach to micro-frontends that separate a large application on a domain into smaller Next.js applications that each serve a set of paths. This is useful when there are collections of pages unrelated to the other pages in the application. By moving those pages to a separate zone (i.e., a separate application), you can reduce the size of each application which improves build times and removes code that is only necessary for one of the zones. Since applications are decoupled, Multi-Zones also allows other applications on the domain to use their own choice of framework.

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

¥For example, let's say you have the following set of pages that you would like to split up:

  • /blog/* 用于所有博客文章

    ¥/blog/* for all blog posts

  • /dashboard/* 用于用户登录到仪表板时的所有页面

    ¥/dashboard/* for all pages when the user is logged-in to the dashboard

  • /* 用于其他区域未覆盖的其余网站

    ¥/* for the rest of your website not covered by other zones

借助多区域支持,你可以创建三个应用,它们都在同一域上提供服务,并且对用户来说看起来相同,但你可以独立开发和部署每个应用。

¥With Multi-Zones support, you can create three applications that all are served on the same domain and look the same to the user, but you can develop and deploy each of the applications independently.

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

¥Navigating between pages in the same zone will perform soft navigations, a navigation that does not require reloading the page. For example, in this diagram, navigating from / to /products will be a soft navigation.

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

¥Navigating from a page in one zone to a page in another zone, such as from / to /dashboard, will perform a hard navigation, unloading the resources of the current page and loading the resources of the new page. Pages that are frequently visited together should live in the same zone to avoid hard navigations.

如何定义区域

¥How to define a zone

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

¥A zone is a normal Next.js application where you also configure an assetPrefix to avoid conflicts with pages and static files in other zones.

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

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

¥Next.js assets, such as JavaScript and CSS, will be prefixed with assetPrefix to make sure that they don't conflict with assets from other zones. These assets will be served under /assetPrefix/_next/... for each of the zones.

处理未路由到另一个更具体区域的所有路径的默认应用不需要 assetPrefix

¥The default application handling all paths not routed to another more specific zone does not need an assetPrefix.

在 Next.js 15 之前的版本中,你可能还需要额外的重写来处理静态资源。这在 Next.js 15 中不再是必要的。

¥In versions older than Next.js 15, you may also need an additional rewrite to handle the static assets. This is no longer necessary in Next.js 15.

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

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

¥How to route requests to the right zone

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

¥With the Multi Zones set-up, you need to route the paths to the correct zone since they are served by different applications. You can use any HTTP proxy to do this, but one of the Next.js applications can also be used to route requests for the entire domain.

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

¥To route to the correct zone using a Next.js application, you can use rewrites. For each path served by a different zone, you would add a rewrite rule to send that path to the domain of the other zone. For example:

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

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

¥destination should be a URL that is served by the zone, including scheme and domain. This should point to the zone's production domain, but it can also be used to route requests to localhost in local development.

很高兴知道:URL 路径对于区域应该是唯一的。例如,两个区域尝试为 /blog 提供服务将产生路由冲突。

¥Good to know: URL paths should be unique to a zone. For example, two zones trying to serve /blog would create a routing conflict.

路由请求使用中间件

¥Routing requests using middleware

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

¥Routing requests through rewrites is recommended to minimize latency overhead for the requests, but middleware can also be used when there is a need for a dynamic decision when routing. For example, if you are using a feature flag to decide where a path should be routed such as during a migration, you can use middleware.

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

区域之间的链接

¥Linking between zones

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

¥Links to paths in a different zone should use an a tag instead of the Next.js <Link> component. This is because Next.js will try to prefetch and soft navigate to any relative path in <Link> component, which will not work across zones.

共享代码

¥Sharing code

组成不同区域的 Next.js 应用可以存在于任何存储库中。但是,将这些区域放在 monorepo 中通常很方便,以便更轻松地共享代码。对于位于不同存储库中的区域,还可以使用公共或私有 NPM 包共享代码。

¥The Next.js applications that make up the different zones can live in any repository. However, it is often convenient to put these zones in a monorepo to more easily share code. For zones that live in different repositories, code can also be shared using public or private NPM packages.

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

¥Since the pages in different zones may be released at different times, feature flags can be useful for enabling or disabling features in unison across the different zones.

对于 Vercel 上的 Next.js 应用,你可以使用 monorepo 和单个 git push 部署所有受影响的区域。

¥For Next.js on Vercel applications, you can use a monorepo to deploy all affected zones with a single git push.

服务器操作

¥Server Actions

当将 服务器操作 与多区域一起使用时,你必须明确允许面向用户的来源,因为面向用户的域可能为多个应用提供服务。在你的 next.config.js 文件中,添加以下几行:

¥When using Server Actions with Multi-Zones, you must explicitly allow the user-facing origin since your user facing domain may serve multiple applications. In your next.config.js file, add the following lines:

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

请参阅 serverActions.allowedOrigins 了解更多信息。

¥See serverActions.allowedOrigins for more information.