likes
comments
collection
share

手把手教你使用Rollup构建javascript模块库

作者站长头像
站长
· 阅读数 90

本篇会教你如何使用Rollup打包TypeScript项目,导出esm/umd模块库,在进行打包代码配置之前,稍微介绍一下Rollup,让刚接触的小伙伴知道啥是Rollup,已经学习过Rollup可以跳过前面的介绍,直接看工程实战部分~

Rollup

Rollup 是一个 JavaScript 模块打包工具,可以将多个小的代码片段编译为完整的库和应用。与传统的 CommonJS 和 AMD 这一类非标准化的解决方案不同,Rollup 使用的是 ES6 版本 Javascript 中的模块标准。新的 ES 模块可以让你自由、无缝地按需使用你最喜爱的库中那些有用的单个函数。这一特性在未来将随处可用,但 Rollup 让你现在就可以,想用就用。

配置

下面用一个简单的示例来看看Rollup 是如何工作的。首先创建Rollup的配置文件rollup.config.js及我们打包的项目文件app.js。

//rollup.config.js
module.exports = {
    input: 'src/app.js',
    output: {
        file: 'dist/boundle.js',
        format: 'cjs'
    }
};

//src/app.js
console.log('My first rollup app.')

与Webpack 一般的项目内部不同,Rollup直接全局安装即可:

(sudo) npm i rollup -g

然后使用Rollup的命令行指令进行打包:

rollup -c rollup.config.js

-c 参数是告诉Rollup使用该配置文件,打包结果如下:

'use strict';
console.log('My first rollup app.')

可以看到,我们打包出来的东西很干净,Rollup并没有添加什么额外的代码(就连第1行的'use strict都可以通过配置output.strict去掉')。 同样的代码如果你用webpack打包试试,多出好多额外的代码。

配置文件说明

通常,这个配置文件位于你项目的根目录,并且命名为 rollup.config.js。Rollup 将会在配置文件被依赖之前,在后台将配置文件和 CommonJS 的相关依赖项进行转译和打包,这样做的优点就是你可以与 ES 模块代码库共享代码,同时与 Node 生态完全互通。

如果你想要使用 require 和 module.exports 将配置文件写成一个 CommonJS 模块,则应该将文件扩展名更改为 .cjs,这会阻止 Rollup 尝试转译文件。此外,如果你使用的是 Node 13+,则将文件扩展名更改为 .mjs 也可以阻止 Rollup 进行编译,并将文件导入为 ES 模块

Rollup 去除死代码

Tree shaking, 最开始是由Rollup实现的,之后被webpack借鉴了过去。 Rollup去除死代码也是基于对ES6 Module的静态分析,找出没有被引用过的模块,将其从最后生成的bundle中排除。 下面看简单的代码示例:

// app.js
import { add } from './util';
console.log(`2 + 3 = ${add(2,3)}`);

// util.js
export function add(a ,b) {
    return a + b;
}

export function sub(a ,b){
    return a - b;
}

Rollup 的打包结果如下:
'use strict';
function add(a, b){
    return a + b;
}
console.log(`2 + 3 = ${add(2,3)}`);

可以看到,util.js中的sub函数没有被引用过,因此也没有出现在最终的bundle.js中。与之前输出的内容非常清晰简洁,没有附加代码。

可选的输出格式

Rollup有一项Webpack不具备的特性,通过配置output.format,开发者可以选择输出资源的模块形式。 上面例子中我们使用的是cjs(CommonJS),除此之外Rollup还支持amd、esm、iife、umd及system。 这项特性针对打包JavaScript库特别有用,因为往往一个库需要支持多种不同的模块形式,而通过Rollup, 用几个命令就可以把一份源代码打包为多份。下面使用一段简单的代码进行举例。

'use strict'
export function add(a ,b) {
    return a + b;
}

export function sub(a ,b){
    return a - b;
}

当 output.fromat 是cjs(CommonJS)时,输出如下:

Object.defineProperty(exports, '__esModule', { value: true });
export function add(a ,b) {
    return a + b;
}
export function sub(a ,b){
    return a - b;
}
exports.add = add;
exports.sub = sub;

当output.format是esm(ES6 Module)时,输出如下:
function add(a , b){
    return a + b;
}
function sub(a, b){
    return a - b;
}
export { add, sub };

工程实战

TypeScript+React18编写的工具库,要求同时输出esm/umd模块。 工程目录如下:

  public/
    index.html
  rollup/
    rollup.config.mjs
    rollup.esm.config.mjs
    rollup.umd.config.mjs
  src/
    components/
        ...
    hooks/
      ...
    styles/
        ...
    index.tsx
    index.css
  package.json
  tsconfig.json
  .README.md

rollup文件夹下面分别创建 rollup.esm.config.mjs 和 rollup.umd.config.mjs 并把两个配置公共的部分抽取出来rollup.config.mjs

公共部分 config

我们看看公共部分的配置文件:

