前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
  • Vue

    • 从源码解读Vue生命周期
    • 组件的本质
    • 有状态组件的设计
    • 设计 VNode
    • 辅助创建 VNode 的 h 函数
    • 自定义渲染器和异步渲染
    • 渲染器之挂载
    • 渲染器的核心 Diff 算法
    • 渲染器之patch
    • 图解 Vue 响应式原理
    • 图解 Vue 异步更新
    • 剖析 Vue 内部运行机制
    • vue响应式原理模拟
    • vue状态管理之vuex
    • 理解Vue的设计思想及实现Vue
    • diff算法深入
    • vue router vuex原理分析
    • Vue3初探响应式原理.
    • vue2源码分析
    • vue组件化实践
  • React

  • Webpack

  • Node

  • Javascript

  • 综合

完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

Webpack 与 Rollup 二者之间该如何选择|原理篇

文章学习导航
面试总览

30 秒速记

  • 核心判断:构建工具从入口解析依赖图,经转换和优化生成可在目标运行时加载的模块与资源
  • 原理主线:围绕 「快速上手」、「Code Splitting」、「写在最后」 建立输入、状态变化与输出之间的因果关系
  • 文章范围:对比分析了 Webpack 和 Rollup 两大前端打包工具的原理、功能和适用场景,帮助开发者根据项目需求选择合适的打包方案,并通过示例演示 Rollup 的基本用法。
  • 边界与代价:静态分析受模块语法、动态依赖和副作用声明限制;拆包过细也会增加请求和运行时成本
  • 工程落地:优化前先测构建阶段、产物组成和缓存命中,再针对解析、转换、压缩或运行时逐层处理

应用开发通常选 Webpack,类库或框架开发更适合选 Rollup。 Webpack 的工程化能力更完整,适合需要第三方模块、代码拆分和 HMR 的复杂应用;Rollup 更专注于 ES Modules,产物扁平、可读,并默认支持 Tree-shaking。我一般会让组件库用 Rollup 输出多种模块格式,让业务应用交给 Webpack。这只是经验原则,两者都能跨场景使用,最终还要看插件生态和构建需求。

这篇文章不要按 API 清单来背。先用上面的 Mind Map 建立全局结构,再通过交互 DEMO 观察正常路径和边界路径如何改变状态;阅读正文时重点核对每一步的输入、负责执行的参与者、产生的中间状态以及最终可观察结果。遇到版本敏感结论,要把“历史实现”“当前行为”和“工程兼容策略”分开说明;遇到性能或架构取舍,则用实际指标、失败现象和验证手段支撑判断。

版本校准: 旧文中的 webpack 4、JSONP 更新清单或 react-hot-loader 代码用于解释历史链路,不应直接复制到新项目。当前 webpack-dev-server 4+ 默认启用 HMR,严格 ESM 可使用 import.meta.webpackHot;生产环境不得携带 HMR runtime。以 webpack HMR 官方指南 和项目锁定版本为准。

Rollup 是一款 ES Modules 打包器。它也可以将项目中散落的细小模块打包为整块代码,从而使得这些划分的模块可以更好地运行在浏览器环境或者 Node.js 环境。

从作用上来看,Rollup 与 Webpack 非常类似。不过相比于 Webpack,Rollup 要小巧的多。因为 Webpack 在配合一些插件的使用下,几乎可以完成开发过程中绝大多数前端工程化的工作。而 Rollup 可以说仅仅是一个 ES Modules 打包器,没有更多其他的功能了。

例如,在 Webpack 中支持 HMR 这种对开发过程十分友好的功能,而在 Rollup 中就没有办法完全支持。

Rollup 诞生的目的并不是要与 Webpack 这样的工具全面竞争。它的初衷只是希望能够提供一个高效的 ES Modules 打包器,充分利用 ES Modules 的各项特性,构建出结构扁平,性能出众的类库。

至于它的其他特点和优势,我们需要上手过后才能深入了解。

# 快速上手

这里我准备了一个简单的示例,具体结构如下:

