远子 💖 Vina

01-Vue3源码之构建过程

远子 â€¢  2020å¹´09月07日 â€¢ 1 条评论

逐行看一下 package.json:

pkg.private

"private": true 时, 代表仓库是私有的, 将无法发布到 npm

vue-next 管理了多个包, 每个包对应一个子仓库:

  • vue-next/packages/compiler-core: 公开仓库, 通过 npm i @vue/compiler-core 安装
  • vue-next/packages/compiler-dom: 公开仓库, 通过 npm i @vue/compiler-dom 安装
  • vue-next/packages/compiler-sfc: 公开仓库, 通过 npm i @vue/compiler-sfc 安装
  • vue-next/packages/compiler-ssr: 公开仓库, 通过 npm i @vue/compiler-ssr 安装
  • vue-next/packages/reactivity: 公开仓库, 通过 npm i @vue/reactivity 安装
  • vue-next/packages/runtime-core: 公开仓库, 通过 npm i @vue/runtime-core 安装
  • vue-next/packages/runtime-dom: 公开仓库, 通过 npm i @vue/runtime-dom 安装
  • vue-next/packages/server-renderer: 公开仓库, 通过 npm i @vue/server-renderer 安装
  • vue-next/packages/shared: 公开仓库, 通过 npm i @vue/shared 安装
  • vue-next/packages/vue: 公开仓库, 通过 npm i vue@next 安装
  • vue-next/packages/size-check: 私有仓库
  • vue-next/packages/template-explorer: 私有仓库
  • vue-next/packages/runtime-test: 私有仓库

pkg.version

版本号, 当前是 3.0.5

pkg.scripts

scripts 是个字段, 可以通过 npm run <属性名> 的方式执行, 目前有以下 script:

{
    "dev": "node scripts/dev.js",
    "build": "node scripts/build.js",
    "size": "node scripts/build.js vue runtime-dom size-check -p -f global",
    "lint": "eslint --ext .ts packages/*/src/**",
    "format": "prettier --write --parser typescript \"packages/**/*.ts?(x)\"",
    "test": "node scripts/build.js vue -f global -d && jest --runInBand",
    "test-dts": "node scripts/build.js shared reactivity runtime-core runtime-dom -dt -f esm-bundler && yarn test-dts-only",
    "test-dts-only": "tsc -p ./test-dts/tsconfig.json && tsc -p ./test-dts/tsconfig.build.json",
    "release": "node scripts/release.js",
    "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
    "dev-compiler": "npm-run-all --parallel \"dev template-explorer\" serve",
    "serve": "serve",
    "open": "open http://localhost:5000/packages/template-explorer/local.html",
    "preinstall": "node ./scripts/checkYarn.js"
}

我们先关注两个主要的命令:

  • npm run dev: 启动开发服务
  • npm run build: 打包构建

pkg.types

pkg.tsd

pkg.gitHooks

"gitHooks": {
  "pre-commit": "lint-staged",
  "commit-msg": "node scripts/verifyCommit.js"
}

Git 的钩子, 目前有两个:

  • pre-commit: 在 git commit 命令前执行 lint-staged
  • commit-msg: 用于检测 commit message 是否合规

pkg.lint-staged

"lint-staged": {
  "*.js": [
    "prettier --write"
  ],
  "*.ts?(x)": [
    "eslint",
    "prettier --parser=typescript --write"
  ]
}

lint-staged 用于格式化代码, .js 文件使用 prettier 格式化, --write 参数代表直接修改文件, prettier 的配置文件是 vue-next/.prettierrc, .prettierrc 定义如下:

semi: false # 不使用分号
singleQuote: true # 使用单引号
printWidth: 80 # 每行最多 80 个字符

.ts 或者 .tsx 文件先使用 eslint 后使用 prettier

pkg.engines

要求 node 的版本在 10.0.0 以上

pkg.devDependencies

对于普通用户来说 Vue 是零依赖的, package.json 中没有定义任何 dependencies

对于 Vue 的开发者, devDependencies 定义了开发环境特有的依赖包, 在 vue-next 目录下通过 npm repo <pkg_name> 命令可以快速打开依赖包的仓库地址

