Monorepo:是管理项目代码的一个方式,指在一个项目仓库(repo)中管理多个模块/包(package)
vue3
源码采用Monorepo
管理项目
vue3项目架构
搭建Monorepo环境
1.全局安装pnpm
npm install pnpm -g # 全局安装pnpm
pnpm init -y # 初始化配置文件
创建.npmrc文件:如果某些工具仅在根目录的node_modules时才有效,可以将其设置为true来提升那些不在根目录的node_modules,就是将你安装的依赖包的依赖包的依赖包的…都放到同一级别(扁平化)
shamefully-hoist = true
配置workspace
新建 pnpm-workspace.yaml :将packages下所有的目录都作为包进行管理
packages:
- 'packages/*'
2.安装环境
pnpm install typescript rollup rollup-plugin-typescript2 @rollup/plugin-json @rollup/plugin-node-resolve @rollup/plugin-commonjs minimist execa@4 esbuild -D -w
- typescript vue3使用ts
- rollup 打包工具
- rollup-plugin-typescript2 rollup 和 ts的 桥梁
- @rollup/plugin-json 支持引入json
- @rollup/plugin-node-resolve 解析node第三方模块
- @rollup/plugin-commonjs 将CommonJS转化为ES6Module
- minimist 命令行参数解析
- execa@4 开启子进程
- esbuild
3.ts
初始化:pnpm tsc --init
常用配置文件:
{
"compilerOptions": {
"outDir": "dist", // 输出的目录
"sourceMap": true, // 采用sourcemap
"target": "es2016", // 目标语法
"module": "esnext", // 模块格式
"moduleResolution": "node", // 模块解析方式
"strict": false, // 严格模式
"resolveJsonModule": true, // 解析json模块
"esModuleInterop": true, // 允许通过es6语法引入commonjs模块
"jsx": "preserve", // jsx 不转义
"lib": ["esnext", "dom"], // 支持的类库 esnext及dom
}
}
4.创建模块
reactivity/package.json
{
"name": "@vue/reactivity",
"version": "1.0.0",
"main": "index.js",
"module":"dist/reactivity.esm-bundler.js",
"unpkg": "dist/reactivity.global.js",
"buildOptions": {
"name": "VueReactivity",
"formats": [
"esm-bundler",
"cjs",
"global"
]
}
}
shared/package.json
{
"name": "@vue/shared",
"version": "1.0.0",
"main": "index.js",
"module": "dist/shared.esm-bundler.js",
"buildOptions": {
"formats": [
"esm-bundler",
"cjs"
]
}
}
formats
为自定义的打包格式:
esm-bundler
在构建工具中使用的格式esm-browser
在浏览器中使用的格式cjs
在node
中使用的格式global
立即执行函数的格式
pnpm install @vue/shared@workspace --filter @vue/reactivity
"baseUrl": ".",
"paths": {
"@vue/*": ["packages/*/src"]
}
5.开发环境esbuild打包
"scripts": {
"dev": "node scripts/dev.js reactivity -f global"
}
const { build } = require('esbuild')
const { resolve } = require('path')
const args = require('minimist')(process.argv.slice(2));
const target = args._[0] || 'reactivity';
const format = args.f || 'global';
const pkg = require(resolve(__dirname, `../packages/${target}/package.json`));
const outputFormat = format.startsWith('global')// 输出的格式
? 'iife'
: format === 'cjs'
? 'cjs'
: 'esm'
const outfile = resolve( // 输出的文件
__dirname,
`../packages/${target}/dist/${target}.${format}.js`
)
build({
entryPoints: [resolve(__dirname, `../packages/${target}/src/index.ts`)],
outfile,
bundle: true,
sourcemap: true,
format: outputFormat,
globalName: pkg.buildOptions?.name,
platform: format === 'cjs' ? 'node' : 'browser',
watch: { // 监控文件变化
onRebuild(error) {
if (!error) console.log(`rebuilt~~~~`)
}
}
}).then(() => {
console.log('watching~~~')
})