Rollup工具的使用教程

161 阅读3分钟

image.png

前言

Rollup和Webpack

Rollup和Webpack 同样都是打包工具,那他们之间到底有什么区别呢?

Webpack

说到打包工具,大家应该第一个想到的是webpack,无论是vue还是react中都是基于Webpack打包工具进行打包,Webpack中的loader(加载器)可以将各种类型的资源转换成 JavaScript 模块。这样,任何资源都可以成为 Webpack 可以处理的模块。
Webpack官网

Rollup

Rollup是下一代JavaScript模块打包工具,它使用ES6的模块标准,这样不需要通过babel将import转化成Commonjs的require方式,Rollup打包的体积非常小,比起Webpack有更加使用的场景。

例如:
在CommonJS中需要引入整个完整的库,而使用ES6时,只需要引入需要使用的函数

// CommonJS
var utils = require( 'utils' );

// ES6
import { ajax } from 'utils';

因为 Rollup 只引入最基本最精简代码,所以打包生成的文件更轻量、快速。
Rollup官网

快速入门

一、新建项目

首先新建一个空文件夹,并用vscode打开
$ npm init -y    //初始化项目

二、安装 Rollup

$ npm install rollup --save-dev     //安装Rollup依赖

2.20.png

Rollup会添加到package.json文件的依赖中,并且会生成一个node_modules文件夹

三、配置 Rollup

新建一个rollup.config.js文件

image.png

-- 接下来就是rollup工具的配置了 
// rollup.config.js
export default {
  input: 'index.js',                 //入口
  output: {                          //出口
    file: 'dist/bundle.js',          //文件路径
    format: 'cjs'                    //输出格式
  }
};

更多关于配置问题,可以参考官网的 Configuration Files

image.png

四、配置打包命令

 -- 在package.json文件中的scripts字段中添加打包命令
// package.json
"scripts": {
    "rollup":"rollup",    //  查看rollup的基本配置
    "build":"rollup -c",  //  打包命令
    "test": "echo \"Error: no test specified\" && exit 1"
  },

微信图片_20220220213307.png

一开始我是直接使用rollup命令去打包,然后出现了rollup的全部配置,我看了一些配置之后才知道需要添加配置, -c 的话相当于使用默认配置文件,这时候才可以进行打包,所以打包的命令是rollup -c,还有更多的配置信息,可以自己设置一个rollup命令进行查看,并且使用。执行打包命令后,rollup会根据配置文件中的信息进行对应的打包操作。

五、测试

万事俱备就差实验了,能不能行就在这一刻体现出来了,这时候我们就使用配置好的命令,执行

$ npm run build

就可以看到是否打包成功了。根据上面的配置,会新建一个dist文件夹,下面有一个打包后的文件bundle.js,可以打开bundle.js文件查看,打包后的内容是什么样的,如果代码过于简单,当然就看不出什么差别了。
PS: 对应的入口文件和出口文件都在rollup.config.js文件中设置。

小结

到这里,rollup的入门就已经结束了,学习完这些,就算是可以简单使用rollup工具进行打包了, 但由于rollup还包含非常多的其他功能,还需要去探索,所以我们会继续往下讲。

深入学习

一、多入口

基础配置是一个入口一个出口,那有没有需要打包不同版本,或者不同功能时候需要打两个或者多个包的时候呢? 答案是肯定有啊,所以也存在多入口的配置

//  单入口
export default {
  input: 'index.js', 
  output: {
    file: 'dist/bundle.js',   
    format: 'cjs'
  }
};

//  多入口
export default {
    input: {
        index:'index.js',
        foo:'foo.js'
    },
    output: {
      dir: 'dist',
      format: 'cjs'
    }
  };

只需要在入口(input)用对象的形式,将需要打包的文件引入,在出口(output)把file改成dir,并设置文件夹路径即可实现多入口配置啦。

二、Format

format是打包后的输出格式,输出格式一共有六种,分别是:amd / esm / iife / umd / cjs / system
用一个例子来看看不同输出格式打包后内容的区别:

import jq from 'jquery'

function add(a, b) {
    return a + b
}
const result = add(1, 2)
console.log(result);
console.log(jq);

一、esm 格式

import 'jquery';

function add(a, b) {
    return a + b
}
const result = add(1, 2);
console.log(result);

esm: ECMAScript modules -- 代码使用ES module规范,这里的import还是import

二、iife 格式

(function (jq) {
    'use strict';

    function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

    var jq__default = /*#__PURE__*/_interopDefaultLegacy(jq);

    function add(a, b) {
        return a + b
    }
    const result = add(1, 2);
    console.log(result);
    console.log(jq__default["default"]);
})(jq);

