专注类库和框架打包之Rollup

1,179 阅读5分钟

文章内容输出来源:拉勾大前端高薪训练营

- 概述

- 也是一款ES Modules 打包器
- 也可以将项目中的一些散落的细小模块打包为整块代码
- rollup与webpack作用类似
- rollup更为小巧,仅仅是一款ESM打包器
- rollup中并不支持类似HMR这种高级特性
- rollup并不是要与webpack全面竞争
- 目标是提供一个充分利用ESM各项特性的高效打包器

- 快速上手

准备代码

  • src/message.js
export default {  
    hi: 'Hi Guys, I'm sjz' 
}
  • 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'
// 使用模块成
const msg = messages.hi
log(msg)
  • 安装rollup

    • yarn add rollup --dev

    • yarn rollup./src/index.js --format life --file dist/bundle.js

      • --format

        • 指定打包结果输出格式
      • --file

        • 指定打包结果存放的位置
  • 发现打包结果惊人的简洁,基本上就跟手写的代码一致

  • rollup自动会开启Tree Shaking

  • Tree Shaking概念最早就来源于rollup

- 配置文件

  • 项目根目录下新建配置文件rollup.config.js
  • 内容
export default {
  // 指定打包入口文件
  input: 'src/index.js',
  // 指定输出的相关配置
  output: {
    // file指定输出的文件名
    file: 'dist/bundle.js',
    // format 指定输出格式
    format: 'iife'
  }
}
  • 执行打包命令

    • yarn rollup --config

      • 必须指定选项--config来申明使用配置文件中的打包配置
    • yarn rollup --config rollup.config.js

      • 可以具体指定使用哪个文件作为打包配置文件

- 使用插件

  • 说明

    • rollup自身的功能就是ES Modules的合并打包

    • 如果项目有更高级的需求,例如

      • 加载其他类型的资源模块
      • 导入CommonJS模块
      • 编译ECMAScript新特性
    • 对于以上需求,rollup支持使用插件的方式扩展

    • 插件不是rollup唯一的扩展方式

      • 与webpack划分loader,plugin, minimizer这这三种方式不同
  • yarn add rollup-plugin-json --dev

  • 修改配置文件rollup.config.js

import json from 'rollup-plugin.json'
export default {
    // 指定打包入口文件
    input: 'src/index.js',
    // 指定输出的相关配置
    output: {
        // file指定输出的文件名
        file: 'dist/bundle.js',
        // format 指定输出格式
        format: 'iife'
    },
    plugin: [
        json()
    ]
}
  • 修改index.js文件
// 导入模块成员
import { log } from './logger'
import messages from './messages'
import { name, version } from '../package.json'
// 使用模块成员
const msg = messages.hi
log(msg)

log(name)
log(version)
  • 打包: yarn rollup --config

    • perfect:package.json文件中只有version和name被打包了

- 加载npm模块

  • rollup默认只能按照文件路径的方式加载本地的文件模块

  • 对于node_modules中的第三方模块,不能像webpack一样直接通过模块名称去导入

    • 可以借助于插件:rollup-plugin-node-resolve 实现
    • 安装插件
      • yarn add rollup-plugin-node-resolve --dev

import json from 'rollup-plugin.json'
import resolve from 'rollup-plugin-node-resolve'

export default {
    // 指定打包入口文件
    input: 'src/index.js',
    // 指定输出的相关配置
    output: {
        // file指定输出的文件名
        file: 'dist/bundle.js',
        // format 指定输出格式
        format: 'iife'
    },
    plugin: [
        json(),
        resolve()
    ]
}
  • 修改index.js文件
import _ from 'lodash_es'
import { log } from './logger'
import messages from './messages'
import { name, version } from '../package.json'
// 使用模块成员
const msg = messages.hi
log(msg)

log(name)
log(version)