devDependencies主要分三种:

  1. Rollup 相关

    • rollup: 配置文件默认是 vue-next/rollup.config.js
    • rollup-plugin-node-builtins
    • rollup-plugin-node-globals
    • rollup-plugin-terser: 压缩混淆代码
    • rollup-plugin-typescript2: TS 降级
    • @rollup/plugin-commonjs: CommonJS 转 ES6
    • @rollup/plugin-json: .json 文件转 ES6
    • @rollup/plugin-node-resolve: 解析 node_modules 路径
    • @rollup/plugin-replace: 在打包中, 替换字符串
  2. TypeScript 相关

    • @babel/types
    • @microsoft/api-extractor
    • @types/hash-sum
    • @types/jest
    • @types/node
    • @types/puppeteer
    • @typescript-eslint/parser
    • typescript
    • ts-jest
  3. 工具包

    • brotli: 一种压缩算法, 像 gzip
    • chalk: 给终端字符添加样式
    • conventional-changelog-cli: 使用 commit message 生成 changelog
    • csstype: CSS 类型声明
    • enquirer: CLI 提示工具, 发布 release 时使用
    • eslint: 代码格式化工具
    • execa: 用来执行终端命令
    • fs-extra: 用于读写文件
    • jest: 测试包
    • lint-staged: 用于格式化代码
    • minimist: 解析终端命令的参数
    • npm-run-all: 同时执行多个 npm 命令
    • prettier: 代码格式化工具
    • puppeteer: Chrome 无头浏览器, 用于测试
    • semver: 用于控制版本
    • serve: 给静态页面启动服务
    • yorkie: husky 的改装版

执行构建命令

构建命令:

npm run build

等价于 node scripts/build.js, build.js 核心逻辑如下:

run();

async function run() {
    await buildAll(allTargets);
}

async function buildAll(targets) {
  await runParallel(require('os').cpus().length, targets, build)
}

async function build(target) {
  const pkgDir = path.resolve(`packages/${target}`)
  const pkg = require(`${pkgDir}/package.json`)
    // 省略了一些代码...
  await execa(
    'rollup',
    [
      '-c',
      '--environment',
      [
        `COMMIT:${commit}`,
        `NODE_ENV:${env}`,
        `TARGET:${target}`,
        formats ? `FORMATS:${formats}` : ``,
        buildTypes ? `TYPES:true` : ``,
        prodOnly ? `PROD_ONLY:true` : ``,
        sourceMap ? `SOURCE_MAP:true` : ``
      ]
        .filter(Boolean)
        .join(',')
    ],
    { stdio: 'inherit' }
  )
}
  1. 执行 run 方法
  2. 并行执行构建任务
  3. 使用 rollup -c --environment COMMIT:提交ID,NODE_ENV:环境,TARGET:包名称 打包各个包

    1. rollup -c 的意思是使用 vue-next/rollup.config.js 作为 rollup 的配置文件
    2. --environment 的意思是携带 COMMIT:提交ID,NODE_ENV:环境,TARGET:包名称 等参数

npm run build 时, 会执行以下命令:

  • vue-next/packages/compiler-core: 执行 rollup -c --environment COMMIT:e79feb0,NODE_ENV:production,TARGET:compiler-core
  • vue-next/packages/compiler-dom: 执行 rollup -c --environment COMMIT:e79feb0,NODE_ENV:production,TARGET:compiler-dom
  • vue-next/packages/compiler-sfc: 执行 rollup -c --environment COMMIT:e79feb0,NODE_ENV:production,TARGET:compiler-sfc
  • vue-next/packages/compiler-ssr: 执行 rollup -c --environment COMMIT:e79feb0,NODE_ENV:production,TARGET:compiler-ssr
  • vue-next/packages/reactivity: 执行 rollup -c --environment COMMIT:e79feb0,NODE_ENV:production,TARGET:reactivity
  • vue-next/packages/runtime-core: 执行 rollup -c --environment COMMIT:e79feb0,NODE_ENV:production,TARGET:runtime-core
  • vue-next/packages/runtime-dom: 执行 rollup -c --environment COMMIT:e79feb0,NODE_ENV:production,TARGET:runtime-dom
  • vue-next/packages/server-renderer: 执行 rollup -c --environment COMMIT:e79feb0,NODE_ENV:production,TARGET:server-renderer
  • vue-next/packages/shared: 执行 rollup -c --environment COMMIT:e79feb0,NODE_ENV:production,TARGET:shared
  • vue-next/packages/vue: 执行 rollup -c --environment COMMIT:e79feb0,NODE_ENV:production,TARGET:vue

rollup.config.js 会导出一个 json:

export default {
  input: '/Users/rmlzy/Documents/mygithub/vue-next/packages/shared/src/index.ts',
  external: [],
  plugins: [], // 不同的包使用的 plugin 有区别
  output: {
    file: '/Users/rmlzy/Documents/mygithub/vue-next/packages/shared/dist/shared.cjs.prod.js',
    format: 'cjs',
    sourcemap: false,
    externalLiveBindings: false,
    globals: { postcss: 'postcss' }
  },
  treeshake: { moduleSideEffects: false }
}

仅有一条评论

  1. ysl

    远哥在不在 远哥在不在 收到请回答 over

我要发表看法

«-必填
«-必填,不公开