.
├── src
│   ├── index.js
│   ├── logger.js
│   └── messages.js
└── package.json
@前端进阶之旅: 代码已经复制到剪贴板

在这个示例的源代码中我准备了三个文件,并且使用 ES Modules 组织的代码模块化。部分代码如下:

// ./src/messages.js
export default {
  hi: 'Hey Guys, I am zce~'
}

// ./src/logger.js
export const log = msg => {
  console.log('---------- INFO ----------')
  console.log(msg)
  console.log('--------------------------')
}
export const error = msg => {
  console.error('---------- ERROR ----------')
  console.error(msg)
  console.error('---------------------------')
}

// ./src/index.js
import { log } from './logger'
import messages from './messages'
log(messages.hi)
@前端进阶之旅: 代码已经复制到剪贴板

如上述代码所示,其中:

  • messages.js: 文件中以默认导出的方式导出了一个对象;
  • logger.js: 文件中单个导出了两个函数成员;
  • 最后在 index.js: 文件中导入了这两个模块,并且使用了它们。

接下来,我们尝试使用 Rollup 完成这个示例应用的打包。这里需要先通过 npm 安装 rollup 这个模块。具体命令如下:

$ npm i rollup --save-dev
@前端进阶之旅: 代码已经复制到剪贴板

安装完成过后,rollup 这个模块同样会在 node_modules/.bin 目录中为我们提供一个 CLI 程序,我们就可以通过这个 CLI 去使用 Rollup 打包。具体命令如下:

$ npx rollup
@前端进阶之旅: 代码已经复制到剪贴板

P.S. 对于 node_modules/.bin 目录下的 CLI,我们可以使用 npx 命令或者 yarn 命令直接启动。

执行 rollup 命令,在不传递任何参数的情况下,这个命令会自动打印出它的帮助信息。具体如下图:

在这个帮助信息的一开始,就已经告诉我们 rollup 命令的正确用法了:我们应该通过参数指定一个打包入口文件。正确命令如下:

$ npx rollup ./src/index.js
@前端进阶之旅: 代码已经复制到剪贴板

这里指定的打包入口是 src/index.js 文件。再次执行 rollup 命令,具体执行结果如下:

根据控制台的输出结果,我们发现 Rollup 直接将打包结果打印到控制台中了。

当然,正常情况下我们还是需要将打包结果输出到一个文件中。具体就是通过 CLI 的 --file 参数指定输出文件路径,具体命令如下:

$ npx rollup ./src/index.js --file ./dist/bundle.js
@前端进阶之旅: 代码已经复制到剪贴板

这样打包的结果就会输出到文件中。

完成以后,我们找到 Rollup 打包输出的文件,具体结果如下:

在这个文件中我们的第一印象就是,Rollup 打包结果惊人的简洁,基本上就跟我们手写的代码一样。相比于 Webpack 大量的引导代码和一堆的模块函数,这里的输出结果没有任何多余代码,就是把打包过程中的各个模块按照依赖顺序,先后拼接到了一起。

而且我们仔细观察打包结果,你会发现,在我们输出的结果中只会保留那些用到的部分,对于未引用部分都没有输出。这是因为 Rollup 默认会自动开启 Tree-shaking 优化输出结果,Tree-shaking 的概念最早也就是 Rollup 这个工具提出的。

# 配置文件

Rollup 同样支持以配置文件的方式去配置打包过程中的各项参数,我们可以在项目的根目录下新建一个 rollup.config.js 的配置文件。具体结构如下:

 .
 ├── src
 │   ├── index.js
 │   ├── logger.js
 │   └── messages.js
 ├── package.json
+└── rollup.config.js
@前端进阶之旅: 代码已经复制到剪贴板

这个文件虽然同样是运行在 Node.js 环境中,但是 Rollup 会额外处理配置文件,所以在 rollup.config.js 中我们可以直接使用 ES Modules 标准。具体代码如下:

