资讯动态

Next.js Multi Zones 实战指南:用 rewrites 把多个 Next.js 应用聚合成单一域名

发布时间:2026/9/8 22:26:27 来源:尧图企业网站定制
Next.js Multi Zones 实战指南用 rewrites 把多个 Next.js 应用聚合成单一域名【免费下载链接】next.jsThe React Framework项目地址: https://gitcode.com/GitHub_Trending/next/next.jsMulti Zones 是 Next.js 官方向微前端演进的一种落地方式把原本运行在同一个域名下的巨型应用拆解为多个彼此独立、各自负责一批 URL 路径的小型 Next.js 应用zone再由其中一个入口应用借助rewrites把不属于自己的路径转发给对应的 zone。本文以仓库中的 examples/with-zones 官方示例含home与blog两个 zone为骨架讲解 Multi Zones 的拆分解耦思路、rewritesassetPrefix/basePath的实现细节、本地联调方法、部署到单一域名下多个 Vercel 项目的完整流程以及用单元测试预先验证 rewrite 路由逻辑的工程实践。Multi Zones 是什么从一个大应用到一批 zoneMulti Zones 把部署在同一个域名下的一个大型 Next.js 应用重新组织为一组更小的、按路径分工的应用每个应用被称为一个 zone各自只服务一组 URL 路径并独立安装依赖、独立开发、独立构建与独立部署。它的适用场景很典型——当某个应用中存在一批与其余页面几乎无关的页面集合时将这些页面挪到独立 zone就能缩小主应用的体积让构建build时间显著下降移除只在某一个 zone 才需要、却长期拖累主应用的代码各 zone 可以按自身节奏升级、扩容团队边界与发布边界随之清晰。Multi Zones 应用之所以能被用户感知为同一个网站是因为由其中一个 zone 充当入口入口应用的next.config.js用rewrites特性 把某些请求路径代理转发到其他 zone。前提约束是同一个域名下的所有 URL 路径必须在所有 zone 之间全局唯一否则路由归属会产生冲突。示例拆解home与blog两个 zone 的分工本示例由两个完全独立的 Next.js 应用组成目录结构如下examples/with-zones/home主应用 zone负责/、/about等全部未指派给 blog 的路径它把指向 blog 的请求通过rewrites转发出去。examples/with-zones/blog子应用 zone专门负责/blog与/blog/*路径通过assetPrefix保证自身资源与 home 互不冲突。两个应用都有自己的package.json版本号各写各的、依赖独立安装各自的页面代码互不感知。看具体的文件布局home 的路由/对应 home/app/page.tsx/about对应 home/app/about/page.tsx公共头部由 home/components/Header.tsx 提供blog 的路由页面被刻意放在blog/app/blog/子目录中于是路由天然带/blog前缀——blog/app/blog/page.tsx 是博客列表页blog/app/blog/post/[id]/page.tsx 是动态文章详情页blog/app/blog/layout.tsx 定义了 zone 自己的根布局。在示例页面之间你还能看到一条关键约束的体现home 首页用普通a href/blog跳往 blog而 blog 内部用next/link维护/blog、/blog/post/1等相对路径。因为 blog 将assetPrefix设为/blog-static其页面对外链接的前缀依然是/blog而非/blog-static。核心机制入口 zone 用rewrites做请求代理Multi Zones 的路由汇聚完全发生在入口应用 home 的 next.config.js 中const { BLOG_URL } process.env; /** type {import(next).NextConfig} */ const nextConfig { async rewrites() { return [ { source: /blog, destination: ${BLOG_URL}/blog, }, { source: /blog/:path, destination: ${BLOG_URL}/blog/:path, }, { source: /blog-static/_next/:path, destination: ${BLOG_URL}/blog-static/_next/:path, }, ]; }, }; module.exports nextConfig;这段配置体现了 Multi Zones 入口的完整职责业务路径转发/blog与/blog/:path被整体透传给 blog zone。:path是 Next.js rewrite 的通配参数语法含义是匹配一个或多个路径段因此/blog/post/1、/blog/whatever都能命中第二条规则并把捕获到的路径段原样拼到目标地址上。静态资源转发/blog-static/_next/:path被单独转发。浏览器访问被代理回来的 blog 页面时页面 HTML 里引用的_next/static脚本与样式会请求/blog-static/_next/...这条 rewrite 确保这些资源请求也被送回 blog zone由它自己处理。若不转发静态资源blog 页面即使成功返回 HTML也无法在 home 域名下正确加载样式与 JS。目标地址来自环境变量destination拼接的是process.env.BLOG_URL也就是说 home 通过环境变量得知blog zone 部署在哪里。这正是本地与生产可复用的关键同一份配置改变BLOG_URL的值即可指向本机 dev server 或线上部署。需要说明的细节当rewrites()返回一个普通数组时默认规则语义等同于afterFiles先查文件系统/页面再命中 rewriteNext.js 也允许返回{ beforeFiles, afterFiles, fallback }结构来显式控制三个阶段。对本示例来说/blog、/blog-static/...不会与 home 自身页面撞路径因此简单数组形式已足够清晰。单元测试见下文在合并规则时兼容了两种返回形态这从侧面印证了两种写法都被框架支持。Zone 资源隔离assetPrefix与basePath怎么选本示例的实际配置assetPrefix 目录前缀两个 zone 部署在同一域名后浏览器看到的资源 URL 也必须互不冲突。blog zone 的 next.config.js 是这样做的/** type {import(next).NextConfig} */ const nextConfig { assetPrefix: /blog-static, }; module.exports nextConfig;配合把页面放在app/blog/子目录下blog zone 用一套组合拳完成了隔离目录结构提供路由前缀/blog而assetPrefix把 Next.js 生成页面里引用的静态资源路径整体加上了/blog-static前缀如/blog-static/_next/static/chunks/xxx.js。home 的第三条 rewrite 再把/blog-static/_next/:path回发给 blog形成闭环。home 自己没有assetPrefix它产出的_next资源就保持在默认路径与 blog 的/blog-static前缀天然错开。basePath的作用与边界官方文档强调basePath会自动给应用内所有页面加上统一前缀包括相对链接。这意味着如果你把basePath设为/blog那么/会被自动解析为/blog、/about会被解析为/blog/about。正因为basePath对应用内全部页面生效它只适合整个应用所有页面共享同一个前缀的情形。如果很多页面并不共享相同的前缀——例如/home和/blog同处一个 zone——那么更合适的选择是assetPrefix它只给 Next.js 生成的静态资源_next/static等加上独特前缀不影响任何页面路由本身。这也解释了为何本示例的 blog zone 采用assetPrefix并把路由交给目录层级解决而不是依赖basePath去顺带改所有链接——对于 zone 间资源去重、页面路径各自独立维护的场景assetPrefix是更精准的隔离手段。本地运行两个 zone与单一应用不同Multi Zones 意味着多个 Next.js 应用叠加在一个站点上因此每个 app 都拥有自己的依赖并独立运行。用脚手架快速复刻示例在仓库里该示例的入口在 examples/with-zones根package.json仅为占位实际依赖都在home/与blog/两个子目录中。如果要从零开始体验 Multi Zones可借助官方示例引导命令将生成独立的with-zones-app项目目录npx create-next-app --example with-zones with-zones-appyarn create next-app --example with-zones with-zones-apppnpm create next-app --example with-zones with-zones-app分别启动 home 与 blog先在仓库根目录启动/homezone对应端口 3000cd home npm install npm run dev # or cd home yarn yarn dev # or cd home pnpm install pnpm dev启动成功后 home 应用即运行在 http://localhost:3000。再打开一个新的终端启动/blogzone——注意 blog/package.json 的dev脚本显式带了端口参数next dev -p 4000这是为了让两个应用能在本机同时监听而不冲突cd blog npm install npm run dev # or cd blog yarn yarn dev # or cd blog pnpm install pnpm devblog 应用应运行在 http://localhost:4000/blog。本地联调的一点提醒home 的rewrites依赖环境变量BLOG_URL。示例 README 在本地阶段建议直接访问各 zone 自己的地址如4000/blog来独立验证功能如果希望在本机也走单一域名 代理的完整链路即访问localhost:3000/blog由 home 转发到 blog则可以仿照下文部署章节的做法为 home 配置BLOG_URLhttp://localhost:4000后再访问 home 域名下对应路径这与线上 Vercel 的转发行为保持一致。上线前先验证用 Jest 单测锁定 rewrite 逻辑Multi Zones 的路由正确性直接决定站点可用性而 home 仓库为此内置了一套针对next.config.js的单元测试实现在 home/test/next-config.test.ts配套的 Jest 配置见 home/jest.config.js通过next/jest创建测试环境为jsdom匹配./**/*.test.{ts,tsx}。这套测试的思路非常值得借鉴在真实部署之前用 path-to-regexp 模拟 Next.js 的 source→destination 匹配过程match()负责命中sourcecompile()负责把捕获的参数回填进destination从而验证 rewrite 会不会按预期转发、会不会误伤 home 自身的路径。测试的核心断言如下非 blog 路径不被转发/、/blog-not、/blog2均返回undefined即 home 自己处理blog 路径被正确转发到子 zone/blog→https://with-zones-blog.vercel.app/blog/blog/post/1→https://with-zones-blog.vercel.app/blog/post/1blog 静态资源被转发到子 zone/blog-static/_next/static/chunks/chunk.css→https://with-zones-blog.vercel.app/blog-static/_next/static/chunks/chunk.css。注意测试开头便设置了process.env.BLOG_URL https://with-zones-blog.vercel.app说明在 CI 或部署流水线中同样的测试可以换成任意环境值来校验目标。它同时兼容了rewrites()返回数组与返回{ beforeFiles, afterFiles }两种结构也演示了对destination进行主机拆分、参数编译等边界处理。把这类配置逻辑可测试化的做法带到你自己的 Multi Zones 工程里可以在每次调整转发规则后获得快速、确定性的反馈。部署把多个 zone 聚合到同一域名Multi Zones 生产部署的核心诉求是每个 zone 一个独立项目、但共享同一个域名。下文以 Vercel 为例示例 README 的部署章节即围绕 Vercel 展开借助其monorepo多仓库子目录支持为每个 app 各创建一个项目。第一步先部署 blog 子 zone将示例推送到 Git 托管平台并导入 Vercel 后在导入流程中不选择仓库根目录而是选中blog目录作为项目源码目录注意按示例说明应不要从 home 开始先部署 blog因为 home 的 rewrite 目标依赖 blog 的线上地址。点击 Continue 完成导入。随后把 Vercel 分配给该项目blog zone的域名地址复制出来写入home/.env并提交到仓库形式如下# 将此 URL 替换为你的 blog 应用的地址 BLOG_URLhttps://with-zones-blog.vercel.app这一步相当于把 blog zone 的线上坐标注入 homehome 的rewrites()运行时读到的正是这个变量。第二步再部署 home 主 zone对同一个仓库再次走一遍导入流程这次选择home目录home/.env 中已配置BLOG_URL因此它知道要把/blog请求发往何处当 home 应用部署完成后两个应用就应该能在同一个域名下协同工作用户访问https://你的域名/blog时home 通过rewrites把请求代理给独立的 blog 部署而 blog 页面引用的/blog-static/_next/...资源也经同一条链路被送回 blog 处理。之后的更新与回滚仓库后续的任何提交都会同时触发与其关联的两个 Vercel 项目的部署Vercel 依据 monorepo 识别出哪些子目录发生了变化两个 zone 可各自拥有独立的部署与回滚记录这正是 Multi Zones 相比单体应用在发布边界上的优势所在。落地要点与常见误区回顾整个示例把 Multi Zones 落到自己项目时建议把握以下几点路径全局唯一是铁律。所有 zone 的路由加起来必须互不重叠入口 zone 的 rewrite 规则要精确圈定哪些前缀属于哪些子 zone否则会出现请求误转或永久转发的路由黑洞。选对资源隔离手段整个应用共享同一前缀时用basePath最省事页面前缀不统一、只想隔离_next静态资源时用assetPrefix。示例中的 blog zone 正是app/blog目录承担路由前缀 assetPrefix: /blog-static承担资源前缀的组合实现且必须配套入口 zone 对/blog-static/_next/:path的静态资源转发缺一条链路页面就会有 HTML、没样式。目标地址用环境变量驱动。BLOG_URL这类配置把 home 与 blog 的耦合降到最低本地指向localhost:4000、预发指向预发部署、线上指向线上域名next.config.js一行不改。把转发规则变成可测试的代码。参考 home/test/next-config.test.ts用path-to-regexp直接对配置做单测能提前捕获误改路由这类回归是低成本高回报的防护网。多 zone 意味着每个 app 都独立安装依赖、独立监听端口与独立部署本地联调时务必注意端口错开如本示例 blog 用next dev -p 4000CI/CD 里则要按子目录分别构建。【免费下载链接】next.jsThe React Framework项目地址: https://gitcode.com/GitHub_Trending/next/next.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价