Rollup 的基本使用

1,168 阅读8分钟

🥇 Rollup 与 Webpack

Rollup官方解析:Rollup 是一个 JavaScript 模块打包器,可以将小块代码编译成大块复杂的代码,例如 library 或应用程序

webpack官方解析:webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。

🥇 应用场景对比

使用Rollup的开源项目:

  1. vue
  2. vuex
  3. vue-router 使用webpack的项目:
  4. ElementUI
  5. mint-ui
  6. vue-cli

从上面使用场景可以大概分析出,Rollup 偏向应用于js库,webpack 偏向应用于前端工程,UI 库;

如果你的应用场景中只是 js 代码,希望做 ES 转换,模块解析,可以使用 Rollup。

如果你的场景中涉及到 css、html,涉及到复杂的代码拆分合并,建议使用 webpack。

🥇 安装和使用

初始化项目包:npm init

安装 rollup:npm i rollup -D

创建 rollup 配置文件:rollup.config.js

export default {
  input: "", // 入口
  output: {}, // 出口
  plugins: [], // 各种插件使用的配置
  external: [], // 外部依赖的配置
  global: {}, // 全局变量的配置
};

🥇 入口的配置

Rollup 的入口配置的 key 同 webpack 的不同,Rollup 的入口是 input,而 webpack 是 entry。

🥈 单个入口配置

单个入口的配置只需要为 input 指定一个入口文件即可

export default {
  input: "src/main.js", // 
  output: {
    file:'dist/main.js' // 一个入口指定一个出口
  }, 
};

🥈 多个入口配置

多个入口配置需要将导出的配置设置为数组,数组的项为一个对象,每一个对象都可以单独配置,例子如下:

export default [
  {
    input: "src/main1.js",  // 入口 1
    output: {
      file: "dist/main-one.js", // 出口 1
    }, 
  },
  {
    input: "src/main2.js", // 入口 2
    output: {
      file: "dist/main-two.js", // 出口 2
    }, 
  },
];

🥇 出口的配置

出口的配置字段为 output,output 可以是一个对象也可以是一个数组,分别对应一个出口和多个出口。 出口配置的各字段解释:

  • file:出口的地址以及打包的名字
  • format:打包的格式,格式分为五种分别为:amd / es / cjs / iife / umd
  • name:当 format 为 iife 和 umd 时必须提供,将作为全局变量挂在window(浏览器环境)下
  • sourcemap:生成 main.map.js 文件,方便调试
  • banner:为打包好的文件添加注释,注释的位置在整个文件的首行
  • footer:为打包好的文件添加注释,注释的位置在整个文件的尾行
  • intro:为打包好的文件添加注释,注释的位置在打包数据内容的头部
  • outro:为打包好的文件添加注释,注释的位置在打包数据内容的末尾

注:banner、footer、intro、outro 可以不用配置在出口中,具体在后文中讲解。

🥈 单个出口配置

单个出口的配置需要将 output 指定为一个对象,对象的每一个 key 都是出口的配置。

export default {
  input: "src/main.js",
  output: {
    file: "dist/main.js",
    format: "es", 
    name: "A", 
    sourcemap: true, 
    banner: "// 文件的首行",
    footer: "// 文件的尾行",
    intro: "// 内容的头部",
    outro: "// 内容的末尾",
  },
};

🥈 多个出口配置

多出口配置需要将 output 配置设置为数组,数组的项为一个对象,每一个对象都可以单独配置,例子如下:

export default {
  input: "src/main.js",
  output: [
    {
      file: "dist/main1.js",
      // ...
    },
    {
      file: "dist/main2.js",
      // ...
    },
  ],
};

🥇 external 的配置

有些场景下,虽然我们使用了 resolve 插件,但可能我们仍然想要某些库保持外部引用状态,这时我们就需要使用 external 属性,来告诉 rollup.js 哪些是外部的类库。

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

export default {
  input: "src/main.js",
  output: {
    file: "dist/main.js",
    format: "es",
  },
  plugins: [resolve()],
  external: ["the-answer"],
};

下图中我们通过 resolve 插件引入了一个外部库 the-answer 如果我们不通过 external 告诉 rollup 我们引入的库需要保持外部引入的话,rollup 会读取库的代码打包到我们的文件中,这样会造成文件过大。如果我们通过 external 告诉 rollup 的话,rollup 会将我们引入的库保持外部引入的状态打包。

🥇 global 属性

