在Turborepo+shadcn/ui的Next.js Monorepo中配置可复用组件
Monorepo 中 shadcn/ui 可复用组件跨应用复用问题解决
问题描述
已按照 shadcn/ui 指导完成 Monorepo 配置,但遇到核心问题:用 shadcn/ui 构建的可复用组件该存放在哪里?例如 apps 目录下的多数应用会用到结构相似、仅背景和标题等细节不同的落地页组件,希望将这类组件统一放在 packages/shared 目录中。参考 v0.dev 方案配置后,无法在 apps 目录的应用中成功导入这些组件。请问该如何解决?是否必须将组件复制到每个应用,还是有更优方式?
当前配置信息
packages/shared/package.json:
{ "name": "@workspace/shared", "version": "0.0.1", "type": "module", "license": "MIT", "scripts": { "lint": "eslint ." }, "dependencies": { "@workspace/ui": "workspace:*", "lucide-react": "0.456.0", "next-themes": "^0.4.3", "next": "^15.1.0", "react": "^19.0.0", "react-dom": "^19.0.0" }, "devDependencies": { "@turbo/gen": "^2.2.3", "@types/node": "^22.9.0", "@types/react": "18.3.0", "@types/react-dom": "18.3.1", "@workspace/eslint-config": "workspace:*", "@workspace/typescript-config": "workspace:*", "@workspace/ui": "workspace:*", "react": "^18.3.1", "tailwindcss": "^3.4.14", "typescript": "^5.6.3" }, "exports": { "./components/*": "./components/*.tsx" } }
根目录 package.json:
{ "name": "monorepo", "version": "1.0.0", "private": true, "scripts": { "build": "turbo build", "dev": "turbo dev", "lint": "turbo lint", "format": "prettier --write \"**/*.{ts,tsx,md}\"" }, "devDependencies": { "@workspace/eslint-config": "workspace:*", "@workspace/typescript-config": "workspace:*", "@workspace/shared": "workspace:*", "prettier": "^3.2.5", "turbo": "^2.3.0", "typescript": "5.5.4" }, "packageManager": "pnpm@9.12.3", "engines": { "node": ">=20" } }
问题修复与最优方案
1. 修正 exports 配置,支持组件递归导入
当前 @workspace/shared 的 exports 仅支持单文件导入,无法覆盖嵌套子目录的组件,调整为:
"exports": { "./components": "./components/index.ts", "./components/*": "./components/*.tsx", "./components/**/*": "./components/**/*.tsx" }
同时建议在 packages/shared/components 下创建 index.ts,统一导出所有可复用组件,简化应用侧导入:
// packages/shared/components/index.ts export { default as LandingPage } from './landing-page/LandingPage'; export { default as LandingHeader } from './landing-page/Header';
2. 统一依赖版本,消除冲突
@workspace/shared 中同时存在 React 19 和 React 18 依赖,会导致版本冲突,需统一版本:
- 删除
devDependencies中的react: ^18.3.1,保持dependencies中 React 版本一致(或根据项目实际统一为 18.x) - 确保
@workspace/ui等内部包的依赖版本与shared包、apps 应用完全匹配
3. 在应用侧正确安装依赖
根目录仅声明 @workspace/shared 为开发依赖是不够的,需在每个 apps 应用中添加生产依赖:
# 在 apps/目标应用目录下执行 pnpm add @workspace/shared@workspace:*
4. 检查 TypeScript 配置一致性
- 根目录
tsconfig.json需添加对packages/shared的引用:
{ "references": [{ "path": "./packages/shared" }] }
packages/shared的tsconfig.json需确保编译配置正确:
{ "compilerOptions": { "jsx": "react-jsx", "module": "ESNext", "moduleResolution": "bundler", "esModuleInterop": true, "skipLibCheck": true, "strict": true, "declaration": true, "declarationMap": true, "outDir": "./dist" }, "include": ["components/**/*", "index.ts"], "exclude": ["node_modules"] }
5. 验证导入路径正确性
应用侧导入组件时使用以下两种合法路径:
// 方式1:通过统一入口导入 import { LandingPage } from '@workspace/shared/components'; // 方式2:直接导入单个组件 import LandingPage from '@workspace/shared/components/landing-page/LandingPage';
最优实践总结
不需要复制组件到每个应用,推荐的复用方式:
- 将通用业务组件(如落地页、通用布局)放在
packages/shared - 将shadcn/ui 基础组件(如 Button、Card)放在
packages/ui - 通过
package.json的exports清晰定义组件导出路径 - 应用侧通过工作区协议安装依赖,实现跨应用组件复用
内容的提问来源于stack exchange,提问作者habib-N19
相关产品推荐
相关产品推荐

