webpack 對前端來講是再熟悉不過的工具了,它提供了強大的功能來構建前端的資源,包括 html/js/ts/css/less/scss ...
等語言腳本,也包括 images/fonts ...
等二進制文件。css
其實,webpack 發起之初主要是爲了解決如下兩個問題:html
正是由於 webpack 擁有如此強大的功能,因此 webpack 在進行資源打包的時候,就會產生不少冗餘的代碼(若是你有查看過 webpack 的 bundle 文件,便會發現)。前端
好比,把 export default str => str;
這段代碼用 webpack 打包就會獲得下面的結果:vue
/******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { /******/ configurable: false, /******/ enumerable: true, /******/ get: getter /******/ }); /******/ } /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); /* harmony default export */ __webpack_exports__["default"] = (str => str); /***/ }) /******/ ]);
這在如下的一些情境中就不過高效,須要尋求更好的解決方案:react
__webpack_require__
),不只致使文件體積增大,還會大幅拉低性能;在這種狀況下,就想要尋求一種更好的解決方案,這即是 rollup.webpack
如今已經有不少類庫都在使用 rollup 進行打包了,好比:react, vue, preact, three.js, moment, d3 等。git
安裝es6
npm i -g rollup # 全局安裝 npm i -D rollup # 本地安裝
使用github
rollup -c # 使用一個配置文件,進行打包操做
更多詳細的用法,參考 rollup.js - command-line-flags.web
rollup 的配置與 webpack 的配置相似,定義在 rollup.config.js
文件中,好比:
// rollup.config.js export default { input: 'src/index.js', output: { file: 'bundle.js', // amd, cjs, esm, iife, umd, system format: 'cjs' } };
經常使用的幾個配置項:
input
: 源碼入口文件,通常是一個文件,如 src/index.js
。output
: 定義輸出,如文件名,目標目錄,輸出模塊範式(es6
, commonjs
, amd
, umd
, iife
等),模塊導出名稱,外部庫聲明,全局變量等。plugins
: 插件,好比 rollup-plugin-json 可讓 rollup 從 .json
文件中導入 json 數據。更多詳細的配置,參考 rollup.js - configuration-files.
先拿段代碼來來看看他們打包以後各自是什麼效果。
源代碼
# 目錄 |-- src/ |-- index.js |-- prefix.js |-- suffix.js # prefix.js const prefix = 'prefix'; export default str => `${prefix} | ${str}`; # suffix.js const suffix = 'suffix'; export default str => `${str} | ${suffix}`; # index.js import prefix from './prefix'; import suffix from './suffix'; export default str => suffix(prefix(str));
配置
# webpack.config.js module.exports = { entry: './src/index.js', output: { filename: 'dist/webpack.bundle.js', library: 'demo', libraryTarget: 'umd' } }; # rollup.config.js export default { input: 'src/index.js', output: { file: 'dist/rollup.bundle.js', name: 'demo', format: 'umd' } };
運行
# webpack 打包 webpack # rollup 打包 rollup -c
webpack.bundle.js
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define([], factory); else if(typeof exports === 'object') exports["demo"] = factory(); else root["demo"] = factory(); })(typeof self !== 'undefined' ? self : this, function() { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { /******/ configurable: false, /******/ enumerable: true, /******/ get: getter /******/ }); /******/ } /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__prefix__ = __webpack_require__(1); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__suffix__ = __webpack_require__(2); /* harmony default export */ __webpack_exports__["default"] = (str => Object(__WEBPACK_IMPORTED_MODULE_1__suffix__["a" /* default */])(Object(__WEBPACK_IMPORTED_MODULE_0__prefix__["a" /* default */])(str))); /***/ }), /* 1 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; const prefix = 'prefix'; /* harmony default export */ __webpack_exports__["a"] = (str => `${prefix} | ${str}`); /***/ }), /* 2 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; const suffix = 'suffix'; /* harmony default export */ __webpack_exports__["a"] = (str => `${str} | ${suffix}`); /***/ }) /******/ ]); });
rollup.bundle.js
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.demo = factory()); }(this, (function () { 'use strict'; const prefix = 'prefix'; var prefix$1 = str => `${prefix} | ${str}`; const suffix = 'suffix'; var suffix$1 = str => `${str} | ${suffix}`; var index = str => suffix$1(prefix$1(str)); return index; })));
其實,你也基本上看出來了,在這種場景下,rollup 的優點在哪裏:
cjs
, umd
頭外,bundle 代碼基本和源碼差很少,也沒有奇怪的 __webpack_require__
, Object.defineProperty
之類的東西;__webpack_require__
, Object.defineProperty
之類的冗餘代碼;rollup 相對 webpack 而言,要小巧、乾淨利落一些,但不具有 webpack 的一些強大的功能,如熱更新,代碼分割,公共依賴提取等。
因此,一個不錯的選擇是,應用使用 webpack,類庫使用 rollup。
更多博客,查看 https://github.com/senntyou/blogs
版權聲明:自由轉載-非商用-非衍生-保持署名(創意共享3.0許可證)