2023-08-18
前端工程化
00
请注意,本文编写于 189 天前,最后修改于 188 天前,其中某些信息可能已经过时。

目录

Rollup与Webpack异同
配置文件
常见插件
rollup集成babel
如何编译TS
实现一个类库

本文介绍Rollup的一些配置及常见插件,最后使用Rollup实现一个类库和Vue3的UI组件库。

中文官网
Rollup是一个JavaScript的模块化打包工具,通常用它来打包类库

Rollup与Webpack异同

  • Rollup主要针对ES Module进行打包的;
  • 另外Webpack通常通过各种loader处理各种各样的文件以及他们的依赖关系;Rollup更多时候是专注于处理JS代码(当然也可以处理cssfontvue等文件)
  • Rollup的配置和理念相对于webpack来说,更加的简洁和容易理解;
  • 在早期webpack不支持TreeShaking时, rollup具备更强的优势;
  • 在实际项目开发中我们通常使用webpack ;而对类库文件进行打包时我们通常使用rollup

相同点

  • rollup 支持代码分割(分包)
  • 支持多入口打包
  • 导出格式(esmamdcjsiifeumd
javascript
// ./src/index.js // 动态导入的模块会自动分包 import('./logger').then(({ log }) => { log('code splitting~') })

配置文件

npm i -D rollup

  • webpackbabel不同,rollupcorecli在同一个包中

  • 配置文件 rollup.config.js

  • npx rollup --config rollup.config.js # 使用默认配置文件

支持所有输出格式

javascript
// ./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 } })) // 方式二 export default { input: 'src/index.js', output: [...] }

关于rollup 这里有一个极简上手demo

常见插件

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

  • @rollup/plugin-node-resolve 加载NPM模块
  • @rollup/plugin-commonjs   加载 CommonJS 模块
    • 如果打包umd 出现了require语句,可能是你没有引用该包
  • @rollup/plugin-json     加载JSON模块
  • @rollup/plugin-terser     代码压缩
  • rollup-plugin-postcss     处理css文件
    • 默认会读取postcss.config.js文件,这个文件又会根据browserslist给样式打补丁
    • postcss.config.js 种可以配置cssnano 压缩 css 还可以配置 postcss-preset-env
    • 它还默认支持了scssless 有了它你可以忘掉 rollup-plugin-scssrollup-plugin-less
  • rollup-plugin-vue2 vue-template-compiler
    • 处理vue2文件
  • rollup-plugin-vue @vue/compile-sfc
    • 处理vue3文件
    • 对于sfc文件要配合 rollup-plugin-stylesrollup-plugin-postcss
  • rollup-plugin-peer-deps-external 处理对等依赖
  • rollup-plugin-styles     处理样式,独立出来或者插入 html某个节点中
  • rollup-plugin-replace     代码动态替换(如 process.env.NODE_ENV
    • 相当于webpack.DefinePlugin

rollup集成babel

我们通常使用babeles6+代码转换成es5以便能在低版本的浏览器上运行。关于babel如果你还不太了解,可以看我的另一篇文章 《babel深入浅出》

@rollup/plugin-babel 用于rollupbabel之间的无缝集成

为什要使用@rollup/plugin-babel
我们先讨论下不使用翻译es6+代码的两种方案

  1. 首先通过Babel运行代码,注意排除模块转换器
  2. 或者通过Rollup运行代码,然后再用babel处理代码

以上两种方式都有缺点

  • 第一种情况除了配置项复杂外,你最终会在整个代码中重复注入polyfill(比如使用了Object.hasOwn方法的每个文件都会引入一次polyfill
  • 第二种情况转译会更慢,因为对于Babel来说转译一个大文件对与转译几个小文件来说需要更多的时间和空间开销
  • 无论哪种方式,您都必须担心放置中间文件的位置,并且让 sourcemaps表现得非常痛苦

使用@rollup/plugin-babel会使整个过程更加容易

javascript
// 1. package.json 配置script脚本 // "build": "rimraf lib/* && rollup -c" // 2. rollup.config.js const {babel} = require('@rollup/plugin-babel'); const nodeResolve = require('@rollup/plugin-node-resolve'); const commonjs = require("@rollup/plugin-commonjs"); const path = require('path'); const resolve = function(...args) { return path.resolve(__dirname, ...args); }; export default [ { input: resolve('./src/index.js'), output: { file: resolve("lib/bundle.umd.js"), format: 'umd', name: '$mylib', }, plugins: [ nodeResolve.default({ browser: true, }), commonjs(), babel({ babelHelpers: 'runtime', exclude: 'node_modules/**', }), ], } ]; // 3. babel.config.js module.exports = { "presets": [ ["@babel/preset-env", { "modules": false, }], ], plugins: [ [ '@babel/plugin-transform-runtime', { corejs: { version: 3, proposals: true, // 支持预设 }, useESModules: true, } ], ] } // 4. package.json配置browserslist // "browserslist": [ // "Android >= 6", // "ios >= 11", // ">0.5%" // ],

如何编译TS

rollup编译TS有两个方案

  1. 使用插件rollup-plugin-typescript
  2. 使用babel编译TS

在研究这两个方案前,我们先了解一下背景

  • 除了babel可以将es6转换成es5外,typescript也有这个能力
  • 相比babel而言,typescriptes5灵活性差很多,为不支持插件能力,还有一个硬伤是不支持为es6API提供垫片。更多差异可以看我的另一篇文章《babel如何编译TS》

通过实测发现rollup-plugin-typescript配置该插件虽然能正常打包,但是打包的过程babe.config.js .browserslist配置无效,
使用 @babel/preset-typescript无法生成声明文件,解决方案是 使用 npx tsc命令 单独生成声明文件
npx tsc --declaration -p ./ -t esnext --emitDeclarationOnly --outDir types

有了上面的基础我们来实现一个类库吧

实现一个类库

中文官网给处理 Rollup 构建应用及类库的示例,但是配置太过于简单。
笔者尝试升级了一下类库的配置,支持 babelts

JS版类库
https://github.com/guojingwen/frondend-project/tree/main/rollup_js_lib

  • 支持es6 句法
  • 支持es6 API
  • 支持cmdumdamdesm
  • 支持browserslist

TS版类库
https://github.com/guojingwen/frondend-project/tree/main/rollup_ts_lib

  • 支持前面JS版本所有功能
  • 支持TS & 自动生成声明文件
  • 支持排除依赖包构建

打包一个Vue3 UI库
https://github.com/guojingwen/frondend-project/tree/main/rollup_ts_vue3_ui_lib

  • 支持es6 句法
  • 支持es6 API
  • 支持TS & 自动生成声明文件
  • 支持cmd umd amd``esm
  • 排除对等依赖构建(vue3 element-plus)
  • 支持 postcss postcss-preset-env cssnano scss

本文作者:郭敬文

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!