Rollup

Rollup 是一个用于 JavaScript 的模块打包工具,它将小的代码片段编译成更大、更复杂的代码,例如库或应用程序。

Posted by page on July 14, 2023

Rollup

基础

命令行

全局安装:npm i rollup -g

局部安装:npm i rollup -D

打包命令:rollup src/main.js --file bundle.js --format umd

配置文件

新增配置:rollup.config.mjs

export default {
  input: "src/main.js",
  output: {
    file: "dist/bundle.js",
    format: "esm",
  },
};

打包命令:rollup --config

区分环境:

"scripts": {
  "build:staging": "rollup -c -w", // -w 开启watch 默认配置文件rollup.config.mjs
  "build:staging": "rollup -c rollup.staging.mjs",
  "build:prod": "rollup -c rollup.prod.mjs"
},

核心配置

input

bundle 入口文件,支持多入口(数组或对象类型时)

external

匹配需要排除在 bundle 外部的模块,匹配成功的模块将作为外部依赖,不被打包到bundle 中,而是在 bundle 中作为外部依赖被直接引用

注: 当创建 iife 或 umd 格式的 bundle 时,需要 output.globals 选项提供全局变量名,以替换掉外部引入。使用时则需将提供对应全局变量的依赖并置前引入

output

  • dir: chunk 被放置目录,多个chunk时必需。否则 file 选项即可

  • file: 指定输出的文件,支持包含路径

  • format: 生成的 bundle 的格式,默认 “es”

  • globals: 适用于 umd / iife 格式,定义外部依赖的全局变量名供 bundle 访问

    external: ['jquery'],
    output: {
      format: 'iife',
      name: 'MyBundle',
      globals: {
        jquery: '$'
      }
    }
    
  • name: 输出格式为 iife / umd 必需,定义访问输出的 bundle 的全局变量名

输出类别

output: {
  chunkFileNames: "js/[name]-[hash].js",
  entryFileNames: "js/[name]-[hash].js",
  assetFileNames: "[ext]/[name]-[hash].[ext]",
}

插件

plugins

使用 插件列表,在捆绑过程的关键点更改 Rollup 的行为

安装插件:npm i @rollup/plugin-terser

插件配置:

import terser from '@rollup/plugin-terser';
import resolve from "@rollup/plugin-node-resolve";

export default {
  input: "src/main.js",
  output: [
    {
      file: "dist/bundle.js",
      format: "esm",
    },
    {
      file: "dist/bundle.min.js",
      format: "iife",
      name: "XEdior",
      plugins: [ terser() ] // 输出插件
    }
  ],
  plugins: [ resolve() ]
};

@rollup/plugin-terser

对输出的代码进行压缩和混淆

@rollup/plugin-node-resolve

帮助 Rollup 解析和处理 Node.js 模块的导入路径,包括支持多种模块格式,识别并查找外部依赖,处理别名和扩展等

@rollup/plugin-commonjs

rollup仅支持ES6模块化规范,引入CJS模块的npm包须借助该插件转换能力实现支持

@rollup/plugin-eslint

@rollup/plugin-babel

Rollup 中实现 Babel 对代码转换,支持对输入代码与输出代码2种转换

npm i @rollup/plugin-babel -D

getBabelOutputPlugin

对 Rollup 输出代码转换

// rollup.config.mjs
import { getBabelOutputPlugin } from "@rollup/plugin-babel";
export default {
  input: "src/main.js",
  output: [],
  plugins: [
    resolve(),
    getBabelOutputPlugin({
      configFile: './babel.config.js'
    })
  ],
};

@babel/preset-env + @babel/plugin-transform-runtime

// babel.config.json
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": "> 0.25%, not dead",
        "loose": true
      }
    ]
  ],
  "plugins": [["@babel/plugin-transform-runtime", { "corejs": 3 }]]
}

注: transform-runtime 方案仅适用于 cjs/esm 模块,对于其它模块(如:iife)实现 babel 转换,需添加 allowAllFormats 参数

// rollup.config.mjs
import { getBabelOutputPlugin } from "@rollup/plugin-babel";
import terser from "@rollup/plugin-terser";

export default {
  ......
  output: {
    file: "dist/xxx.min.js",
    format: "iife",
    name: "xxx",
    plugins: [
      getBabelOutputPlugin({
        allowAllFormats: true,
        configFile: './babel.config.js' // preset-env方案
      }),
      terser(),
    ],
    extend: true,
  }
}

@rollup/plugin-html

创建 HTML 文件,注入 Rollup bundle

