摘要:之外的另一種選擇對前端來說是再熟悉不過的工具了,它提供了強大的功能來構建前端的資源,包括等語言腳本,也包括等二進制文件。所以,一個不錯的選擇是,應用使用,類庫使用。
webpack 之外的另一種選擇:rollup
webpack 對前端來說是再熟悉不過的工具了,它提供了強大的功能來構建前端的資源,包括 html/js/ts/css/less/scss ... 等語言腳本,也包括 images/fonts ... 等二進制文件。
其實,webpack 發起之初主要是為了解決以下兩個問題:
代碼拆分(Code Splitting): 可以將應用程序分解成可管理的代碼塊,可以按需加載,這樣用戶便可快速與應用交互,而不必等到整個應用程序下載和解析完成才能使用,以此構建復雜的單頁應用程序(SPA);
靜態資源(Static Assets): 可以將所有的靜態資源,如 js、css、圖片、字體等,導入到應用程序中,然后由 webpack 使用 hash 重命名需要的資源文件,而無需為文件 URL 增添 hash 而使用 hack 腳本,并且一個資源還能依賴其他資源。
正是因為 webpack 擁有如此強大的功能,所以 webpack 在進行資源打包的時候,就會產生很多冗余的代碼(如果你有查看過 webpack 的 bundle 文件,便會發現)。
比如,把 export default str => str; 這段代碼用 webpack 打包就會得到下面的結果:
/******/ (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); /***/ }) /******/ ]);
這在以下的一些情境中就不太高效,需要尋求更好的解決方案:
需要 js 高效運行。因為 webpack 對子模塊定義和運行時的依賴處理(__webpack_require__),不僅導致文件體積增大,還會大幅拉低性能;
項目(特別是類庫)只有 js,而沒有其他的靜態資源文件,使用 webpack 就有點大才小用了,因為 webpack bundle 文件的體積略大,運行略慢,可讀性略低。
在這種情況下,就想要尋求一種更好的解決方案,這便是 rollup.
現在已經有很多類庫都在使用 rollup 進行打包了,比如:react, vue, preact, three.js, moment, d3 等。
1. 工具安裝
npm i -g rollup # 全局安裝 npm i -D rollup # 本地安裝
使用
rollup -c # 使用一個配置文件,進行打包操作
更多詳細的用法,參考 rollup.js - command-line-flags.
2. 配置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.
3. rollup 與 webpack 對比先拿段代碼來來看看他們打包之后各自是什么效果。
源代碼
# 目錄 |-- 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 bundle 中的 __webpack_require__, Object.defineProperty 之類的冗余代碼;
另外,rollup 也對 es 模塊輸出及 iife 格式打包有很好的支持。
4. 結論rollup 相對 webpack 而言,要小巧、干凈利落一些,但不具備 webpack 的一些強大的功能,如熱更新,代碼分割,公共依賴提取等。
所以,一個不錯的選擇是,應用使用 webpack,類庫使用 rollup。
5. 后續更多博客,查看 https://github.com/senntyou/blogs
作者:深予之 (@senntyou)
版權聲明:自由轉載-非商用-非衍生-保持署名(創意共享3.0許可證)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/96999.html
摘要:便提供了一個額外的選擇,對于不喜歡配置的開發者尤其友好,因為沒有配置文件,僅有的少量配置項也是從命令行輸入。另外會自動識別安裝在中的插件,然后導入,而無需手動配置。與相比,零配置是最大的特點與優勢,但沒有功能強大,也缺少了些靈活性。 webpack 之外的另一種選擇:parcel 之前有寫過一篇 webpack 之外的另一種選擇:rollup,這次算是姊妹篇,介紹另外一個工具 parc...
摘要:一般建議文件最大不超過。按需加載可以減小首屏加載文件的體積,達到提高響應速度的目的。如果你的項目不需要處理靜態資源如圖片,也不需要按需加載,并追求前端高性能的話,可以嘗試。 如何提升前端性能和響應速度 下面大多是從前端工程化的角度給出的優化建議,如果需要了解語法上的優化,可以參考: 如何提高頁面加載速度 編寫高效的JavaScript Web前端性能優化進階 - 完結篇 1. 原生...
摘要:一般建議文件最大不超過。按需加載可以減小首屏加載文件的體積,達到提高響應速度的目的。如果你的項目不需要處理靜態資源如圖片,也不需要按需加載,并追求前端高性能的話,可以嘗試。 如何提升前端性能和響應速度 下面大多是從前端工程化的角度給出的優化建議,如果需要了解語法上的優化,可以參考: 如何提高頁面加載速度 編寫高效的JavaScript Web前端性能優化進階 - 完結篇 1. 原生...
摘要:性能優化利器性能優化性能優化不外乎從三個角度入手開發者在編寫程序時,盡量避免不必要的冗余代碼,包括冗余的第三方庫首先要避免不必要的冗余代碼,包括不必要的閉包不必要的變量與函數聲明不必要的模塊分割等。 js 性能優化利器:prepack 1. js 性能優化 js 性能優化不外乎從三個角度入手: 1.1 開發者在編寫程序時,盡量避免不必要的冗余代碼,包括冗余的第三方庫 首先要避免不必要的...
摘要:從到完美,寫一個庫庫前端組件庫之前講了很多關于項目工程化前端架構前端構建等方面的技術,這次說說怎么寫一個完美的第三方庫。使用導出模塊,就可以在使用這個庫的項目中構建時使用功能。 從 1 到完美,寫一個 js 庫、node 庫、前端組件庫 之前講了很多關于項目工程化、前端架構、前端構建等方面的技術,這次說說怎么寫一個完美的第三方庫。 1. 選擇合適的規范來寫代碼 js 模塊化的發展大致有...
閱讀 1837·2021-11-25 09:43
閱讀 1347·2021-11-22 15:08
閱讀 3751·2021-11-22 09:34
閱讀 3232·2021-09-04 16:40
閱讀 3034·2021-09-04 16:40
閱讀 553·2019-08-30 15:54
閱讀 1342·2019-08-29 17:19
閱讀 1759·2019-08-28 18:13