vue源码构建流程build.js阅读理解

1. 概述

build.js 是 Vue 项目中的生产构建脚本,其主要作用是生成优化的生产版本构建文件并拼接 TypeScript 类型定义文件。该脚本是 Vue 项目构建系统的核心组件,负责协调多个包的构建过程。

2. 功能与特性

build.js 主要提供以下功能:

  • 多包并行构建:利用 CPU 多核能力并行构建多个包,提高构建效率
  • 多种输出格式支持:支持生成 ESM、CJS、IIFE 等多种模块格式
  • 构建选项灵活配置:通过命令行参数控制构建行为
  • 文件大小分析:构建后自动计算并显示文件大小、gzip 和 brotli 压缩后的大小
  • 枚举内联优化:优化代码中的枚举值使用
  • 版本信息注入:将 Git 提交信息和版本号注入构建产物

3. 命令行参数解析

build.js 使用 Node.js 的 util.parseArgs 解析命令行参数,支持以下选项:

参数名 简写 类型 说明
formats -f 字符串 指定构建格式(如 esm,cjs,global
devOnly -d 布尔值 仅构建开发版本
prodOnly -p 布尔值 仅构建生产版本
withTypes -t 布尔值 同时构建 TypeScript 类型定义
sourceMap -s 布尔值 生成源码映射文件
release 布尔值 发布模式构建
all -a 布尔值 构建所有匹配的目标包
size 布尔值 写入构建产物大小信息到文件

此外,还支持位置参数指定要构建的目标包名,包名支持模糊匹配。

4. 核心流程

4.1 初始化阶段

javascript 复制代码
run()

async function run() {
  if (writeSize) fs.mkdirSync(sizeDir, { recursive: true })
  const removeCache = scanEnums()
  try {
    const resolvedTargets = targets.length
      ? fuzzyMatchTarget(targets, buildAllMatching)
      : allTargets
    await buildAll(resolvedTargets)
    await checkAllSizes(resolvedTargets)
    if (buildTypes) {
      // 构建 TypeScript 类型定义
    }
  } finally {
    removeCache()
  }
}

初始化阶段主要完成:

  • 创建大小报告目录(如果需要)
  • 扫描并内联枚举值
  • 解析目标包列表
  • 启动构建流程
  • 检查构建产物大小
  • 构建类型定义(如果需要)

4.2 并行构建机制

javascript 复制代码
async function buildAll(targets) {
  await runParallel(cpus().length, targets, build)
}

buildAll 函数是构建系统的核心,它使用 runParallel 函数实现多目标并行构建。该函数会根据 CPU 核心数限制并发构建数量,避免资源耗尽。

4.3 单包构建流程

javascript 复制代码
async function build(target) {
  const pkgBase = privatePackages.includes(target)
    ? `packages-private`
    : `packages`
  const pkgDir = path.resolve(`${pkgBase}/${target}`)
  const pkg = JSON.parse(fs.readFileSync(`${pkgDir}/package.json`, 'utf-8'))

  // 跳过私有包(全量构建时)
  if ((isRelease || !targets.length) && pkg.private) {
    return
  }

  // 清理旧的 dist 目录
  if (!formats && fs.existsSync(`${pkgDir}/dist`)) {
    fs.rmSync(`${pkgDir}/dist`, { recursive: true })
  }

  // 确定构建环境
  const env = (pkg.buildOptions && pkg.buildOptions.env) ||
    (devOnly ? 'development' : 'production')

  // 执行 Rollup 构建
  await exec(
    'rollup',
    [
      '-c',
      '--environment',
      [
        `COMMIT:${commit}`,
        `NODE_ENV:${env}`,
        `TARGET:${target}`,
        formats ? `FORMATS:${formats}` : ``,
        prodOnly ? `PROD_ONLY:true` : ``,
        sourceMap ? `SOURCE_MAP:true` : ``,
      ]
        .filter(Boolean)
        .join(','),
    ],
    { stdio: 'inherit' },
  )
}

单包构建流程包括:

  • 确定包的基础路径(公开包或私有包)
  • 读取包的 package.json 配置
  • 跳过不应构建的私有包
  • 清理旧的构建目录
  • 确定构建环境(开发或生产)
  • 调用 Rollup 执行实际构建,传递必要的环境变量

4.4 文件大小检查

javascript 复制代码
async function checkAllSizes(targets) {
  if (devOnly || (formats && !formats.includes('global'))) {
    return
  }
  console.log()
  for (const target of targets) {
    await checkSize(target)
  }
  console.log()
}

async function checkSize(target) {
  const pkgDir = path.resolve(`packages/${target}`)
  await checkFileSize(`${pkgDir}/dist/${target}.global.prod.js`)
  if (!formats || formats.includes('global-runtime')) {
    await checkFileSize(`${pkgDir}/dist/${target}.runtime.global.prod.js`)
  }
}

async function checkFileSize(filePath) {
  // 计算并显示文件大小、gzip 和 brotli 压缩后的大小
}

文件大小检查功能会:

  • 检查全局生产构建文件的大小
  • 计算并显示原始大小、gzip 压缩大小和 brotli 压缩大小
  • 可选地将大小信息写入文件系统

5. 关键依赖

build.js 依赖以下核心模块:

  • Node.js 内置模块fs, path, util, zlib, os, child_process
  • 第三方工具picocolors(终端颜色输出), pretty-bytes(文件大小格式化)
  • 自定义工具模块./utils.js(工具函数), ./inline-enums.js(枚举内联优化)
  • 构建工具rollup(实际执行构建)

6. 输入输出示例

6.1 输入输出示例

示例 1: 构建特定包

输入:

bash 复制代码
node scripts/build.js vue

输出: 构建 vue 包,生成所有默认格式的构建产物(esm-bundler, cjs, global 等),并显示构建产物的大小信息。

示例 2: 构建匹配的多个包

输入:

bash 复制代码
node scripts/build.js dom -a

输出: 构建所有名称包含 "dom" 的包(如 compiler-dom, runtime-dom)。

示例 3: 指定构建格式

输入:

bash 复制代码
node scripts/build.js core --formats cjs

输出: 构建 core 包,仅生成 CJS 格式的构建产物。

示例 4: 同时构建类型定义

输入:

bash 复制代码
node scripts/build.js vue -t

输出: 构建 vue 包,并同时构建其 TypeScript 类型定义文件。

7. 构建产物

build.js 在每个包的 dist 目录下生成以下类型的构建产物:

  • ESM Bundler 版本:用于现代打包工具的 ESM 格式
  • ESM Browser 版本:可直接在浏览器中使用的 ESM 格式
  • CJS 版本:用于 Node.js 环境的 CommonJS 格式
  • Global/IIFE 版本 :可通过 <script> 标签直接在浏览器中使用的格式
  • Runtime 版本:不包含编译器的轻量级版本(各种格式都有对应的 runtime 版本)
  • 生产优化版本:经过压缩和优化的生产环境版本

每个构建产物都注入了版本信息、Git 提交哈希等元数据,并根据构建环境设置了正确的特性标志。

8. 总结

build.js 是 Vue 项目的核心构建脚本,它通过灵活的参数配置和高效的并行构建机制,确保了 Vue 库能够以多种格式和优化级别输出,满足不同场景的使用需求。该脚本不仅负责构建 JavaScript 代码,还集成了类型定义生成、文件大小分析等功能,是 Vue 开发工作流中不可或缺的工具。

相关推荐
前端fighter12 小时前
Vue 3 路由切换:页面未刷新问题
前端·vue.js·面试
Jenna的海糖12 小时前
Vue 中 v-model 的 “双向绑定”:从原理到自定义组件适配
前端·javascript·vue.js
子兮曰13 小时前
🚀 图片加载速度提升300%!Vue/React项目WebP兼容方案大揭秘
前端·vue.js·react.js
周周爱喝粥呀14 小时前
【案例】Three.js 模拟水波纹与天空场景(附案例代码)
前端·javascript·vue.js·3d
顾辰逸you14 小时前
mixins实现逻辑复用
前端·vue.js·vuex
前端小巷子15 小时前
Vue 项目性能优化实战
前端·vue.js·面试
夏小花花16 小时前
关于牙科、挂号、医生类小程序或管理系统项目 项目包含微信小程序和pc端两部分
前端·javascript·vue.js·微信小程序·小程序
柯南二号20 小时前
【大前端】Vue 和 React 主要区别
前端·vue.js·react.js
小光学长1 天前
基于vue驾校管理系统的设计与实现5hl93(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
前端·数据库·vue.js