Rollup打包学习梳理

262 阅读4分钟

rollup.js 是一款简单易用的 ES 模块打包工具。

Rollup的安装

npm安装即可,我这边是全局安装的4.12.0版本

Rollup的基本使用

最基础的功能

可以直接使用rollup命令rollup main.js --file bundle.js,直接将两个文件打包成一个文件

打包前

// TestA.js
export const logFunction = () => {
  console.log("123");
};

// main.js
import { logFunction } from "./src/TestA";
logFunction();

打包后

// bundle.js
const logFunction = () => {
  console.log("123");
};

logFunction();

使用config配置文件

实际的打包配置比较复杂,使用配置文件会方便一点。

//rollup.config.js
export default {
  input: "main.js",
  output: [
    {
      file: "dist/esm/index.js",
    },
  ],
  plugins: [],
};

打包命令pnpm rollup -c 但会提示错误

RollupError: Node tried to load your configuration file as CommonJS even though it is likely an ES module. To resolve this, change the extension of your configuration to ".mjs", set "type": "module" in your package.json file or pass the "--bundleConfigAsCjs" flag.

这个时候在package.json中,添加"type": "module",声明项目中的所有.js文件都使用Es Modules就可以正常打包了。

{
  "name": "hy-rollup",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "module", // 添加配置
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

打包format Todo

使用插件

Rollup的基础功能只是一个ESM打包器,有些复杂场景就需要使用rollup插件来处理了。

打包Typescript

首先新建三个Ts文件

// TestA.ts
const testA = (number: number): string => {
  console.log(number);
  return "num is " + number;
};

export default testA;


// TestB.ts
import testA from "./TestA";

export const testB = (...params: any) => {
  testA(10);
  console.log(params);
};

export let testBB = "testBB";

// main.ts
import { testB } from "./src/TestB";

testB();

然后再调用原有命令,会报错。这个时候就需要用rollup插件来处理了。首先安装1个rollup插件和两个ts依赖

pnpm add @rollup/plugin-typescript
pnpm add tslib -D
pnpm add typescript -D

然后再执行pnpm rollup -c,就可以正常的打包了。打包结果如下。

var testA = function (number) {
  console.log(number);
  return "num is " + number;
};

var testB = function () {
  var params = [];
  for (var _i = 0; _i < arguments.length; _i++) {
    params[_i] = arguments[_i];
  }
  testA(10);
  console.log(params);
};

testB();

通过ts配置文件控制ts编译

如果我们想对ts编译做控制,可以使用npx tsc --init命令,在根栏目创建一个tsconfig.js配置文件。

初始化的配置文件,这里我把注释都删掉了。

{
  "compilerOptions": {
    "target": "es2016",
    "module": "commonjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}

但是这样打的包会变成这个样子,明显不是我们想要的。

Object.defineProperty(exports, "__esModule", { value: true });
const TestB_1 = require("./src/TestB");
(0, TestB_1.testB)();

可以猜测下,@rollup/plugin-typescript插件里的默认读取的ts配置和tsc默认生成的不同,这个时候就需要研究下tsconfig.json里面的参数了。研究过后发现,只要修改以下两个参数,就能打包成我们想要的样子了。

// tsconfig.json
{
  "compilerOptions": {
    "target": "ES5", // 想要的编译后的结果
    "module": "ES6", // 使用什么模块处理模式
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "moduleResolution": "Bundler"
  }
}

此外,上面的配置文件,我还偷偷的加上了"moduleResolution": "Bundler"配置,它以让你使用 exports 声明类型的同时,使用相对路径模块可以不写扩展名。 具体可以看这篇文章

@rollup/plugin-alias

通过@rollup/plugin-alias插件可以给import路径设置别名

import alias from '@rollup/plugin-alias';

export default {
  input: 'src/index.js',
  output: {
    dir: 'output',
    format: 'cjs'
  },
  plugins: [
    alias({
      entries: [
        { find: 'utils', replacement: '../../../utils' },
        { find: 'batman-1.0.0', replacement: './joker-1.5.0' }
      ]
    })
  ]
};

@rollup/plugin-node-resolve

这个插件可以让我们直接使用npm包名称来import npm包(rollup默认必须使用文件路径来引入npm包)

import { nodeResolve } from '@rollup/plugin-node-resolve';

export default {
  input: 'src/index.js',
  output: {
    dir: 'output',
    format: 'cjs'
  },
  plugins: [nodeResolve()]
};

@rollup/plugin-commonjs

允许我们打包commonjs,正常情况下,我们开发前端项目的js库时,是不会写commonjs的,但是我们有时会引入第三方的npm包,其中可能有的npm包是用commonjs模式导出的,这个时候我们就需要用到这个插件了

@rollup/plugin-json

可以import json文件

举个例子

把axios打包进我们的库中。

import axios from "axios";
const testA = (number: number): string => {
  console.log(number, axios);
  return "num is " + number;
};

export default testA;

  1. 需要引入@rollup/plugin-typescript插件来处理ts
  2. 需要使用@rollup/plugin-node-resolve来处理第三方npm包名的解析
  3. 打包过程中会报错,因为axios内部还使用了commonjs模块以及对json的引用,所以还需要使用@rollup/plugin-commonjs插件以及@rollup/plugin-json插件
  4. 打包成功,但是发现打包产物里面还有require("xx"),后面在使用这个js库的时候还会报错。
  5. 如果对插件配置比较熟悉的话,可以给@rollup/plugin-node-resolve插件配置browser: true ,就可以正常使用了,同时也不需要使用@rollup/plugin-commonjs插件了()
// 配置文件
import typescript from "@rollup/plugin-typescript";
import { nodeResolve } from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import json from "@rollup/plugin-json";

export default {
  input: "main.ts",
  output: [
    {
      file: "dist/esm/index.js",
    },
  ],
  plugins: [
    typescript(),
    nodeResolve({ browser: true }), //commonjs(),
    json(),
  ],
};

@rollup/plugin-babel

这里我们用了tsc,编译ts,如果是用js写的库的话,需要用babel编译。(之前看到大部分文章,编译ts库也都用rollupplugin-babel,还没搞懂原因)