Appearance
搭建 Monorepo 环境
Vue3 中使用 pnpm workspace 来实现 monorepo (pnpm-'https://pnpm.io/') 是快速、节省磁盘空间的包管理器。主要采用符号链接的方式管理模块)
全局安装 pnpm
bash
# 全局安装pnpm
npm install pnpm -g
# 初始化配置文件
pnpm init -y
1
2
3
4
2
3
4
创建.npmrc
文件
- npm 的特点 bootstarp - animate.css 不用重新安装 animate.css (幽灵依赖)
shamefully-hoist = true
1
这里您可以尝试一下安装 Vue3
, pnpm install vue@next
此时默认情况下 vue3
中依赖的模块不会被提升到 node_modules
下。 添加羞耻的提升可以将 Vue3,所依赖的模块提升到 node_modules
中
配置 workspace
新建 pnpm-workspace.yaml
javascript
packages:
- 'packages/*'
1
2
2
将 packages 下所有的目录都作为包进行管理。这样我们的 Monorepo 就搭建好了。确实比 lerna + yarn workspace 更快捷
环境搭建
打包项目 Vue3 采用 rollup 进行打包代码,安装打包所需要的依赖
依赖 | - |
---|---|
typescript | 在项目中支持 Typescript |
rollup | 打包工具 |
rollup-plugin-typescript2 | rollup 和 ts 的 桥梁 |
@rollup/plugin-json | 支持引入 json |
@rollup/plugin-node-resolve | 解析 node 第三方模块 |
@rollup/plugin-commonjs | 将 CommonJS 转化为 ES6Module |
minimist | 命令行参数解析 |
execa@4 | 开启子进程 |
安装 rollup 模块
bash
pnpm install typescript rollup rollup-plugin-typescript2 @rollup/plugin-json @rollup/plugin-node-resolve @rollup/plugin-commonjs minimist execa@4 esbuild -D -w
1
初始化 TS
bash
pnpm tsc --init
1
先添加些常用的 ts-config 配置,后续需要其他的在继续增加
json
{
"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
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
创建模块
我们现在packages
目录下新建两个 package,用于下一章手写响应式原理做准备
- reactivity 响应式模块
- shared 共享模块
所有包的入口均为src/index.ts
这样可以实现统一打包
reactivity/package.json
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"
]
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
shared/package.json
json
{
"name": "@vue/shared",
"version": "1.0.0",
"main": "index.js",
"module": "dist/shared.esm-bundler.js",
"buildOptions": {
"formats": [
"esm-bundler",
"cjs"
]
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
formats 为自定义的打包格式,有 esm-bundler 在构建工具中使用的格式、esm-browser 在浏览器中使用的格式、cjs 在 node 中使用的格式、global 立即执行函数的格式
bash
pnpm install @vue/shared@workspace --filter @vue/reactivity
1
配置 ts 引用关系
tsconfig.json
javascript
"baseUrl": ".",
"paths": {
"@vue/*": ["packages/*/src"]
}
1
2
3
4
2
3
4
开发环境 esbuild 打包

解析用户参数
package.json
json
"scripts": {
"dev": "node scripts/dev.js reactivity -f global"
}
1
2
3
2
3
新建目录下 scripts/dev.js
javascript
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~~~')
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37