vue3源码(一)搭建开发环境

Monorepo:是管理项目代码的一个方式,指在一个项目仓库(repo)中管理多个模块/包(package)
vue3源码采用Monorepo管理项目

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

初始化:pnpm tsc --init
常用配置文件:

{
  "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"
        ]
    }
}

formats为自定义的打包格式:

  • esm-bundler在构建工具中使用的格式
  • esm-browser在浏览器中使用的格式
  • cjsnode中使用的格式
  • 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~~~')
})