import fs from "fs";
import html, { makeHtmlAttributes } from "@rollup/plugin-html";

export default {
  input: "demo/main.js",
  output: {
    dir: "demo/dist",
    format: "iife",
  },
  plugins: [
    ......
    // 配置项创建
    html({
      title: "Demo",
      attributes: { html: { lang: "zh-cmn-Hans" }, script... },
      meta: [
        { charset: "utf-8" },
        { name: "viewport", content: "width=device-width, initial-scale=1.0" },
      ],
    }),
    // 基于模板创建
    html({
      template: ({ files, attributes, publicPath }) => {
        const scripts = (files.js || [])
          .map(({ fileName }) => {
            const attrs = makeHtmlAttributes(attributes.script);
            return `<script src="${publicPath}${fileName}"${attrs}></script>`;
          })
          .join("\n");
        const links = (files.css || [])
          .map(({ fileName }) => {
            const attrs = makeHtmlAttributes(attributes.link);
            return `<link href="${publicPath}${fileName}" rel="stylesheet"${attrs}>`;
          })
          .join("\n");
        let htmlString = fs.readFileSync("demo/public/index.html", "utf-8");
        htmlString = htmlString.replace(`\${links}`, links);
        htmlString = htmlString.replace(`\${scripts}`, scripts);
        return htmlString;
      },
    }),
    ......
  ],
};

rollup-plugin-generate-html-template

定义html模板生成注入bundle的html文件

rollup-plugin-postcss

通过 postcss 为rollup提供强大处理css模块能力,额外支持sass、less等

npm i postcss rollup-plugin-postcss -D

// rollup.config.mjs
plugins: [
  postcss({ extract: true, to: "dist/main.css" }),
]

插件配置

extract:是否CSS Module 单独文件输出

to:输出目录备注项,提供 postcss plugins 信息帮助

:单独配置文件 postcss.config.js,仅支持对 postcss plugins 配置项

postcss-url

处理css中文件(字体、图片)url,控制输出目录依赖文件位置以及url

@rollup/plugin-url

使rollup支持导入文件(如图片、字体等静态资源)转换为基于URL的模块

它会复制静态资源到指定的输出目录,并在 JavaScript 中以 URL 替换原来的导入路径

import img from './myImage.png';
// "x/xx/myImage.png"

@rollup/plugin-image

图片模块转为 base64 格式 dom内容引入

rollup-plugin-html

用于加载 HTML 文件内容的 Rollup 插件,可在 JavaScript 代码中用作字符串变量

rollup-plugin-svg-to-symbol

svg 图片转 symbol内容引入

import svgToSymbol from "rollup-plugin-svg-to-symbol";

{
  ......

  plugins: [
    svgToSymbol()
  ]
}

使用:

` `

import undo from "../images/svg/undo.svg";
import redo from "../images/svg/redo.svg";

const symbols = [
  undo,
  redo
].join("");

document.body.insertAdjacentHTML(
  "beforeend",
  `<svg xmlns="http://www.w3.org/2000/svg" style="display: none">${symbols}</svg>`
);

rollup-plugin-watch

rollop.watch 仅会监听入口文件引用的模块,对于 assets 类资源修改不被监听,该插件支持监听指定目录修改时重新构建

import watch from "rollup-plugin-watch";
{
  ...
  plugins: [ watch({ dir: "public" }) ]
}

rollup-plugin-livereload

收到rollup watch更新通知时自动刷新浏览

import livereload from "rollup-plugin-livereload";
// plugins
{
  watch({ dir: "public" }), // 额外监听public目录
  livereload("dist"),
  serve("dist"),
}

rollup-plugin-serve

为 Rollup bundle 输出提供开发服务

// roullup.dev.mjs
import html from "@rollup/plugin-html";
import serve from "rollup-plugin-serve";

export default {
  input: "demo/main.js",
  output: {
    dir: "demo/dev-server", // 开发环境输出目录
    format: "iife",
  },
  plugins: [
    html({ ... }),
    serve("demo/dev-server")
  ],
};

rollup-plugin-clear

rollup打包资源时清除指定目录

clear({ targets: ["dist"] })

配置

代码分割

自动分割:动态加载或多个入口文件

手动分割:output.manualChunks 手动控制

output: [
  {
    dir: "dist", // 多chunk必需
    format: "esm",
    entryFileNames: "HyperTextEditor.js", // 入口文件的模式
    chunkFileNames: "[name].[hash].js",  // 分割 chunk 的命名模式
    manualChunks: {
      "lodash-utils": ["lodash-es"], // 匹配自定义的公共 chunk
    },
  }
]