前情提要
半年前,为了解决万恶的百度地图内存泄露的问题,组里的前端被我拆分成了两个独立的项目,地图作为单独的前端服务部署,主项目通过 iFrame 的方式引入地图服务,才算真正解决了地图内存泄露的问题
半年后,项目终于快要交付了,2.0 版本迭代也提上了日程,于是我想到,能不能把这两个项目再合起来,类似微服务一样来管理,也就是说终于要开始接触 monorepo 这玩意了
技术选型
先是技术选型,monorepo 目前好像也就 yarn 的 lerna、巨硬的 rush、pnpm 三种相对流行的解决方案
rush 巨硬家的很多东西给人的感觉就是,玩具,玩腻了就丢,留下一堆坑给开发者,不考虑
lerna lerna 相对老一点,好像也没什么缺点
pnpm pnpm 给我的感觉就是,js 在走 java 的路了,node_modules 变成中央仓库了,从概念上来看好像不错,拿来玩玩
单个项目改造
要想从 yarn 切换到 pnpm,首先肯定要看看删除 yarn.lock 换成 pnpm install 之后,项目能不能正常跑起来
得益于项目的依赖版本还不算太老,pnpm install 完之后,run dev 成功没跑起来(
问题不大,报错一个一个解决,主要涉及到以下几点
webpack-cli 报错 这个还好,很容易找到问题,webpack-cli 版本低了要升级一下,我是从
^4.8.0
升级到了^4.10.0
部分幽灵依赖报错 老生长谈了,把 lodash、zrender 等几个没安装就拿来用的依赖加上就好了
webpack acron 别名配置 忘记这个别名配置是用来解决什么问题的了,反正也是个幽灵依赖,加上就行了,注意版本号
pnpm monorepo 项目搭建
pnpm 初始化一个 monorepo 项目很简单,不啰嗦,但是把两个独立的项目放在 monorepo 根目录下,作为子项目之后,问题就多了
- tsconfig 配置 ts 和 eslint 的配置本来就是老大难了,monorepo 想要把一些公共配置提升到根目录就更难了。主要是注意路径别名的配置、baseUrl 的设置等。看看下面的示例吧
// 根目录 tsconfig,
{
"compilerOptions": {
"jsx": "react",
"esModuleInterop": true,
"sourceMap": true,
"resolveJsonModule": true,
"target": "es5",
"lib": ["es5", "es2015", "es2016", "dom", "es2015.promise"],
"module": "ESNext",
"moduleResolution": "node",
"allowJs": true,
"strict": true,
"noImplicitAny": false,
"downlevelIteration": true,
"forceConsistentCasingInFileNames": true,
"rootDir": "./",
"baseUrl": "./",
"outDir": "./dist",
},
"include": ["packages/*/src"]
}
/**
* 子目录 tsconfig,先 extends,然后要用 baseUrl 指明当前文件所处的相对路径
* 再配置路径别名,不然路径别名就是相对根目录的了
* 注意子项目的配置一定要有 include 指明当前子项目路径,不然打包时 ts 会把根目录作为项目路径
*/
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist",
"paths": {
"@src/*": [
"./src/*"
]
}
},
"include": ["./src", "./postcss.config.js", "tailwind.config.js"]
}
- eslint 配置 eslint 配置简直就是永远的痛啊,太难了。这里主要是注意,alias map 的路径是当前 IDE 自行决定的,所以
vscode
和webstorm
有时候表现会不一致!为了解决这个问题头发都掉了好多,其实解决方法也简单,就是在.eslintrc.js
里用path.resolve(__dirname, './src')
来指明别名路径,如下
// 子项目 eslint 配置
const path = require('path');
module.exports = {
// 继承规则
extends: '../../.eslintrc.js',
overrides: [
{
// 注意 overrides 需要配置 files 属性
files: ['*.tsx', '*.ts', '*.jsx', '*.js'],
settings: {
// 自动检查 react 版本
react: {
version: 'detect',
},
// 配置路径别名
'import/resolver': {
alias: {
map: [['@src', path.resolve(__dirname, './src')]],
extensions: ['.tsx', '.ts', '.jsx', '.js'],
},
},
},
},
],
};
- tailwind class 失效 原因暂时不明,推测是因为启动脚本在根目录,tailwind 在 js 入口组件里引入
import 'tailwindcss/tailwindcss.css'
的时候,目录指向不对,所以引入不了。解决办法:新建一个 css,然后在入口组件里引入这个 css 就行
,内容就是引入 tailwind 的基本 css,如下
@tailwind base;
@tailwind components;
@tailwind utilities;
prettier 配置 这个简单,一般也只需要在根目录配置一下
.prettierrc
就行了.npmrc 管理依赖提升问题 这个配置没做,但是以后可能会用得上,可以解决一些依赖问题
总结
项目配置基本上都是一劳永逸的事情,所以一些东西也很容易忘记,而且这些前端工具一天一个样,只能说难搞,希望以后能有个统一简单的工程化方案吧