Rollup.js: 開源JS庫的打包利器

前言

Rollup 是一個 JavaScript 模塊打包器,說到模塊打包器,自然就會想到 webpack。webpack 是一個現代 JavaScript 應用程序的靜態模塊打包器,那麼在 webpack 已經成爲前端構建主流的今天,爲什麼還要用 Rollup 呢?

Rollup 中文文檔 中介紹到,它可以將小塊代碼編譯成大塊複雜的代碼,例如 library 或應用程序。可以看到它的應用場景之一,就是打包 JS 庫。自己寫個 JS 庫,在我們開發工作中和開源項目中還是比較常見的。可謂是生命不息,造輪子不止。如果還沒寫過,那就趕緊來提升下自己的技(逼)術(格)吧。

對比 webpack

用過 webpack 的都知道,它可以將所有的靜態資源,導入到應用程序中,也是因爲它強大的功能,所以打包 bundle 文件時,會產生很多冗餘的代碼,在大型的應用中,這點冗餘代碼就會顯得微不足道,但是在一個小小的庫中,就會顯得比較明顯了。比如這麼一個類:

class People{
    constructor(){
        this.name  = 'linxin'
    }
    getName(){ return this.name; }
}
export default People;

經過 webpack 打包之後,變成下面這樣(案例移除了具體內容),多出了很多方法,這顯然不是我們想要的。

/******/ (function(modules) { // webpackBootstrap
/******/     var installedModules = {};
/******/     function __webpack_require__(moduleId) { **** }
/******/     __webpack_require__.m = modules;
/******/     __webpack_require__.c = installedModules;
/******/     __webpack_require__.d = function(exports, name, getter) { *** };
/******/     __webpack_require__.r = function(exports) { *** };
/******/     __webpack_require__.t = function(value, mode) { *** };
/******/     __webpack_require__.n = function(module) { *** };
/******/     __webpack_require__.o = function(object, property) { *** };
/******/     __webpack_require__.p = "";
/******/     return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/******/ ([ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__);
class People{
    constructor(){
        this.name  = 'linxin'
    }
    getName(){
        return this.name;
    }
}
/* harmony default export */ __webpack_exports__["default"] = (People); }) ]);

而 Rollup 打包之後的代碼跟源碼基本一致,作爲一個 JS 庫,我們還是希望簡潔一點,代碼量少點。畢竟實現相同的功能,誰都不想去引入一個更繁重的庫吧。

特性

ES模塊

Rollup 使用 ES6 的模塊標準,而不像 CommonJS 和 AMD,雖然也叫模塊化,其實只是一種臨時的解決方案。Rollup 的模塊可以使我們開發時可以獨立的開發每個小模塊,代碼小而簡單,更加方便測試每個小模塊,在構建時纔打包成一個完成的 JS 庫。

Tree-shaking

tree shaking 指的是移除 JavaScript 上下文中的未引用代碼,它依賴於 ES2015 模塊系統中的靜態結構特性,例如 import 和 export。靜態結構的 import 就好像是變量引用一樣,不需要執行代碼,在編譯時就可以確定它是否有引用到,如果沒引用,就不把該段代碼打包進來。比如用到了一個第三方庫的一個功能,但我肯定不要把它完整的庫都打包進來,我只需要打包用到的代碼即可,這時候 tree shaking 就可以發揮出它的作用了。

應用

開發一個 JS 庫,我需要 Rollup 能爲我提供些常用的功能:

  • 支持 ES6 轉 ES5
  • 代碼壓縮
  • ESLint
  • 支持 Typescript

基本配置

Rollup 使用一個 rollup.config.js 文件進行配置。

// rollup.config.js
export default {
    input: 'src/index.js',
    output: {
        file: 'dist/bundle.js',
        format: 'umd'
    }
};

配置跟其他工具基本一致,從入口文件 index.js 打包後輸出文件 bundle.js。format 是生成包的格式,可選有 amd,cjs,es,iife,umd,umd 是通用模塊定義,打包後可以通過 <script> 標籤引入,也可以通過 import 等方式引入,作爲一個 JS 庫要適用各個場景,應選擇 umd 。

babel

Rollup 通過插件在打包的關鍵過程中更改行爲,babel的插件就是 rollup-plugin-babel,需要先安裝相關依賴

npm i rollup-plugin-babel@latest @babel/core @babel/preset-env -D

新建 .babelrc 文件,配置 babel

{
    "presets": ["@babel/preset-env"]
}

代碼壓縮

npm i rollup-plugin-uglify -D

因爲 rollup-plugin-uglify 無法壓縮 ES6 的語法,所以必須先用 babel 轉。如果想直接壓縮 ES6 的語法,可換成 rollup-plugin-terser

ESLint

開發一個 JS 庫,不能亂七八糟,隨心所欲的寫代碼,必須規範起來,當別人爲你的開源庫做貢獻時,也必須遵循你的開發規範。安裝 ESLint 插件

npm i rollup-plugin-eslint -D

然後初始化生成一個 ESLint 配置文件 ./node_modules/.bin/eslint --init

那麼最終的 rollup.config.js 配置文件如下:

import babel from 'rollup-plugin-babel';
import { uglify } from 'rollup-plugin-uglify';
import { eslint } from "rollup-plugin-eslint";
export default {
    input: './index.js',
    output: {
        file: 'dist/bundle.js',
        name: 'People',
        format: 'umd'
    },
    plugins: [
        eslint({
            fix: true,
              exclude: 'node_modules/**'
        }),
        babel({
          exclude: 'node_modules/**'
        }),
        uglify()
    ]
};

TypeScript

如果使用 TypeScript 進行開發,則需要安裝 rollup-plugin-typescript2 插件和相關依賴

npm i rollup-plugin-typescript2 typescript -D

然後初始化生成一個 tsconfig.js 配置文件 tsc --init,那麼使用 TypeScript 的打包文件如下:

import typescript from 'rollup-plugin-typescript2';

export default {
    input: './index.ts',
    output: {
        file: 'dist/bundle.js',
        name: 'People',
        format: 'umd'
    },
    plugins: [
        typescript()
    ]
}

插件

除了以上用的這些插件之外,還有一些可能根據項目需求也有需要

  • rollup-plugin-commonjs:讓 Rollup 識別 commonjs 類型的包,默認只支持導入ES6
  • rollup-plugin-node-resolve:讓 Rollup 能識別 node_modules 中的包,引入第三方庫,默認識別不了的
  • rollup-plugin-json:支持 json 文件
  • rollup-plugin-replace:支持字符串替換
  • rollup-plugin-sourcemaps:能生成 sourcemaps 文件

總結

以上只是介紹了 Rollup 的一些基本用法,更多的請參考官方文檔。Rollup 已被許多主流的 JavaScript 庫使用,包括 vue 和 react。它也可用於構建絕大多數應用程序,但是代碼拆分和運行時態的動態導入這類高級功能,它還不能支持,如果需用這些功能,那就可以使用 webpack。案例可查看:sChart.js

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章