以pnpm构建monorepo
// 新建项目文件夹
mkdir my-vue3 && mkdir my-vue3
// 使用pnpm项目初始化
pnpm init
搭建my-vue3项目基本结构
├── package.json
├── packages # 多子项目的目录
│ ├── vue # 打包、测试实例、项目整体入口模块
│ │ ├── src/*
│ │ └── package.json
│ ├── reactivity # 响应性模块
│ │ ├── src/*
│ │ └── package.json
│ ├── shared # 共享公共方法模块
│ │ ├── src/*
│ │ └── package.json
├── scripts #存放项目通用编译脚本
└── pnpm-workspace.yaml #monorepo项目配置文件
上面的项目结构并没有包含所有的vue项目目录,在后续的开发中,会逐渐增减。
需要注意每一个包目录里面也需要一个 package.json 文件进行声明这是一个 NPM 包目录。所以我们需要进入每个包目录进行初始一个 package.json 文件。以 vue 包为例,我们进入到 vue 目录底下初始化一个 package.json 文件,更改包名:@my-vue3/vue。文件内容如下:
{
"name": "@my-vue3/vue",
"version": "0.0.1",
"description": "",
"main": "index.ts",
}
配置pnpm的monorepo工作区
创建pnpm-workspace.yaml,进行 monorepo 的项目配置
packages:
- packages/*
仓库项目内的包相互调用
@my-vue3/vue需要调用@my-vue3/reactivity,就需要把它安装到根目录下的node_modules目录中
// -w 表示安装到共公模块的 packages.json 中,也就是根目录下的 packages.json。
pnpm install @my-vue3/reactivity -w
TS配置
pnpm add -D typescript @types/node -w
{
"compilerOptions": {
"outDir": "dist", // 指定输出目录
"target": "es2018", // 目标语言的版本
"module": "esnext", // 生成代码的模板标准
"baseUrl": ".", // 解析非相对模块的基地址,默认是当前目录
"sourceMap": false, // 是否生成相应的Map映射的文件,默认:false
"moduleResolution": "node", // 指定模块解析策略,node或classic
"allowJs": false, // 是否允许编译器编译JS,JSX文件
"strict": true, // 是否启动所有严格检查的总开关,默认:false,启动后将开启所有的严格检查选项
"noUnusedLocals": true, // 是否检查未使用的局部变量,默认:false
"resolveJsonModule": true, // 是否解析 JSON 模块,默认:false
"allowSyntheticDefaultImports": true, // 是否允许从没有默认导出的模块中默认导入,默认:false
"esModuleInterop": true, // 是否通过为所有导入模块创建命名空间对象,允许CommonJS和ES模块之间的互操作性,开启改选项时,也自动开启allowSyntheticDefaultImports选项,默认:false
"removeComments": false, // 删除注释
"rootDir": ".", // 指定输出文件目录(用于输出),用于控制输出目录结构
"types": [],
"paths": { // 路径映射,相对于baseUrl
"@my-vue3/*": ["packages/*/src"]
}
},
"include": ["packages/*/src"]
}
rollup配置
pnpm add -D rollup-plugin-typescript2 tslib @rollup/plugin-node-resolve @rollup/plugin-commonjs -w
创建rollup.config.js文件
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import typescript from 'rollup-plugin-typescript2'
/**
* 默认导出一个数组,数组的每一个对象都是一个单独的导出文件配置,详细可查:https://www.rollupjs.com/guide/big-list-of-options
*/
export default [
{
// 入口文件
input: 'packages/vue/src/index.ts',
// 打包出口
output: [
// 导出 iife 模式的包
{
// 开启 SourceMap
sourcemap: true,
// 导出的文件地址
file: './packages/vue/dist/vue.js',
// 生成的包格式:一个自动执行的功能,适合作为<script>标签
format: 'iife',
// 变量名
name: 'Vue'
}
],
// 插件
plugins: [
// ts 支持
typescript(),
// 模块导入的路径补全
resolve(),
// 将 CommonJS 模块转换为 ES2015
commonjs()
]
}
]
并在package.json新增一个scripts:
"build": "rollup -c -w"
然后从packages/vue/src/index.ts中导出一个变量,在执行npm run bulid,代码如下图所示,则打包成功
引入代码格式工具
pnpm add -D -w eslint @antfu/eslint-config
新建.eslintrc文件,并写入以下内容:
{
"extends": "@antfu"
}
因为我使用的webstorm,以下是我的配置截图:
测试
此时我们可以在vue/src/index.ts中导出一个变量
export const name = 'echo'
然后运行命令npm run build即可在vue/dist文件夹下看到编译后的结果
var Vue = (function (exports) {
'use strict';
const name = 'echo';
exports.name = name;
return exports;
})({});
//# sourceMappingURL=vue.js.map
总结
以上内容完成后,为我们后续源码的学习提供了学习的开发环境。
感谢
本系列文章的撰写参考了《vue.js设计与实现》、发表在掘金上的系列文章《vue3 源码学习,实现一个 mini-vue》,特此感谢在我学习vue路上给予的帮助。