Monorepo:是管理项目代码的一个方式,指在一个项目仓库(repo)中管理多个模块/包(package)
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
初始化:
常用配置文件:
{ "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" ] } }
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~~~') })