log.(_camelCase.toLower('hello word')
  • yarn rollup --config

    • Ok~

- 加载CommonJS模块

  • 安装插件rollup-plugin-commonjs

    • yarn add rollup-plugin-commonjs --dev
  • 修改index.js文件

// 导入模块成员
import _ from 'lodash_es'
import { log } from './logger'
import messages from './messages'
import { name, version } from '../package.json'
import cjs from './cjs-module'
// 使用模块成员
const msg = messages.hi
log(msg)

log(name)
log(version)

log.(_camelCase.toLower('hello word'))
console.log(cjs)
  • 新建文件:cjs-module.js

    • 内容
module.exports = {
    foo: 'bar'
}
  • yarn rollup --config

    • OK~

- Code Splitting(代码拆分)

  • 在rollup最新的版本中已经支持代码拆分了

  • 同样可以使用符合ES Modules标准的动态导入(Dynamic Import)的方式去实现模块的按需加载

    • Rollup也会自动去处理代码的拆分也就是我所说的分包
  • src/index.js

import('./logger').then(({ log })⥤{
    log('Code Splitting~')
})
  • 打包

    • yarn rollup --config

      • 报错: Error: UMD and IIFE output formats are not supported for Code Splitting builds
  • 解决打包错误

    • yarn rollup --config --format amd

      • 报错: Error: You must set "output.dir" instead of "ouput.file" when generating multiple chunks
  • 解决打包错误

    • 修改配置文件rollup.config.js
import json from 'rollup-plugin.json'
import resolve from 'rollup-plugin-node-resolve'

export default {
  // 指定打包入口文件
  input: 'src/index.js',
  // 指定输出的相关配置
  output: {
    // file指定输出的文件名
    // file: 'dist/bundle.js',
    // format 指定输出格式
    // format: 'iife'
    dir: 'dist',
    format: 'amd'
  },
  plugin: [
    json(),
    resolve()
  ]
}
  • 再次打包

    • yarn rollup --config

      • OK~

- 多入口打包

  • 对于不同入口当中的那些公共部分也会自动提取到单个文件当中作为独立的bundle
  • 配置方式1
import json from 'rollup-plugin.json'
import resolve from 'rollup-plugin-node-resolve'

export default {
  // 指定打包入口文件
  input: ['src/index.js', 'src/album.js']
  // 指定输出的相关配置
  output: {
    // file指定输出的文件名
    // file: 'dist/bundle.js',
    // format 指定输出格式
    // format: 'iife'
    dir: 'dist',
    format: 'amd'
  },
  plugin: [
    json(),
    resolve()
  ]
}
  • 配置方式2
import json from 'rollup-plugin.json'
import resolve from 'rollup-plugin-node-resolve'

export default {
  // 指定打包入口文件
  // input: ['src/index.js', 'src/album.js']
  input: {
    foo: 'src/index.js',
    bar: 'src/album.js'
  },
  // 指定输出的相关配置
  output: {
    // file指定输出的文件名
    // file: 'dist/bundle.js',
    // format 指定输出格式
    // format: 'iife'
    dir: 'dist',
    // 多入口打包时这里不能使用life, 
    // 因为多入口打包时rollup内部会进行代码拆分
    format: 'amd'
  },
  plugin: [
    json(),
    resolve()
  ]
}
  • yarn rollup --config

    • OK~
  • 注意

    • 对于amd这种输出格式的文件,我们不能直接去引用到页面上
    • 必须要通过实现amd标准的库去加载
  • dist/index.html

<DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
    <!-- <script src="foo.js"></script> -->
    <script src="https://unpkgs.com/requirejs@2.3.6/require.js" data-main="foo.js"></script> 
</body>
</html>
  • serve dist

    • OK~

- 选用原则(rollup/webpack)

  • rollup

    • 优点

      • 输出结果更加扁平
      • 自动移出未引用的代码
      • 打包结果依然完全可读
    • 缺点

      • 加载非ESM的第三方模块比较复杂
      • 模块最终都被打包到一个函数中,无法实现HMR
      • 浏览器环境中,代码拆分功能依赖AMD库
  • 大多数知名框架或类库都在使用rollup

  • webpack大而全,rollup小而美

  • 开发应用程序

    • 使用webpack
  • 开发一个框架或类库

    • 使用rollup