基于Next.js与Turborepo实现共享页面方案
问题
我用Turborepo搭建了一个包含两个Next.js应用的monorepo,目录结构如下:
base |---apps | |---editor | | |---pages | | |---index.js // 两个应用的该文件内容不同 | | |---anotherPage.js // 两个应用的该文件内容相同 | | | |---etsy | |---pages | |---index.js // 两个应用的该文件内容不同 | |---anotherPage.js // 两个应用的该文件内容相同 | |---packages
Next.js自带自动路由功能,访问url/anotherPage会自动对应到pages/anotherPage.js。现在两个应用之间有大量共享页面,以及pages/api下的共享API,想把这些共享内容移到packages目录下,同时保留自动路由和API路由功能,该怎么做?
解决方案
下面是几种可落地的实现方式,均能保留Next.js的自动路由特性:
方法1:用符号链接直接映射共享路由(最省心)
直接通过文件系统符号链接,让Next.js的自动路由系统“识别”到packages里的共享页面/API:
- 在
packages下创建shared-routes包,完全复刻Next.js的pages目录结构:
packages |---shared-routes | |---pages | |---anotherPage.js // 共享页面 | |---api | |---sharedApi.js // 共享API
- 给每个应用的pages目录创建指向共享文件的符号链接:
- Mac/Linux:在
apps/editor/pages下执行ln -s ../../../packages/shared-routes/pages/anotherPage.js ./anotherPage.js - Windows:用
mklink ./anotherPage.js ../../../packages/shared-routes/pages/anotherPage.js(需管理员权限)
- Mac/Linux:在
- 嫌手动操作麻烦?可以在Turborepo根目录的
package.json中添加脚本,一次性给所有应用创建链接:
{ "scripts": { "link-shared-routes": "cd apps/editor/pages && ln -s ../../../packages/shared-routes/pages/anotherPage.js ./anotherPage.js && cd ../../etsy/pages && ln -s ../../../packages/shared-routes/pages/anotherPage.js ./anotherPage.js" } }
方法2:用包导出+Next.js编译配置(规范的monorepo做法)
这种方式无需文件链接,完全靠包管理和Next.js编译配置实现,符合monorepo最佳实践:
- 在
packages/shared-routes的package.json中配置导出规则,让应用能精准导入共享内容:
{ "name": "@repo/shared-routes", "exports": { "./pages/*": "./pages/*", "./api/*": "./pages/api/*" }, "type": "module" }
- 给每个Next.js应用的
next.config.js添加transpilePackages配置,告诉Next.js需要编译这个共享包(避免ES模块语法报错):
/** @type {import('next').NextConfig} */ const nextConfig = { transpilePackages: ['@repo/shared-routes'], } module.exports = nextConfig
- 在应用的pages目录下创建“转发文件”,比如
apps/editor/pages/anotherPage.js只需写:
// 导出共享页面的默认组件及所有路由相关方法(如getStaticProps、getStaticPaths) export { default, getStaticProps, getStaticPaths } from '@repo/shared-routes/pages/anotherPage'
- 共享API的处理逻辑完全一致,比如
apps/editor/pages/api/sharedApi.js:
export { default } from '@repo/shared-routes/api/sharedApi'
方法3:自定义Next.js路由映射(进阶场景)
如果需要更灵活的路由控制,可自定义Next.js的路由解析逻辑,但需手动维护映射规则,适合少量共享路由的场景:
- 在应用的
next.config.js中使用rewrites或redirects配置路由映射,将请求指向共享包中的内容。 - 或使用
@next/mdx等插件扩展路由,但复杂度较高,不推荐用于大量共享路由的场景。
注意事项
- 确保共享包的依赖版本与应用一致,避免编译错误。
- 使用方法2时,转发文件需导出所有必要的路由相关函数,否则会丢失Next.js的路由特性。
- Turborepo的缓存机制会自动处理共享包的变更,修改共享路由后所有应用会同步更新。
内容的提问来源于stack exchange,提问作者Vipul Rajan
相关产品推荐
相关产品推荐