export default {
  input: "src/main.js",
  output: {
    file: "dist/main.js",
    format: "es",
  },
  global:{
    "$":"jquery" // 告诉 rollup 全局指令 $ 就是 jquery
  }
};

🥇 插件详解

请尽量使用官方插件:github.com/rollup/plug…

🥈 支持导入远程库

🥉 @rollup/plugin-node-resolve

安装:npm i -D @rollup/plugin-node-resolve

配置 rollup.config.js:

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

export default {
  input: "src/main.js",
  output: {
    file: "dist/main.js",
    format: "es",
  },
  plugins: [resolve()],
};

resolve 插件的作用

正常我们打包的对象是本地的 js 代码和库,但实际开发中,不太可能所有的库都位于本地,我们大多会通过 npm 下载远程的库。

与 webpack 和 browserify 这样的其他捆绑包不同,rollup 不知道如何打破常规去处理这些依赖。因此我们需要添加一些配置。

首先在我们的项目中添加一个依赖 jquery,然后修改 src/main.js 文件

import answer from "the-answer";

export default function () {
  console.log("answer " + answer);
}

执行 npm run build 后会报如下错误

打包后的 main.js 仍然会在 Node.js 中工作,但是 jquery 不包含在包中。为了解决这个问题,将我们编写的源码与依赖的第三方库进行合并,rollup.js 为我们提供了 resolve 插件。

首先,安装 resolve 插件:npm i -D @rollup/plugin-node-resolve

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

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

export default {
 input: "src/main.js",
  output: {
    file: "dist/main.js",
    format: "es",
  },
  plugins: [resolve()],
};

再次打包就不会报错了

🥈 支持非es模块化

🥉 @rollup/plugin-commonjs

安装:npm i -D @rollup/plugin-commonjs

配置 rollup.config.js:

import commonjs from "@rollup/plugin-commonjs";
export default {
  input: "src/main.js",
  output: {
    file: "dist/main.js",
    format: "es",
  },
  plugins: [commonjs()],
};

commonjs 插件的作用

rollup.js 编译源码中的模块引用默认只支持 ES6+ 的模块方式 import/export。然而大量的 npm 模块是基于 CommonJS 模块方式,这就导致了大量 npm 模块不能直接编译使用。

因此使得 rollup.js 编译支持 npm 模块和 CommonJS 模块方式的插件就应运而生:@rollup/plugin-commonjs。

🥈 js兼容

🥉 @rollup/plugin-babel

安装:npm i -D @rollup/plugin-babel @babel/core @babel/preset-env

安装 @rollup/plugin-babel 后,在安装 @babel/core,因为 @babel/core 是 babel 的核心,都安装好以后创建一个 .babelrc 文件,用于配置 babel,我们看.babelrc配置了preset env,所以要安装这个插件,都安装成功后,babel 插件才可以正常工作。

// .babelrc 
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "modules": false, // 将此设置为 false 将保留 ES 模块。 仅当您打算将本机 ES 模块发送到浏览器时才使用此选项。
        "useBuiltIns": "usage", // @babel/preset-env 编译新的 API 使用 core-js 这个库需要安装 corejs 库, 默认使用 core-js2 版本的库
        "corejs": 3 // 告诉 @babel/preset-env 使用 corejs3 版本
      }
    ]
  ]
}

配置 rollup.config.js:

import babel from "@rollup/plugin-babel";
export default {
  input: "src/main.js",
  output: {
    file: "dist/main.js",
    format: "es",
  },
  plugins: [
    babel({
      exclude: "node_modules/**", // 排除 node_modules 文件夹下的文件
    }),
  ],
};

babel 插件的作用

Babel:www.babeljs.cn/docs/

Babel 是一个工具链,主要用于将采用 ECMAScript 2015+ 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。

🥉 rollup-plugin-buble

安装:npm i -D rollup-plugin-buble

配置 rollup.config.js:

import buble from "rollup-plugin-buble";

export default {
  input: "src/main.js",
  output: {
    file: "dist/main.js",
    format: "es",
  },
  plugins: [buble()],
};

🥈 支持导入json

🥉 @rollup/plugin-json

安装:npm i -D @rollup/plugin-json

配置 rollup.config.js:

import json from "@rollup/plugin-json";
export default {
  input: "src/main.js",
  output: {
    file: "dist/main.js",
    format: "es",
  },
  plugins: [json()],
};

json 插件的作用

没有 json 插件的支持我们在导入 json 文件时会报错,所以需要安 json 插件来支持 json 文件的导入