// ./rollup.config.js
export default {
  input: 'src/index.js',
  output: {
    file: 'dist/bundle.js',
    format: 'es' // 输出格式
  }
}
@前端进阶之旅: 代码已经复制到剪贴板

这个文件中需要导出一个配置对象,在这个对象中我们可以通过 input 属性指定打包的入口文件路径,通过 output 指定输出相关配置,output 属性是一个对象,在 output 对象中可以使用 file 属性指定输出的文件名,format 属性指定输出代码的格式。

完成以后,我们回到命令行,再次执行 rollup 命令,不过需要注意的是,这里需要通过 --config 参数来表明使用项目中的配置文件。你也可以通过这个参数来指定不同的配置文件名称。具体命令如下:

$ npx rollup --config # 使用默认配置文件
$ npx rollup --config rollup.prod.js # 指定配置文件路径
@前端进阶之旅: 代码已经复制到剪贴板

# 输出格式

Rollup 打包支持多种输出格式,这里我们回到配置文件中,配置同时输出所有格式下的文件,具体配置如下:

// ./rollup.config.js
// 所有 Rollup 支持的格式
const formats = ['es', 'amd', 'cjs', 'iife', 'umd', 'system']

export default formats.map(format => ({
  input: 'src/index.js',
  output: {
    file: `dist/bundle.${format}.js`,
    format
  }
}))
@前端进阶之旅: 代码已经复制到剪贴板

在这个配置当中我们导出了一个数组,数组中的每个成员都是一个单独的打包配置,这样 Rollup 就会分别按照每个配置单独打包。这一点与 Webpack 非常相似。

配置完成之后,我们回到命令行终端,再次运行 Rollup 打包。那这次打包过后,dist 目录下就会生成不同格式的输出结果,如下图所示:

你可以自己依次去了解一下每种格式的输出结果,其实不同的输出格式大都是为了适配不同的运行环境,并没有什么需要额外理解的地方。

# 使用插件

Rollup 自身的功能就只是 ES Modules 模块的合并,如果有更高级的要求,例如加载其他类型的资源文件或者支持导入 CommonJS 模块,又或是编译 ES 新特性,这些额外的需求 Rollup 同样支持使用插件去扩展实现。

Webpack 中划分了 Loader、Plugin 和 Minimizer 三种扩展方式,而插件是 Rollup 的唯一的扩展方式。

这里我们先来尝试使用一个可以让我们在代码中导入 JSON 文件的插件: @rollup/plugin-json,通过这个过程来了解如何在 Rollup 中使用插件。

首先我们需要将 @rollup/plugin-json 作为项目的开发依赖安装进来。具体安装命令:

$ npm i @rollup/plugin-json --save-dev
@前端进阶之旅: 代码已经复制到剪贴板

安装完成过后,我们打开配置文件。由于 rollup 的配置文件中可以直接使用 ES Modules,所以我们这里使用 import 导入这个插件模块。具体代码如下:

// ./rollup.config.js
import json from '@rollup/plugin-json'

export default {
  input: 'src/index.js',
  output: {
    file: 'dist/bundle.js',
    format: 'es'
  },
  plugins: [json()]
}
@前端进阶之旅: 代码已经复制到剪贴板

← Babel原理及其使用前端构建新玩法 Vite 上手与思考 →

fe
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
  • Vue

    • 从源码解读Vue生命周期
    • 组件的本质
    • 有状态组件的设计
    • 设计 VNode
    • 辅助创建 VNode 的 h 函数
    • 自定义渲染器和异步渲染
    • 渲染器之挂载
    • 渲染器的核心 Diff 算法
    • 渲染器之patch
    • 图解 Vue 响应式原理
    • 图解 Vue 异步更新
    • 剖析 Vue 内部运行机制
    • vue响应式原理模拟
    • vue状态管理之vuex
    • 理解Vue的设计思想及实现Vue
    • diff算法深入
    • vue router vuex原理分析
    • Vue3初探响应式原理.
    • vue2源码分析
    • vue组件化实践
  • React

  • Webpack

  • Node

  • Javascript

  • 综合