解决monorepo场景下子包作为依赖项在开发和生产暴露文件的问题
# 前言
在
monorepo
场景下包和包之间相互存在依赖
关系是很常见的问题,但这同样会暴露出一个问题:代码上线之后我们肯定是将打包好的代码发布到npm
上而不会将全部源码发布上去,那么问题来了,子包的package.json
里的暴露项配置我们到底是配置打包后
的目录还是配置源码
目录呢?
# 问题解析
产生这个问题的原因很简单,就是生产阶段引用的是打包后的代码,而本地开发阶段需要的是实时更新的代码,也就是我们的源码。如何在这两者之间做好权衡是
monorepo
架构必须考虑的一个问题
# 解决办法
首先正常情况下,我们配置子包会这么配
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.cjs"
},
},
1
2
3
4
5
6
2
3
4
5
6
这样配置指向我们dist
文件,也就是构建后的文件。这样开发者在使用这个包的时候直接用包名引入就会链到dist
文件夹里去。
但是很明显, 这样的配置是无法满足我们的开发阶段的。开发阶段需要引入的肯定是源码,而不是构建后的产物,不然每改动一下就要重新构建子包,这不是纯找罪受吗?
# 解决办法一
暴露多条链路,使用方根据环境不同重写引入的别名。
// 子包的package.json
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.cjs"
},
"./src/index": "./src/index.ts"
},
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
可以看到,我们在子包中既配置了dist
目录暴露出去同时也配置了源码路径暴露出去,这个时候主包需要通过别名
来重写引入路径达到目的
// 主包 vite.config.js
resolve: {
alias: {
'@': path.join(__dirname, './src'),
'@itachi3/nc-h5-components': isProduction ? '@itachi3/nc-h5-components' : '@itachi3/nc-h5-components/src/index', // 兼容本地和开发环境
'@itachi3/ncaxios': isProduction ? '@itachi3/ncaxios' : '@itachi3/ncaxios/src/index',
},
},
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
通过这样配置之后,开发环境我们使用的源码,而生产环境则就会使用构建后的产物。
# 解决办法二
同样也是改写package.json
,但这个方法是通过脚本的形式去改,让子包在build
阶段去自动的把暴露项修改成构建产物
// util/update_package.js
const { readFileSync, writeFileSync } = require('fs')
const path = require('path')
const pkgPath = path.resolve(__dirname, '../package.json')
const pkgContent = JSON.parse(readFileSync(pkgPath, 'utf8'))
pkgContent.exports = {
'.': {
import: './dist/index.js',
},
'./styles': './dist/styles/index.css',
'./types': './dist/types/base.d.ts',
}
writeFileSync(pkgPath, JSON.stringify(pkgContent, '', '\t'), {
encoding: 'utf8',
})
console.log('[package] 修改package.json 文件成功')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
这样在每次build
子包前执行一下这个命令,就可以了。主包无需做修改。
# 总结
两种解决办法都是需要修改子包的package.json
,第一种方法利用了配置引入别名的优势,而第二种方法则是简单粗暴的去修改子包的暴露项。可自行选择使用哪种方法
编辑 (opens new window)
上次更新: 2024/01/08, 15:37:55