目录
1.1 创建monorepo仓库
# 安装pnpm 使用pnpm管理仓库
npm install -g pnpm
# 初始化仓库
pnpm init -y
1.2 配置
(1)修改package.json
{
"name": "vue3-lesson",
"private": true, // 开启仓库私有
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {},
"devDependencies": {}
}
(2)修改安装依赖
# 安装依赖
# typescript 使用ts管理类型
# 安装esbuild 构建工具
# 安装minimist 解析命令行参数
pnpm install -D typescript esbuild minimist
(3)pnpm配置
由于当前pnpm会默认以树状层级存放安装的依赖,因此我们需要将依赖包下的所有依赖配置为平铺,方便之后导入时的路径书写
在根目录下创建.npmrc文件,在文件中写入以下配置
shamefully-hoist=true
我们还需要指定monorepo管理的包所存放的目录,因此我们在根目录下创建一个packages文件夹专门来存放每个包模块
我们还需配置仓库管理目录,在根目录下创建一个pnpm-workspace.yaml文件,写入以下配置:
packages:
- 'packages/*'
- 'packages/*/*'
此后如果需要安装项目全局依赖,我们需要加一个参数,即 -w
(4)typescript配置
在根目录下创建一个tsconfig.json文件(可以使用命令tsc -init生成),写入以下配置:
{
"compilerOptions": {
"target": "es2016",
"lib": ["ESNext","DOM"],
"jsx": "preserve",
"module":"ESNext",
"moduleResolution": "node10",
"resolveJsonModule": true,
"sourceMap": true,
"outDir": "dist", // 打包目录
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": false,
"skipLibCheck": true
}
}
1.3 创建打包脚本
(1).创建目录结构
- 在根目录下创建一个script文件夹,用于存放打包的脚本文件
- 在其中创建一个dev.js文件,作为打包入口文件
- 在packages下创建一个reactivity文件夹
其结构如下:
packages
├── reactivity
│ ├── src
│ │ └── index.ts
│ └── package.json
- 在根目录的package.json中添加打包命令
"scripts": {
"dev": "node script/dev.js reactivity -f esm"
},
- 在reactivity中创建src文件夹,并在其中创建index.ts文件,作为入口文件
- 在reactivity中创建package.json文件,写入以下配置:
{
"name": "@vue/reactivity",
"version": "1.0.0",
"description": "Reactivity for Vue",
"module": "dist/reactivity.esm-bundler.js",
"unpkg": "dist/reactivity.global.js",
"buildOptions": {
"name": "VueReactivity",
"formats": [
"es-bundler",
"es-browser",
"cjs",
"global"
]
},
"dependencies": {}
}
(2).编写打包脚本
在script/dev.js中写入以下代码:
import minimist from "minimist";
import { resolve ,dirname} from 'path'
import { fileURLToPath } from 'url'
import { createRequire } from 'module'
import esbuild from "esbuild";
// 解析当前文件路径
const __filename = fileURLToPath(import.meta.url);
// 获取当前文件路径(这里由于es模块无法像cjs模块一样直接拿到__dirname,所以需要手动解析)
const __dirname = dirname(__filename); // 解析当前文件路径
// 获取模块导入方法require
const require = createRequire(import.meta.url) // 创建require
// 解析参数(即在package.json 中配置的那条命令所打包的文件的参数)
// node中的命令按参数可以通过process获取
const argv = process.argv.slice(2);
// 解析参数
const args = minimist(argv);
// 提取需要打包的模块名
const target = args._[0] || "reactivity"; // 打包那个项目
// 提取打包格式
const formate = args.f || "iife"; // 打包格式
// 提取包名 这个主要是在打包为iife(自执行函数)格式时,需要为iife函数命名
const pkg = require(`../packages/${target}/package.json`)
// 解析,模块文件入口
const entry = resolve(__dirname,`../packages/${target}/src/index.ts`)
// 根据需要开始打包
esbuild.context({
entryPoints: [entry], // 入口文件
outfile: resolve(__dirname,`../packages/${target}/dist/${target}.js`) ,// 打包出口
platform: 'browser', // 打包环境(打包完的代码运行平台)
sourcemap: true, // 可以调试源代码
format: formate, // 打包格式
/**
* cjs: 打包成commonjs格式
* esm: 打包成es模块
* iife: 打包成自执行函数(打包位自执行函数时需要为该函数变量命名)
*/
globalName: pkg.buildOptions?.name // 打包名称
}).then((ctx) => {
console.log(`${target}打包完成`)
return ctx.watch(); // 监听文件变化
})
(3).打包依赖文件
在packages下依照reactivity的结构在创建一个shared模块,在index.ts写出部分代码,并导出。在reactivity中导入并使用。可以直接在reactivity中使用pnpm 安装
这里就需要去tsconfig.json中添加以下配置
"baseUrl": "./",
"paths": {
"@vue/*": ["packages/*/src"]
},
# 安装
pnpm install @vue/shared
在dev.js中添加打包配置
esbuild.context({
...
bundle: true, // 将所有主文件与依赖文件打包为单个文件
})
这样一来无论引入多少个模块,打包完成之后就只有一个js文件
至此,整个打包的环境就配置完成了。