vue3.0的 monorepo模式
Monorepo 是什么?简单的来说,Monorepo 的核心观点是所有的项目在一个代码仓库中。这并不是说代码没有组织都放在 ./src 文件夹里面,二是在一个packages文件夹下分割成一个个相对独立的项目,在vue3.0中就是将各个功能单独抽离出一个个单独的模块,各自打包,又能互相引用。vue2中是只打一个包。类似于最终的效果vue3.0的打包效果:下面我们来大致实现下整个 monorepo
Monorepo 是什么?
简单的来说,Monorepo 的核心观点是所有的项目在一个代码仓库中。这并不是说代码没有组织都放在 ./src 文件夹里面,二是在一个packages文件夹下分割成一个个相对独立的项目,在vue3.0中就是将各个功能单独抽离出一个个单独的模块,各自打包,又能互相引用。vue2中是只打一个包。
类似于
最终的效果vue3.0的打包效果:
下面我们来大致实现下整个 monorepo模式的打包过程,大致了解下这种模式
1.安装需要的插件
yarn add typescript rollup rollup-plugin-typescript2 @rollup/plugin-node-resolve @rollup/plugin-json execa --ignore-workspace-root-check(忽略工作空间)因为monorepo方式只支持yarn
依次插件的功能:
支持typeScript
1.打包工具
2.rollup和ts的桥梁
3.解析node第三方模块
4.支持引入json
5.开启子进程方便执行命令
2.简单讲下目录
shared中的package 和reactivity差不多(名字对应换下就行),主要有两个参数 buildOptions 这个参数 名字自定义的打包的时候取获取配置就行,这个后面说
src下的index.ts :const shared = {} export { shared} 没什么东西
dist 文件夹忽略这是我们打包出来的结果
build.js 全局打包,这个打包命令就是一次性讲packages中的各模块分别单独打包
dev.js 是单个模块打包
3.我们看下build.js
- 总结下面的带来来说就是干了几件事
- 1.通过fs模块找到packages下的几个可以打包的目标文件夹名字的数组
- 2.通过runParallel方法,依次调用build并行打包
- 3.build方法中其实就用到了execa开启子进程使用rollup打包
- 4.下面我们就要去看下rollup的配置 rollup.config.js
/*
* @Author: your name
* @Date: 2021-12-09 16:04:21
* @LastEditTime: 2021-12-13 16:22:09
* @LastEditors: Please set LastEditors
* @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @FilePath: \vue3.0\scripts\build.js
*/
// 将package目录下得所有包打包
const fs = require("fs");
const execa = require("execa"); //开启子进程,进行打包,最终还是使用rollup打包
// 找到目标模块
const target = fs.readdirSync("packages").filter((f) => {
// 判断是否是个目录
if (!fs.statSync(`packages/${f}`).isDirectory()) {
return false;
} else {
return true;
}
});
// 依次并行打包
runParallel(target, build).then((res) => {});
function runParallel(targets, iteratorFn) {
let res = [];
// 异步并行打包
for (const item of targets) {
const p = iteratorFn(item);
res.push(p);
}
return Promise.all(res);
}
// 核心打包模块build
async function build(target) {
// 调用rollup.config.js
await execa("rollup", ["-c", "--environment", `TARGET:${target}`], {
stdio: "inherit", //子进程共享给父进程
});
console.log(target, "build:打包");
}
4.rollup.config.js配置
- 总结
- 1.通过上面代码传入的参数process.env.target包名,取package.json
- 2.
- buildOption 中的参数name 就是用来坐全局变量,打包后script 引入就能直接使用这个值
- formats:打包出的类型 下面代码中outputConfig 就是针对这些类型的枚举,比如:format: “cjs”, //commondJS 是给node使用 因为node 不支持import es6语法 弄得使用这个项目就会引用cjs结尾的文件
- 最后export 就行了下面带面有注释,至于rollup怎么打包的我们暂时不用管
import path from "path";
import json from "@rollup/plugin-json";
import resolvePlugin from "@rollup/plugin-node-resolve";
import ts from "rollup-plugin-typescript2";
// rollup配置
console.log(process.env.target);
// 根据环境变量中得target属性获取对应模块中得package.json
// 找目标
const packagesDir = path.resolve(__dirname, "packages");
// 找具体哪个包
const packageDir = path.resolve(packagesDir, process.env.TARGET);
const resolve = (p) => path.resolve(packageDir, p);
// 取package.json
const pkg = require(resolve("package.json"));
// 取i文件名
const name = path.basename(packageDir);
// 对打包类型 先做一个映射表(枚举表),根据你提供得fromats来格式化需要打包得内容
const outputConfig = {
//自定义得
"esm-bundler": {
file: resolve(`dist/${name}.esm-bundler.js`),
format: "es", //es模块 第三方模块引用 支持import
},
cjs: {
file: resolve(`dist/${name}.cjs.js`),
format: "cjs", //commondJS 是给node使用 因为node 不支持import es6语法
},
global: {
file: resolve(`dist/${name}.global.js`),
format: "iife", //全局模块 立即执行 比如script 标签直接引入
},
};
// 自已在每个包中定义得 buildOptions
const options = pkg.buildOptions;
// 从映射表中找到配置 生成rollup 配置
function createdConfig(format, output) {
output.name = options.name;
output.sourcemap = true; ///生成map文件
// 生成rollup 配置
return {
input: resolve("src/index.ts"),
output,
plugins: [
json(),
ts({
tsconfig: path.resolve(__dirname, "tsconfig.json"),
}), //解析ts
resolvePlugin(), //第三方解析
],
};
}
// rollup 最终需要导出一个配置变量
export default options.formats.map((format) =>
createdConfig(format, outputConfig[format])
);
console.log(pkg);
5,因为是ts文件,需要ts的配置文件
npx tsc --int
修改里面的几个值
“target”: “es2016”,
“module”: “ESNext”,
“moduleResolution”: “node”, /* Specify how TypeScript looks up a file from a given module specifier. /
“baseUrl”: “.”, / Specify the base directory to resolve non-relative module names. /
“paths”: {
"@vue/":[“packages/*/src”]
},
“esModuleInterop”: true,
“forceConsistentCasingInFileNames”: true,
“strict”: false,
“skipLibCheck”: true
6.最后打包,npm run build*
7.相互引用
执行yarn install 在项目根目录下,只要package.json配置了workspaces,他自动会将packages中的项目建立软链接到modules中
{
"private": true,
"workspaces": [
"packages/*"
],
"name": "vue3.0",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"dev": "node scripts/dev.js",
"build": "node scripts/build.js"
},
"dependencies": {
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^13.0.6",
"execa": "^5.0.0",
"rollup": "^2.60.2",
"rollup-plugin-typescript2": "^0.31.1",
"typescript": "^4.5.2"
}
}
更多推荐
所有评论(0)