iife: 自执行函数 -- 打包后,代码变成了一个自执行函数
引入的依赖,会以参数的形式传入自执行函数,

优点:

  • 有自己的作用域,不会变量污染,
  • 对代码体积的影响不大
  • 简单易懂 缺点:
  • 输出的变量可能影响全局变量;引入依赖包时依赖全局变量。

三、 cjs 格式

'use strict';

var jq = require('jquery');

function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

var jq__default = /*#__PURE__*/_interopDefaultLegacy(jq);

function add(a, b) {
    return a + b
}
const result = add(1, 2);
console.log(result);
console.log(jq__default["default"]);

cjs: commonjs -- 代码使用commonjs规范,这里的import 打包后变成了require

优点:

  • 完善的模块化方案,完美解决了 IIFE 的各种缺点。 缺点:
  • 不支持浏览器环境,因为这种同步的引入方式可能导致浏览器假死。

四、 amd格式

define(['jquery'], (function (jq) { 'use strict';

    function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

    var jq__default = /*#__PURE__*/_interopDefaultLegacy(jq);

    function add(a, b) {
        return a + b
    }
    const result = add(1, 2);
    console.log(result);
    console.log(jq__default["default"]);

}));

amd: 核心内容是一个全局方法 define 。与前面那些相比会相对复杂一些,但他解决了 IIFE 和 CommonJS 所面临的问题,对“浏览器里完善的JS模块方法” 提供了一套完善的方案。

优点:

  • 一套完备的浏览器里 js 文件模块化方案 缺点:
  • 代码组织形式别扭,可读性差

五、umd 格式

(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('jquery')) :
    typeof define === 'function' && define.amd ? define(['jquery'], factory) :
    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.jq));
})(this, (function (jq) { 'use strict';

    function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

    var jq__default = /*#__PURE__*/_interopDefaultLegacy(jq);

    function add(a, b) {
        return a + b
    }
    const result = add(1, 2);
    console.log(result);
    console.log(jq__default["default"]);
}));

umd: 整整一大段代码,只是在处理兼容性问题,判断当前应该使用 amd 或是 CommonJS

优点:

  • 抹平了一个包在 AMD 和 CommonJS 里的差异 缺点:
  • 会为了兼容产生大量不好理解的代码。(理解难度与包体积)

六、system 格式

System.register(['jquery'], (function () {
    'use strict';
    var jq;
    return {
        setters: [function (module) {
            jq = module["default"];
        }],
        execute: (function () {

            function add(a, b) {
                return a + b
            }
            const result = add(1, 2);
            console.log(result);
            console.log(jq);

        })
    };
}));

system: system 的打包结果其实和 amd 类似,提供了全局的对象 System,并提供了注册的方式和统一的写法。

三、Plugins

当我们的项目越来越大,需要引入的功能也越来越多,这时候默认的配置已经无法满足打包的需求的时候,我们就需要引入插件(plugins),来帮助打包。例如使用 Babel 编译代码,使用 JSON 文件等。

这里以引入json文件数据为例:
首先可以创建一个json文件,或者就以package.json来说,我们需要获取文件中的版本号(version)

//package.json
{
  "devDependencies": {
    "rollup": "^2.67.3"
  },
  "name": "use-rollup",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "rollup":"rollup",
    "build":"rollup -c",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": ""
}

第一步 先安装插件

$ npm install --save-dev @rollup/plugin-json

第二步 更新js文件内容,引入json文件数据

// index.js
import { version } from '../package.json';
console.log(version);

第三步 修改 rollup.config.js

修改前
// rollup.config.js 
export default {
    input:'index.js',
    output: {
      file: 'dist/bundle.js',
      format: 'cjs'
    }
  };
  
修改后
// rollup.config.js 
import json from '@rollup/plugin-json';
export default {
    input: {
        index:'index.js',
        foo:'foo.js'
    },
    output: {
      dir: 'dist',
      format: 'cjs'
    },
    plugins: [json()]
  };

第四步 打包
先来看看没有安装插件的情况:

image.png 会报错,报错内容是,json is not defined

rollup.config.js 可以看出引入了插件,在plugins处添加了插件,所以插件是一定要先安装的,否则无法识别json文件

安装完插件后,再次打包就不会再报错了,就可以识别json文件的引入了。

小结
插件的基本使用,就是打包需要引入什么插件,就安装对应插件所需的依赖,然后在plugins中添加之后进行打包即可。

总结

学习完了rollup的基本使用,接下来我会继续更新一篇rollup的实现原理的文章,和大家一起学习和分享。