[!] Error: Unexpected token (Note that you need @rollup/plugin-json to import JSON files)
// [!] Error: Unexpected token (注意你需要 @rollup/plugin-json 来导入JSON文件)

🥈 支持别名

🥉 rollup-plugin-alias

安装:npm i -D rollup-plugin-alias

配置 rollup.config.js:

import alias from "rollup-plugin-alias";
const path = require("path");

const pathResolve = (p) => path.resolve(__dirname, p);
export default {
  input: "src/main.js",
  output: {
    file: "dist/main.js",
    format: "es",
  },
  plugins: [
    alias({
      resolve: [".jsx", ".js"], // 可选,默认情况下这只会查找 .js 文件或文件夹
      entries: {
        "@": pathResolve("src"),
        _: __dirname,
      },
    }),
  ],
};

alias 插件的作用

alias 插件提供了为模块起别名的功能,用过 webpack 的应该对这个功能非常熟悉

🥈 代码压缩

🥉 rollup-plugin-terser

安装:npm i -D rollup-plugin-terser

配置 rollup.config.js:

import { terser } from "rollup-plugin-terser";
export default {
  input: "src/main.js",
  output: {
    file: "dist/main.js",
    format: "es",
  },
  plugins: [terser()],
};

🥈 代码检查

🥉 rollup-plugin-eslint

安装:npm i -D rollup-plugin-eslint

另外,需要创建 .eslintrc 文件配置 eslint 规则

// .eslintrc 
module.exports = {
  root: true,
  parserOptions: {
    "ecmaVersion": 6, 		// 支持es6
    "sourceType": "module"	// 使用 es6 模块化
  },
  env: { // 设置环境
    "browser": true,   // 支持浏览器环境: 能够使用window上的全局变量
    "node": true       // 支持服务器环境:  能够使用node上global的全局变量
  },
  extends: : "eslint:recommended", // 使用 eslint 推荐的默认规则 https://cn.eslint.org/docs/rules/
  globals: {	// 声明使用的全局变量, 这样即使没有定义也不会报错了
    "$": "readonly"	// $ 只读变量
  },
  rules: {  // eslint检查的规则  0 忽略 1 警告 2 错误
    "no-console": 0, 	// 不检查 console
    "eqeqeq": 2,	// 用 == 而不用 === 就报错
    "no-alert": 2 // 不能使用 alert
  },
}

配置 rollup.config.js:

import eslint from "rollup-plugin-eslint";
export default {
  input: "src/main.js",
  output: {
    file: "dist/main.js",
    format: "es",
  },
  plugins: [
    eslint({
      include:['src/**/*.js'] // 需要检查的部分
  	})
  ],
};

🥈 热更新

🥉 rollup-watch

安装:npm i -D rollup-watch

配置 package.js:

"scripts": {
  "dev": "rollup -c -w",
},

🥈 开启本地服务器

🥉 rollup-plugin-serve

安装:npm i -D rollup-plugin-serve

配置 rollup.config.js:

import serve from "rollup-plugin-serve";
export default {
  input: "src/main.js",
  output: {
    file: "dist/main.js",
    format: "es",
  },
  plugins: [
    serve({ 
      open: true, // 是否打开浏览器
      contentBase: "./", // 入口 html 文件位置
      historyApiFallback: true, // 设置为 true 返回 index.html 而不是 404
      host: "localhost", // 
      port: 3000 // 端口号
    })
  ],
};

🥈 实时刷新页面

🥉 rollup-plugin-livereload

安装:npm i -D rollup-plugin-livereload

实时刷新页面,配合 rollup-plugin-serve 使用

配置 rollup.config.js:

import serve from "rollup-plugin-serve";
import livereload from "rollup-plugin-livereload";
export default {
  input: "src/main.js",
  output: {
    file: "dist/main.js",
    format: "es",
  },
  plugins: [
    serve({ 
      open: true, // 是否打开浏览器
      contentBase: "./", // 入口 html 文件位置
      historyApiFallback: true, // 设置为 true 返回 index.html 而不是 404
      host: "localhost", // 
      port: 3000 // 端口号
    }),
    livereload()
  ],
};

🥈 删除调试器语句和函数

🥉 @rollup/plugin-strip

安装:npm install @rollup/plugin-strip --save-dev

实时刷新页面,配合 rollup-plugin-serve 使用

配置 rollup.config.js:

import strip from "@rollup/plugin-strip";
export default {
  input: "src/main.js",
  output: {
    file: "dist/main.js",
    format: "es",
  },
  plugins: [
    strip({
      exlude: "node_modules/**",
    }),
  ],
};