React技术栈Monorepo公共配置放置及路径配置方案咨询
目录结构
project │ README.md │ .gitignore │ package.json │ └───packages │ │ │ └───A │ │ │ package.json │ │ │ index.html │ │ └───src │ │ │ └───B │ │ │ package.json │ │ │ index.html │ │ └───src │ │ │ └───common │ │ package.json │ └───src └───.git │ └───.husky
我希望将A、B和common包实现为monorepo。由于它们均使用React,可以应用相同的lint规则(.eslintrc.js、.prettier.json),同时babel、webpack和ts相关配置也完全一致(使用相同的插件和加载器)。因此,我希望将lint配置以及babel.config.json、tsconfig.json、webpack.config.js等文件放在根工作区。
但我不清楚如何设置一些路径相关的配置,例如别名:
// babel.config.json "plugins": [ [ "module-resolver", { "root": [""], "alias": { "@": "./src/", "@assets": "./src/assets/", "@components": "./src/components/", "@pages": "./src/pages/", "@services": "./src/services/" } } ] ]
这种情况下,通常是否需要为每个包单独配置webpack.config.js或tsconfig.json的"paths"字段?
不需要为每个包单独编写完整的webpack/tsconfig配置文件,通过根配置复用+动态路径处理即可实现统一管理,具体方案如下:
1. Babel 别名统一配置
修改根目录的babel.config.json,利用module-resolver的cwd选项,让别名解析自动适配每个子包的目录:
// 根目录 babel.config.json "plugins": [ [ "module-resolver", { "root": ["./src"], "alias": { "@": "./src", "@assets": "./src/assets", "@components": "./src/components", "@pages": "./src/pages", "@services": "./src/services" }, "cwd": "packagejson" // 关键:基于子包的package.json目录解析路径 } ] ]
设置cwd: "packagejson"后,module-resolver会自动识别当前执行环境所在的子包目录,让@等别名指向对应子包的src文件夹,无需每个包单独配置。
2. TypeScript Paths 复用配置
根目录创建基础tsconfig.json,子包通过继承并覆盖baseUrl实现路径适配:
- 根目录
tsconfig.json:
{ "compilerOptions": { "target": "ESNext", "module": "ESNext", "jsx": "react-jsx", // 其他通用编译配置 "paths": { "@/*": ["./src/*"], "@assets/*": ["./src/assets/*"], "@components/*": ["./src/components/*"], "@pages/*": ["./src/pages/*"], "@services/*": ["./src/services/*"] } }, "exclude": ["node_modules"] }
- 子包(如
packages/A/tsconfig.json):
{ "extends": "../../tsconfig.json", "compilerOptions": { "baseUrl": "./src" // 覆盖为当前子包的src目录 }, "include": ["./src/**/*"] }
通过继承+局部覆盖,TypeScript会自动基于子包的baseUrl解析paths规则,实现别名的正确指向。
3. Webpack 别名动态配置
根目录编写通用webpack.config.js,利用process.cwd()获取当前执行的子包目录,动态设置别名:
// 根目录 webpack.config.js const path = require('path'); module.exports = (env, argv) => { const packageRoot = process.cwd(); // 执行webpack时的当前子包目录 return { // 其他通用配置(入口、loader、插件等) resolve: { alias: { '@': path.resolve(packageRoot, './src'), '@assets': path.resolve(packageRoot, './src/assets'), '@components': path.resolve(packageRoot, './src/components'), '@pages': path.resolve(packageRoot, './src/pages'), '@services': path.resolve(packageRoot, './src/services') } } }; };
然后在子包的package.json中添加脚本,指定使用根配置:
// packages/A/package.json "scripts": { "build": "webpack --config ../../webpack.config.js", "dev": "webpack serve --config ../../webpack.config.js" }
这样webpack执行时会自动适配当前子包的路径,无需每个包单独编写配置。
4. ESLint 适配别名解析
根目录的.eslintrc.js通过配置import/resolver,让ESLint识别Babel配置的别名:
// 根目录 .eslintrc.js module.exports = { // 其他lint规则配置 settings: { 'import/resolver': { 'babel-module': {} } } };
只要Babel别名配置正确,ESLint就能自动识别路径,无需额外配置。
内容的提问来源于stack exchange,提问作者yjlee

