在Webpack几乎统治前端应用构建的这几年,很多团队其实忽略了一个事实:Rollup这种同样优秀的打包器,始终在库与组件构建领域活得很好。我最早接触Rollup是因为维护公司内部组件库,明明源码没多少,用Webpack打出来却总是拖着一堆运行时垫片和奇怪的兼容代码,最后切成Rollup之后,产物直接砍掉40%的体积,tree shaking也真正生效了。当时我就在想,大部分前端工程化文章都在讲Webpack怎么调,却很少有人把Rollup和Webpack放在一起,讲清楚它们的边界、各自的优势段位,以及如何在同一套前端工程中配合使用。
这篇文章就是围绕“模块打包优化与性能提升”这个主题,把我在实际项目中同时使用Webpack和Rollup的完整经验写出来。你会看到这两种工具分别适合解决什么问题、为什么库构建推荐用Rollup而应用打包继续用Webpack、如何在不推翻现有工程的前提下引入Rollup做局部优化,以及那些文档里不会写但实际一定会踩的坑。无论你是被Webpack构建速度折磨的应用开发人员,还是要为团队搭建组件库、工具库的工程负责同学,这篇内容应该都能提供一套可落地的操作路径。
1. 先弄清定位:Rollup和Webpack到底谁该出现在你的工程里
很多人一听说Rollup就把Webpack喷得一文不值,这属于典型的工具偏见。在我自己的实践观感里,Rollup和Webpack从来不是谁替代谁的关系,而是分工不同。你必须先想清楚自己要交付什么,再决定用谁。
1.1 两者的核心差异:产物代码与运行时机制
从设计哲学上看,Webpack是一个应用打包器,它考虑的是复杂依赖图、各种静态资源、代码分割、热更新、以及浏览器环境的兼容兜底。它的产物会内置一套模块运行时(runtime),用来在浏览器里动态加载chunk、处理模块之间的引用关系。这套运行时本身是有体积成本的,通常几KB到十几KB不等,尽管在大型应用里这点开销可以忽略,但在一个要发布给很多业务方使用的npm包里,它就是纯粹的负担。
Rollup则完全不同。它出生在ES Modules普及之后,核心思想是“把源码当成一组ES模块,通过静态分析直接合并成一份干净的产物”。Rollup不使用运行时,它把你写的模块代码按依赖关系直接拍平到一个文件里,引用顺序完全可预测。你写什么结构,产物大体还是什么结构,只是去掉了模块包装壳。这种特性让Rollup极其适合生成库文件、组件文件,因为它产出的代码干净、紧凑、没有黑魔法。
一个很直白的对比是:同一个工具函数库,用Webpack打包出来的dist文件里能看到__webpack_require__这种东西,用Rollup打包则完全看不到任何框架痕迹。对使用者来说,后者显然更友好。
1.2 选型逻辑:什么项目用Rollup,什么项目继续用Webpack
在我负责过的前端工程里,我基本按下面几条原则来做选择,大家可以参考。
Webpack的舒适区是业务应用。只要项目需要路由懒加载、按需引入图片字体、开发环境热更新、处理各种loader链,那Webpack或者是它生态下的Vite就是最合适的。你不太会想用Rollup去搭一个需要按页面拆包的中后台应用,虽然它技术上也能做到,但对开发体验的维护成本远超收益。
Rollup的舒适区是发布到npm的库文件。比如组件库、工具函数库、插件的打包产物、甚至被多个应用复用的业务模块。这类产物追求的是体积小、结构清晰、副作用可控、让使用方自己的打包工具能二次tree shaking。我自己维护过一个内部UI组件库,用Rollup同时输出ESM和CJS两种格式,总产物体积比之前用Webpack直接打包时减少了接近一半。
除此之外还有一种情况也很适合Rollup:现有Webpack应用里的大型内部模块如果单独提取出来用Rollup预构建,可以绕开Webpack对这部分代码的重复解析时间,让增量构建明显变快。这个操作我在第五节会详细讲。
1.3 为什么实际工程里会出现“Rollup方案 + Webpack工程”的混合形态
不少团队听到Rollup第一反应是“要不要把Webpack换掉”,其实这是误解。我在真实项目里更常用的是混合构建:整个应用仍然用Webpack搭建,但应用里那些需要被多个入口或外部项目复用的核心模块,会单独拉出来用Rollup打包成ESM格式,然后让Webpack通过alias或者依赖直接引用这份产物。
这么做有三个直接收益。第一,核心模块的构建时间被从Webpack全量构建里剥离,Webpack的依赖解析范围更小,构建速度显著提升。第二,核心模块的产物是ESM,Webpack在打包引用它的时候能够继续做tree shaking,应用体积不会因为预构建反而膨胀。第三,这套核心模块将来如果要从应用里拆成独立npm包,构建链路已经提前验证过,只需要调一下发布脚本。
当然这种混合模式不是没有代价,它要求团队必须维护两套构建配置。我在第二节和第三节会分别讲清楚Webpack侧的优化怎么做、Rollup侧的构建怎么配,以及在联调过程中最容易出的问题。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Webpack侧的打包优化:先把存量工程的性能榨干
如果你暂时不打算引入Rollup,只是想优化现有Webpack项目,那这一部分同样适用。我见过很多项目一谈优化就想到换构建工具,但往往连基础的持久化缓存都没开。把Webpack自身的潜力榨干之后,再决定要不要引入额外复杂度,这才是工程化的正确顺序。
2.1 分清问题类型:构建速度慢还是产物体积大
做Webpack优化之前先问自己:要解决的是开发时构建慢,还是线上产物体积大?这两个问题的解法和优化方向几乎不重叠,不先分类很容易把配置改得面目全非。
如果是开发时构建慢,通常是模块解析范围太大、loader执行时间过长、缓存失效频繁。这种情况我推荐优先做四件事:
- 把
cache设置为filesystem,让Webpack在磁盘上持久化中间结果。Webpack 5默认就是filesystem缓存,但很多从Webpack 4升上来的项目还在用cache: false或者内存缓存。 - 用
module.rules里的include字段把loader的处理范围精确到src目录,千万别让babel-loader去扫node_modules。 - 开启
parallel能力密集型loader的并行构建。比如thread-loader,把它放在耗时的loader之前,可以在多核CPU上并行执行。 - 仔细检查
resolve.alias和resolve.extensions,别让Webpack在解析时做太多无意义的路径尝试。
如果是产物体积大,那要做的又是另一套工作。先跑一次webpack --profile --json > stats.json,用webpack-bundle-analyzer可视化看看产物体积的分布。很多人一上来就说“我要做代码分割”,其实首要是先去找到那个占了几百KB的第三方库,判断它是不是必须的。
2.2 性能量化:怎么看优化有没有生效
优化不量化等于白做。我自己会建立一组固定指标,每次调优都对比同样几个数字。
- 冷启动全量构建时间:清掉缓存后执行一次生产构建的耗时。
- 增量构建时间:改一行代码,观察热更新或者重新构建的耗时。
- 产物总体积(gzip前/gzip后):主要看gzip后体积,因为线上真正传输的是它。
- 首屏chunk体积:包含入口及其同步依赖的chunk大小,超过200KB就该警惕了。
- 构建缓存命中率:Webpack 5内置了缓存统计,可以直接在日志里看到。
我习惯在做任何配置变更之前先记录一组基线数据,然后把修改后的数据对比画出来。有时候你觉得自己优化了很多,但数字一拉出来发现根本不明显,这时候就要考虑是不是没打中要害——比如构建瓶颈其实在图片压缩,你却在那里调代码分割参数,确实没什么用。
3. 核心实操:把内部库构建切到Rollup的完整配置过程
这一章我会直接给出一套可落地的Rollup配置方案,并结合我自己在实际项目中的踩坑记录。这套配置我用于构建内部组件库和工具库,目前已经稳定跑了两个大版本,实测对整个基础设施的维护效率有明显改善。
3.1 最小可用Rollup配置长什么样
Rollup的配置和Webpack一样,最终就是一个导出的对象,里面写着input入口、output出口、以及一串插件。但比Webpack清爽很多,没有那么多loader和resolve的复杂规则,因为Rollup默认就只认ESM。
一个只处理ES模块的最小配置长这样:
javascript复制// rollup.config.mjs
export default {
input: 'src/index.js',
output: {
file: 'dist/index.esm.js',
format: 'esm'
}
};
如果你只是想把源码里的ESM模块合并成一份文件,上面这个就够了。实际项目中你几乎肯定要处理node_modules里的依赖、CommonJS模块、代码压缩等问题,所以才会引入插件体系。
Rollup的插件生态和Webpack的loader不一样。Webpack的loader是在模块被import时对源文件做转换,而Rollup插件更像是在构建流程的各个生命周期节点上介入处理,这决定了它在处理某些非标准模块格式时不如Webpack生态那么“顺手”,但也因此让构建流程更透明、更好控制。
3.2 核心插件分工:resolve、commonjs、babel、terser与plugin-wasm
我的标准库构建配置会引入下面这几个插件,分别解决不同问题。先看完整配置,再逐个解释为什么要这么选。
javascript复制// rollup.config.mjs
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import babel from '@rollup/plugin-babel';
import terser from '@rollup/plugin-terser';
import { visualizer } from 'rollup-plugin-visualizer';
import wasm from 'rollup-plugin-wasm';
export default {
input: 'src/index.js',
output: [
{
file: 'dist/index.esm.js',
format: 'esm',
sourcemap: true
},
{
file: 'dist/index.cjs.js',
format: 'cjs',
exports: 'named',
sourcemap: true
}
],
external: ['react', 'react-dom'],
plugins: [
resolve({ extensions: ['.js', '.jsx', '.ts', '.tsx'] }),
commonjs(),
wasm(),
babel({
babelHelpers: 'bundled',
extensions: ['.js', '.jsx', '.ts', '.tsx'],
exclude: 'node_modules/**'
}),
terser({ format: { comments: false } }),
visualizer({ filename: 'dist/stats.html' })
]
};
逐个解释插件的作用。
node-resolve:Rollup默认不认node_modules里的包路径。你要import一个已经install到node_modules的第三方包,没有这个插件就解析不到。它相当于Webpack里resolve模块的简化版。
commonjs:把CommonJS格式的依赖转换成ESM。毕竟不是所有包都写了ESM入口,很多老牌的包还停留在module.exports。没有这个插件,一旦import到CJS格式的包,Rollup构建就会直接报错。
wasm:这个插件是我最新项目中加进来的,因为组件库里有一个WebAssembly模块需要被同步导入。rollup-plugin-wasm会把.wasm文件作为base64内联进产物,同时生成对应的JS封装。它解决的痛点是:Rollup默认不会像Webpack那样用asset处理二进制文件,你直接用import xxx from './xxx.wasm'会被当成缺失模块直接抛错。
babel:给源码做语法降级。这里有个容易踩的坑是babelHelpers选项。如果设成bundled,辅助函数会被内联进每个产物,虽然省了额外依赖,但产物里会有重复代码;如果设成runtime,它会去引用@babel/runtime,需要产物使用者安装这个依赖。库作者想减少产物体积,可以选bundled,然后接受一定的重复;想完全消灭重复,就得选runtime。我个人在组件库里用bundled,因为组件库本身产物不算大,多个文件打包在一起后重复量可接受,少一个peer依赖方便使用方安装。
terser:代码压缩,等价于Webpack里用在production模式的terser-webpack-plugin。
visualizer:产物体积可视化分析。虽然是开发依赖,但能让你非常直观地看到每个模块占的体积比例,找优化目标的时候特别有用。
3.3 外部依赖声明:external配置决定产物边界
很多第一次用Rollup的人会困惑一个问题:为什么我的组件库把react也打进了产物里?答案就是你没配置external。
Rollup和Webpack的一个关键区别在于,Webpack默认会把所有import的包都打进bundle,除非你在externals里显式排除;Rollup默认行为也一样,但它处理依赖的方式更“语法级”——如果import的包在external数组里,它会在产物里保留这个import语句,让使用方自己解决。
对库构建来说,react、react-dom、vue这类框架运行时必须放在external里。它们应该作为peerDependencies由使用方提供,如果打进库里,轻则产物体积翻倍,重则导致使用方项目里出现两份React,触发hooks报错。我自己就踩过这个坑,当时组件库编译忘记把react-dom加进external,结果业务方的React应用界面直接白屏,排查半天发现是两份react-dom的dispatcher对不上。
判断哪些包要external的基本原则:看它会不会被使用方的打包器二次解析。凡是使用方大概率自己装了、且不应该出现两份的依赖,都放external。拿不准的时候可以查一下这个包的peerDependencies,如果它本身就把React设为peer,那你构建库时也一定要external它。
3.4 output多格式输出:为什么同时输出ESM和CJS
配置里我定义了两组output,一是esm格式,二是cjs格式。很多同学会问:既然现代浏览器和打包器都支持ESM了,只发ESM不就行了?
理论上是这样,但现实里仍然有大量老项目在使用CommonJS的模块解析方式,比如还没升级到Webpack 5的旧工程,或者跑在Node端的服务端渲染代码。如果npm包只有ESM入口,CJS环境会直接require报错。
所以我的组件库在package.json里会同时暴露两个入口:
json复制{
"name": "@your-scope/your-lib",
"main": "dist/index.cjs.js",
"module": "dist/index.esm.js",
"exports": {
".": {
"import": "./dist/index.esm.js",
"require": "./dist/index.cjs.js"
}
}
}
main字段给老版本Node和CJS解析器用,module字段给Webpack等打包器提供ESM入口,exports字段则是Node 12+和新一代打包器推荐的方式。这样配置之后,使用方打包时能够拿到ESM版本做tree shaking,老环境也能通过CJS版本正常运行。
4. Tree Shaking深度对比:Rollup为什么能摇得更干净
Tree Shaking是模块打包优化里最常被提起的词。我遇到不少开发者以为只要把构建模式设成production,tree shaking就自动生效了。其实没那么简单,它需要模块格式支持 + 打包器静态分析 + 开发者编写习惯三者配合才能达到理想效果。
4.1 ESM静态结构带来的摇树优势
Tree Shaking的技术基础是ES Modules的静态结构——import和export必须在模块顶层出现,不能在条件语句里或函数内部动态生成。这种静态性让打包器可以在不执行代码的情况下,构建出完整的依赖关系图,然后从入口出发,标记所有被引用到的export,最后把没被引用的代码从产物里删除。
Rollup从1.0开始就把tree shaking放在最核心的位置,它的摇树分析比Webpack更激进。Rollup会沿着模块的引用关系做整条链路的“死代码消除”,如果一个变量从未被使用,它能一直追踪到最源头,把这个变量的定义连同它的依赖一起删掉。Webpack 5的tree shaking能力相比4已经有很大提升,但Webpack的模块机制毕竟要维护chunk、runtime等复杂结构,在部分场景下仍然会保守地保留一些代码。
举个例子,假如你有这样一个工具文件:
javascript复制// utils.js
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
入口只import了add。Rollup对这段代码的处理是直接删掉subtract函数的定义。Webpack实际上也能做到,但如果在某个模块里,一个让人看不出来是否会被调用的代码块存在副作用——比如顶层执行了一句console.log——那Webpack的默认配置就会保守地保留这个模块。Rollup处理时会相对更信任纯ES模块结构。
这只是理论对比。实际工程里如果代码本身是ESM,且没有副作用标记问题,Webpack 5和Rollup的摇树效果差距没有传说中那么大。真正的差异往往出现在处理第三方依赖和sideEffects配置时。
4.2 让Webpack也能摇干净的sideEffects配置
在Webpack项目里,如果你的某个模块没有任何副作用——比如它只导出纯函数、纯组件,不修改全局变量,不产生外部可观察的影响——那就应该在package.json里明确声明"sideEffects": false,告诉Webpack:这个包里的模块即使被引入但没有被使用,也可以放心地删掉。
如果你的代码里确实有副作用逻辑,比如引入了全局样式:
javascript复制import './global.css';
那就不能简单粗暴地设成false,否则连样式都会被摇掉。正确做法是用数组形式声明哪些文件有副作用:
json复制{
"sideEffects": [
"**/*.css",
"./src/polyfill.js"
]
}
我之前接过一个优化任务,业务方老说打包体积大,我一看,项目里所有自己写的工具函数都被集中在一个utils/index.js桶文件里导出,且没有任何sideEffects配置。Webpack只能保守地把这整个模块当成可能有副作用的代码,导致一个只是用了一个formatTime函数的页面把几十个工具函数全部打包了进去。后来把这个工具库的package.json加上sideEffects: false,并把桶文件按函数拆分导出也做了一部分,产物体积直接少了20%。
这里多说一句,项目越大,sideEffects配置带来的收益越明显。因为Webpack默认要保留那些无法证明无副作用的模块,而这种“无法证明”在大型项目里比比皆是。
4.3 副作用标记是Rollup方案的隐性杀手
用Rollup构建库的时候,副作用问题一样存在,而且因为Rollup的摇树更激进,副作用误判的后果也更严重。
我举一个实际场景:组件库入口是集中导出的:
javascript复制// src/index.js
export { default as Button } from './components/Button';
export { default as Input } from './components/Input';
export { default as Toast } from './components/Toast';
如果某个组件的模块顶层有副作用代码,比如定义了一个自定义事件监听、往某个全局对象上挂东西,Rollup在打包入口时就会发现这个模块不能被安全删除,于是整个引入会保留。这不算错,但如果你没意识到某个模块有隐性的副作用,可能就会看到产物里出现一堆“貌似没用”的代码——这些代码其实正是因为副作用标记而保留下来的。
所以我在写Rollup构建的库源码时,会坚持一个原则:副作用代码单独放文件,且在package.json里精确声明。比如全局样式放在src/styles/,polyfill放在src/polyfills/,然后在package.json里声明这些路径都是有副作用的。这样Rollup在摇树时可以充分删除没有副作用的纯逻辑模块,同时保留必要的引入。
如果构建产物被使用方二次打包,使用方的Webpack还是会看这个npm包的sideEffects字段。这个时候如果你的库没有正确声明,那你在Rollup里摇得非常干净的产物,到了业务方可能会被Webpack整体保留。所以发布库之前,最好把package.json的sideEffects字段也一并检查一遍。
5. 混合工程里的配置协同与问题排查
工具选型落到实处后,最麻烦的不是单独用Rollup或者单独用Webpack,而是同一个前端工程里两套构建体系需要协同工作。我在实践过程中积累了一些配置协同和问题排查的经验,这里挑最有代表性的几个场景写出来。
5.1 如何让Webpack正确引用Rollup构建的ESM产物
假设你的核心模块已经用Rollup构建好了,产物是dist/core.esm.js。在主应用的Webpack配置里想引用它,有几个层级可以操作。
最简单的方式是直接在源码里相对路径引用:
javascript复制import { coreApi } from '../../packages/core/dist/core.esm.js';
这种方式的问题是路径太长、语义不清晰,而且一旦核心模块的位置变动,所有引用的地方都要改。我更推荐在Webpack的resolve.alias里指一个别名,比如:
javascript复制// webpack.config.js
const path = require('path');
module.exports = {
// ...
resolve: {
alias: {
'@core': path.resolve(__dirname, 'packages/core/dist/core.esm.js')
}
}
};
这样做的好处是业务代码里不需要关心核心模块是用什么工具构建的,将来如果核心模块从应用里拆出去发布成独立npm包,只需要把alias去掉,全局替换一下引用路径就行。
这里有一个重要注意事项:Webpack在解析ESM产物时,仍然会把它当作一个普通的ESM模块做依赖分析,因此产物里不能包含浏览器不支持的语法。如果你Rollup构建时忘了做语法降级,产物里可能残留可选链或空值合并操作符,而你的Webpack应用为了兼容老浏览器配置了更低的语法目标,那么Webpack这个loader链通常不会去转译node_modules里的文件,老浏览器就会直接报语法错误。建议在Rollup配置里@rollup/plugin-babel的targets与主应用的兼容范围保持一致,或者干脆让核心模块产物生成时也走一遍语法降级。
5.2 构建时间没降反升,可能是缓存与并行配置冲突
我在混合构建试点初期,原本计划把核心模块的构建时间从Webpack里剥离出去,结果加上Rollup预构建步骤后整体时间反而变长了。排查发现原因主要有两个。
第一个原因是我把Rollup构建放到了Webpack构建之前,串行执行。如果模块又大又多,Rollup构建本身要几十秒,就导致整个发布流程被拉长。解决思路是把Rollup参与构建的模块控制在一个合理粒度,别把整个业务仓库都交给Rollup去构建,它只负责那些纯粹、少依赖、相对稳定的核心模块。至于发布流程,可以尝试并行执行Rollup和Webpack的构建,等两边都完成后再执行后续的产物处理。
第二个原因是Webpack 5的filesystem缓存和模块id复用之间的关系。有时候你改了核心模块的代码,核心模块的ESM产物虽然变了,但Webpack因为持久化缓存认为这个模块没有变化,导致线上产物还是旧的。排查出来后发现是Webpack的cache.version没有和核心模块的版本关联起来。这个问题的修复方式很粗暴:给Webpack缓存配置加一个version字段,每次核心模块升级时手动更新一下,确保缓存不串味。
javascript复制// webpack.config.js
module.exports = {
cache: {
type: 'filesystem',
version: '1.2.3'
}
};
5.3 模块重复打包的经典场景:依赖被同时打进Rollup产物和Webpack产物
混合构建最隐蔽的坑是同一个第三方包被打了两次——一次在你的Rollup产物里,另一次在主应用Webpack打包时又引入了一份。
举个例子,你的核心模块依赖了lodash-es,Rollup构建时如果忘记把它加进external,它会直接被内联进core.esm.js。主应用刚好也依赖了lodash-es,Webpack在主应用打包时会从node_modules里再解析一份。最终结果就是产物体积里有两份lodash,不仅浪费空间,某些有内部状态的库还可能导致逻辑混乱。
解决办法就是我在3.3节强调过的external配置。把所有不希望Rollup打包进去的依赖都声明成external。对库构建来说,最好把所有dependencies之外的对等依赖都external,只保留那些你确实希望和使用方共享的代码。
判断Rollup产物里是否意外带了某个依赖,有一个非常直接的检查方法:打开产物文件全局搜一下node_modules里包的特征代码,或者看visualizer生成的HTML分析图,依赖占比一目了然。
5.4 混合构建的正确接入流程
说了这么多经验,最后整理一个我在新项目里落地混合构建的接入流程,可以作为参考。
第一步,先跑通现有Webpack工程的构建,记录基线数据(构建时间、产物体积、首屏chunk大小)。第二步,选择一个相对独立、依赖稳定、被多个入口引用的核心模块作为试点,用Rollup建立构建配置,先只输出ESM格式。第三步,在试点模块里检查产物:依赖有没有意外内联、代码有没有降级到位、tree shaking是否生效。第四步,用Webpack的alias规则把试点模块的入口替换为Rollup产物,跑一遍全量构建,对比基线数据。第五步,如果效果符合预期,再把更多的模块纳入Rollup构建范围,逐步形成一套可复用的npm script配置。
这套流程最大的好处是每走一步都有明确的可验证点,出问题能快速定位是Rollup配置的问题还是Webpack接入的问题,而不是一口气把整条链路改完再面对一堆不知道来源的报错。
6. 踩过几次坑之后的工作流心得
前面把配置和方法论讲得差不多了,最后聊一些我在这个过程中踩出来的个人习惯。这些内容不算多么高深的技术,但确实能帮你少走弯路。
第一件事,任何构建工具的变更都要先形成基线数据再动手。我见过太多人改了一整天Webpack配置,最后问效果如何,只能说“感觉好像快了一点”。没有数据支撑的优化等于没有优化。我自己每次调优前都会固定跑一个命令把stats信息记录下来,改动完成后对比输出,只有数据明确变好了,这个改动才算成立。
第二件事,库的打包产物一定要构建出来之后人工检查一遍。Rollup打包一个东西出来,它不是非得成功执行、代码没报错就行,你得打开产物文件实际扫一眼里有没有可疑的运行时注入、有没有不应该出现的依赖、有没有把使用方的peer dependency误打进去。这些问题是自动化工具不会替你发现的,靠代码review之前先靠人工review产物。
第三件事,别把工具当信仰。Rollup和Webpack都是工程手段,最终目的是让团队交付更快、产品运行更稳。如果某个团队整体Webpack技能很熟,而且核心模块与业务代码耦合度高、很难拆分,那强行引入Rollup收益反而不大。我见证过很多团队架构讨论到后来变成“Rollup vs Webpack谁更高级”的意气之争,这真的很没意思。正确姿势应该是像做实验一样,用数据验证、小范围试点、让效果说话。
这篇文章里写的配置和经验,都是从我实际维护过的内部组件库和混合构建工程里沉淀下来的。当前端工程规模大到一定程度之后,“用一个工具解决所有问题”的思路会越来越吃力,而“在正确的边界用正确的工具”才是更有工程价值的解法。希望这篇基于Rollup和Webpack的实践笔记,能在你处理模块打包优化的时候提供一个新的参考方向。
