前言
为什么 Vite 在生产环境不使用 ESBuild 而是选择 Rollup?为什么 Rollup 打包出来的代码比 Webpack 更纯粹?本文将带你深入 Rollup 的核心配置,并拆解 Vite 是如何驱动 Rollup 完成生产环境构建的。
一、 Rollup 核心配置:构建系统的"方向盘"
1. 核心概念
Rollup 是 Vite 生产环境下的底层打包工具,专注于 ES 模块的打包优化。
注意 :在 Vite 项目中,不需要单独编写rollup.config.js文件 ,所有 Rollup 相关的配置都统一写在vite.config.js/ts的build.rollupOptions字段中。Vite 会自动将你的配置与内置的 Rollup 配置合并,生成最终的打包配置。
2. 核心特点
- 具有天然的 Tree Shaking 功能,可以静态分析 ES 模块的导入导出关系,精准移除未使用到的代码
- 支持Scope Hoisting(作用域提升) ,将多个模块的代码合并到同一个作用域中,减少函数包裹和运行时开销
- 打包产物体积小、执行效率高,特别适合用于 JavaScript 库和工具的打包
- 插件系统简洁强大,易于扩展和定制
二、Rollup 核心配置项详解
1. input(打包入口)
用于指定打包的入口文件,支持三种写法:
- 字符串:单入口,所有代码打包到一个文件中,适合 SPA 单页面应用
- 数组:多入口,每个入口生成独立的 chunk 文件,公共依赖会自动拆分
- 对象:多入口,可自定义每个 chunk 的名称,是最灵活的写法
javascript
// 单入口
input: 'src/index.js'
// 数组多入口
input: ['src/page1.js', 'src/page2.js']
// 对象多入口(推荐)
input: {
home: 'src/pages/home.js',
about: 'src/pages/about.js',
vendor: 'src/utils/vendor.js'
}
原内容保留:如果是多文件的话,会给每个入口生成独立文件,公共依赖会在打包过程中拆分出来,适用于 MPA(多页应用)、库的多版本。
2. output(打包输出)
该属性为对象或对象数组类型,可以指定打包后的文件输出规则。如果配置为数组,可以将同一份代码打包成多种不同格式的包同时输出。output 核心属性如下:
| 属性名 | 类型 | 说明 |
|---|---|---|
dir |
string | 输出目录,当有多个 chunk 时必须使用此属性 |
file |
string | 单个输出文件的路径,仅适用于单入口单 chunk 的情况 |
format |
string | 输出格式,支持:- esm:ES Module 格式(Vite 默认)- cjs:CommonJS 格式- umd:通用模块定义- iife:立即执行函数格式 |
name |
string | 打包为iife或umd格式时必须配置,指定对外暴露的全局变量名 |
globals |
object | 全局变量声明,用于将外部依赖映射为全局变量示例:{ jquery: '$' }表示项目中可以直接用$代替jquery |
sourcemap |
boolean | 是否生成源码映射文件,方便生产环境调试 |
assetFileNames |
string | 静态资源文件输出文件名模板示例:'assets/[name]-[hash][extname]' |
下面的例子代表第一次打包(ESM 格式),将结果输出到dist/es/目录,第二次打包(CJS 格式),将结果输出到dist/cjs/目录
javascript
output: [
{
dir: "dist/es", // 输出到 dist/es 目录
format: "esm", // ES Module 格式
},
{
dir: "dist/cjs", // 输出到 dist/cjs 目录
format: "cjs", // CommonJS 格式
},
]
3. external(外部依赖)
用于标记某些模块为外部依赖,告诉 Rollup 这些模块不应该被打包到最终的 bundle 中。对于某些第三方包,有时候我们不想让 Rollup 进行打包,也可以通过 external 进行外部化。external 支持三种写法:
javascript
// 字符串写法
external: ['vue', 'react']
// 正则写法
external: [/^lodash/]
// 函数写法(最灵活)
external: (id) => {
// 所有node_modules中的模块都标记为外部依赖
return id.includes('node_modules')
}
使用场景:
- 库打包时,将核心依赖(如 Vue、React)外部化,避免重复打包
- 减少打包体积,提高构建速度
- 利用 CDN 加载公共依赖
4. plugins(插件系统)
用于扩展和定制 Rollup 的构建流程。该配置项可以与output配置在同一级(全局生效),也可以配置在 output 参数里面(仅对该输出生效)。可使用自定义编写的 Rollup 插件,也可以使用第三方插件。
常用 Rollup 插件整理如下:
| 插件名称 | 作用 |
|---|---|
@rollup/plugin-json |
支持.json文件的加载,并配合 Tree Shaking 去掉未使用的部分 |
@rollup/plugin-babel |
使用 Babel 进行 JS 代码的语法转译,兼容低版本浏览器 |
@rollup/plugin-typescript |
支持使用 TypeScript 开发 |
@rollup/plugin-alias |
支持路径别名配置 |
@rollup/plugin-replace |
在打包过程中进行变量字符串的替换 |
@rollup/plugin-node-resolve |
解析 node_modules 中的第三方依赖 |
@rollup/plugin-commonjs |
将 CommonJS 模块转换为 ES 模块,供 Rollup 处理 |
rollup-plugin-visualizer |
对打包产物进行分析,自动生成产物体积可视化分析图 |
补充说明 :
@rollup/plugin-node-resolve和@rollup/plugin-commonjs是 Rollup 处理第三方依赖的必备插件,Vite 已经内置了这两个插件,不需要手动配置。
这篇笔记非常深入地探讨了 Rollup 在 Vite 体系中的地位。作为现代前端打包工具的"幕后英雄",Rollup 的配置和流程是进阶高级前端的必修课。
为了适配掘金的风格,我为你优化了标题,并引入了"声明式配置图解 "和"双阶段构建流 "的概念,同时修正了部分关于 input 拼写的小细节。
进阶必备:深度解析 Rollup 配置与 Vite 生产构建流程
前言
为什么 Vite 在生产环境不使用 ESBuild 而是选择 Rollup?为什么 Rollup 打包出来的代码比 Webpack 更纯粹?本文将带你深入 Rollup 的核心配置,并拆解 Vite 是如何驱动 Rollup 完成生产环境构建的。
一、 Rollup 核心配置:构建系统的"方向盘"
Rollup 的配置以简洁著称,其设计的核心目标是打包出最干净的代码库。
1. 入口与出口 (Input & Output)
-
input(注意是单数):支持字符串或数组/对象。- 单入口:适合单页面应用 (SPA),生成一个主 bundle。
- 多入口:适合多页面应用 (MPA) 或组件库,Rollup 会自动提取公共依赖。
-
output:支持数组形式,实现一份源码,多种格式输出。-
format:esm: 现代浏览器首选。cjs: Node.js 环境使用。umd: 兼容 AMD/CommonJS/全局变量。
-
globals: 映射外部依赖,如{ jquery: '$' }。
-
2. 外部依赖 (External)
核心作用:标记某些模块不被打包。
- 场景:在开发组件库时,通常会将
vue或react设为external,让宿主环境提供这些依赖,减小打包体积。
3. 常用插件全家桶
| 插件名称 | 核心作用 |
|---|---|
@rollup/plugin-json |
让 JS 能直接 import json,并支持 Tree Shaking。 |
@rollup/plugin-babel |
配合 Babel 进行语法降级,解决兼容性问题。 |
@rollup/plugin-typescript |
让 Rollup 具备处理 TS 的能力。 |
@rollup/plugin-alias |
配置路径别名(如 @ 指向 src)。 |
rollup-plugin-visualizer |
神器:生成体积分析图,优化首屏加载必看。 |
三、 Vite 视角下的 Rollup 构建流程
执行vite build命令后,Vite 会先完成自身的预处理工作,然后将所有打包任务委托给 Rollup 执行。整个流程可以分为以下三个核心阶段:
阶段 1:Vite 配置预处理与 Rollup 配置生成
Vite 读取vite.config.js,先分离 Vite 非 Rollup 相关的配置和 Rollup 相关配置;将 Vite 内置的处理 Vue/TS/CSS/ 静态资源插件注入,再合并用户配置的插件,最终生成标准的包含input、output、plugins等核心字段的Rollup 配置对象。
接着 Vite 调用 Rollup 的rollup.rollup()方法,传入上述配置,启动 Rollup 构建流程。
阶段 2:Rollup 构建阶段(建立模块依赖图)
Rollup 从input指定的入口文件开始,依次执行所有插件的resolveId(解析模块路径)→load(加载文件内容)→transform(转换文件为标准 ES 模块)钩子来处理各类资源。在处理的过程中会递归解析所有导入的模块,直到所有依赖解析完成,建立完整的模块依赖图。
补充:这个阶段只进行模块的解析和转换,不会生成任何输出文件。所有的文件内容都会被加载到内存中,形成一个完整的模块树。
阶段 3:Rollup 生成阶段(产物生成与输出)
在构建打包的过程中,Vite 会基于模块依赖图执行 Tree-shaking 移除未使用代码、Scope Hoisting 作用域提升,并根据output配置进行代码分割将代码拆分成多个独立的 chunks 文件,实现按需加载。Vite 插件在此阶段补充处理(将.vue、.ts 等文件编译为标准的 js 文件、并处理 css 将其压缩成单独的 css 文件等)。
最后调用bundle.generate()在内存中生成编译后的 JS/CSS/HTML 等产物,和bundle.write()将内存中的产物写入磁盘(默认dist目录),最终生成可部署的静态资源文件。
补充 :
bundle.generate()只在内存中生成产物,不写入磁盘;bundle.write()会先调用bundle.generate(),然后将产物写入到指定的输出目录。
总结
Rollup 作为 Vite 生产环境的底层打包工具,是理解 Vite 打包原理的关键。掌握 Rollup 的核心配置和构建流程,不仅能帮助你解决生产环境中的各种打包问题,还能让你更灵活地定制 Vite 的构建流程,实现更高效的打包优化和插件开发。