//rollup.config.mjs
import typescript from 'rollup-plugin-typescript2'
import { nodeResolve } from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import json from '@rollup/plugin-json'
import sass from 'rollup-plugin-sass'
import autoprefixer from 'autoprefixer'
import postcss from 'postcss'

//rollup-plugin-typescript2 插件配置项目
const overrides = {
    compilerOptions: { declaration: true },
    exclude: ["src/**/*.test.tsx", "src/setupTests.ts"] 
}
const config = {
    input: 'src/index.tsx', // 入口项(必选)
    plugins: [
      nodeResolve(),
      commonjs(),
      json(),
      typescript({ tsconfigOverride: overrides }),
      sass({ 
        output: 'dist/index.css',
        processor: css => postcss([autoprefixer])
        .process(css)
        .then(result => result.css) 
      })
    ],
  }
  
 export default config
  

rollup生态圈也是提供了丰富的插件来处理各类业务,我们着重说一下上面用到的几个插件。

插件 @rollup/plugin-node-resolve:

npm install @rollup/plugin-node-resolve -D

@rollup/plugin-node-resolve 插件来处理外部模块(rollup默认无法处理外部模块,也就是说无法解析打包从npm上下载使用的包,使用这个插件可以帮助我们使用)。

插件 @rollup/plugin-commonjs:

npm install @rollup/plugin-commonjs -D

一些库会导出成你可以正常导入的 ES6 模块。 但是目前, npm 中的大多数包都是以 CommonJS 模块的形式出现的。 在它们更改之前,我们需要将 CommonJS 模块转换为 ES2015 供 Rollup 处理。

插件 rollup-plugin-json:

npm install rollup-plugin-json -D

使用 rollup-plugin-json 插件来处理json文件。

插件 rollup-plugin-typescript2:

npm install rollup-plugin-typescript2 -D

rollup-plugin-typescript2 支持 typescript,是原始rollup-plugin-typescript的重写。 这个版本比原来的要慢一些,但是它会打印出TypeScript的语法和语义诊断消息(毕竟这是使用TypeScript的主要原因)。

配置项可以查看文档:www.npmjs.com/package/rol…

插件 rollup-plugin-sass:

npm install rollup-plugin-sass -D

用于Rollup和Sass之间的无缝集成。

配置项可以查看文档:www.npmjs.com/package/rol…

插件 postcss:

npm install postcss -D

使用 postcss 处理css,它支持css文件的加载、css加前缀、css压缩、对scss/less的支持等等。

插件 autoprefixer:

npm install autoprefixer -D

可以使用 autoprefixer 插件为CSS3添加前缀

esm模块 config

来看构建esm库的配置文件:

// rollup.esm.config.mjs

import basicConfig from './rollup.config.mjs'
import excludeDependenciesFromBundle from "rollup-plugin-exclude-dependencies-from-bundle"

const config = {
    ...basicConfig, //整合公共部分
    output: [
      {
        file: 'dist/index.es.js', //输出文件
        format: 'es' //输出格式
      }
    ],
    plugins: [ //插件
      ...basicConfig.plugins, //整合公共部分插件
      excludeDependenciesFromBundle() //忽略掉dependencies和peerDependencies的依赖
    ]
  }
  
  export default config

umd模块 config

导出的umd模式在浏览器中使用 script 和 link 标签直接引入文件,并使用全局变量 TEST。

来看构建umd库的配置文件:

//rollup.umd.config.mjs

import basicConfig from './rollup.config.mjs'
import { terser } from "rollup-plugin-terser"
import replace from '@rollup/plugin-replace'

const config = {
  ...basicConfig, //整合公共部分配置
  output: [ 
    {
      name: 'TEST', //浏览器引入的全局变量名称
      file: 'dist/index.umd.js', //输出文件
      format: 'umd', //输出格式
      exports: 'named', //导出的是全局变量命名方式
      globals: { //对被排除的依赖命名
        'react': 'React', //三方库映射
        'react-dom': 'ReactDOM',
        'axios': 'Axios'
      },
      plugins: [
        terser() //terser插件在rollup打包过程当中实现代码压缩
      ],
    },
  ],
  plugins: [
    replace({
      'process.env.NODE_ENV': JSON.stringify('production'), //该插件在绑定时替换文件中的目标字符串
    }),
    ...basicConfig.plugins //整合公共部分插件
  ],
   //有时候一些外部引用的库我们并不想一并打包在我们的库中,
   //如:lodash、react,可以在配置文件中使用 external 字段来告诉rollup不要将这些库打包
  external: ['react', 'react-dom', 'axios'] //排除的这些需要在页面中单独引入cdn link 链接
}

export default config

package.json 配置命令

在package.json 中配置打包命令

  "scripts": {
    "build-es": "rollup --config rollup/rollup.esm.config.mjs",
    "build-umd": "rollup --config rollup/rollup.umd.config.mjs"
  }

构建运行

在终端分别执行: npm run build-es , npm run build-umd

目标文件夹中输出:dist/index.es.js, dist/index.umd.js

发布到npmjs或者部署到服务器即可使用!

转载自:https://juejin.cn/post/7181741108697759805
评论
请登录