【架构师(第三十五篇)】 业务组件库开发之使用 Rollup 进行打包

2,187 阅读3分钟

打包工具简介与对比

Webpack

大型 SPA 项目的模块化构建,也就是常说的 web 应用。

  • 通过各种 loader 处理各种各样的静态资源
  • 通过各种插件 plugins 对整体文件进行一些处理
  • Code splitting 将公共模块进行提取
  • 提供一个 webpack-dev-server ,进行本地开发
  • 支持 HMR 模块热替换

Rollup

Rollup 设计之初就是面向 ES Module 的,构建出结构扁平,性能出众的类库。

ES Module 的规则

  • import 只能作为模块顶层的语句出现,不能出现在 function 里或者 if 里。
  • import 的模块名只能是字符串常量。
  • 不管 import 的语句位置出现在哪里,在模块初始化的时候,所有的 import 都必须导入完成。

使用工具静态分析的过程

  • Tree shaking ,摇树,让死了的叶子掉下来。
  • 目的就是将 ES Module 打包生成特定的 JS 模块文件,并最大程度的减小体积。

Webpack VS Rollup

通过以上的对比可以得出,构建App应用时,webpack 比较合适,如果是类库(纯js项目),rollup 更加合适。

Webpack 的优势

  • 强大的生态插件
  • 面向开发应用的特性支持 HMR,按需加载,公共模块提取。
  • 简化 web 开发的环节,图片自动转 base64,资源的缓存(添加 chunkID)。

Rollup 的优势

  • 构建高性能的模块文件,这正是类库所需要的。
  • 编译出来的代码可读性好,内容更小,执行效率更高。
  • 配置简单。

SnowPack

开发环境

  • 利用新版本浏览器支持 ES Module 的特性。
  • 不会被打包。
  • 每个文件编译一次,永久被缓存。
  • 当一个文件修改的时候,只需要重新 build 那一个文件。

处理 node_modules 中的模块

  • 扫描 node_modules 中的模块,找到使用的模块。
  • 将每个模块都分别转换成单个的 js 文件。
  • 这些文件都是 esm 模块,可以被最新的浏览器直接使用。

为生产环境 build 代码

  • 默认情况下,和开发环境生成的代码几乎是一致的。
  • 提供了插件,生成 bundle,全浏览器兼容的代码。

打包什么类型的模块

  • 首要格式:ES Module,并且提供支持 typescripttype 文件。
  • 备选方案:UMD

Rollup 配置文件和插件

rollup.config.js

默认的配置文件

// 打包 vue 文件
import vue from 'rollup-plugin-vue'
// 打包 css
import css from 'rollup-plugin-css-only'
// 打包 ts 文件
import ts from 'rollup-plugin-typescript2'
// 打包依赖
import { nodeResolve } from '@rollup/plugin-node-resolve'
// 文件名称
import { name } from './package.json'

// 文件
const file = type => `dist/${name}.${type}.js`

export { name, file }

// 开启 ts 的类型声明文件打包
const overrides = {
  compilerOptions: {
    declaration: true
  },
  exclude: ['src/main.ts', 'node_modules', 'src/App.vue']
}

export default {
  input: "src/index.ts",
  output: {
    name,
    file: file('esm'),
    format: "es"
  },
  plugins: [
    nodeResolve(),
    vue(),
    css({ output: 'bundle.css' }),
    ts({ tsconfigOverride: overrides })
  ],
  // 排除需要打包的第三方库
  // external: (id) => {
  //   return /^vue/.test(id)
  // }
  external: ['vue', 'lodash-es']
}

rollup.umd.config.js

生成 umd 规范的组件库

import baseConfig, { file } from './rollup.config'

export default {
  ...baseConfig,
  output: {
    name: 'LegoComponents',
    file: file('umd'),
    format: 'umd',
    // 第三方库的全局变量名称
    globals: {
      'vue': "Vue",
      'lodash-es': '_'
    },
    // 组件库的全局变量名称
    exports: 'named'
  },
}

rollup.esm.config.js

生成 esm 规范的组件库

import baseConfig, { name, file } from './rollup.config'

export default {
  ...baseConfig,
  output: {
    name,
    file: file('esm'),
    format: 'es'
  }
}

package.json

package.json 内容

  • 新建 buildbuild:esmbuild:umd 命令
  • peerDependencies 用于第三方库,前置依赖,本地不安装
  • 可以添加到 devDependencies,来进行本地安装
{
  "name": "lego-component",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "npm run clean && npm run build:esm && npm run build:umd",
    "lint": "vue-cli-service lint",
    "build:esm": "rollup --config rollup.esm.config.js",
    "build:umd": "rollup --config rollup.umd.config.js",
    "clean": "rimraf ./dist"
  },
  "peerDependencies": {
    "vue": "^3.2.37"
  },
  "dependencies": {
    "ant-design-vue": "^3.2.6",
    "core-js": "^3.6.5",
    "lodash-es": "^4.17.21"
  },
  "devDependencies": {
    "vue": "^3.2.37"
  }
}