中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

CommonJS是怎么導致打包后體積增大的

發布時間:2021-10-23 17:39:03 來源:億速云 閱讀:139 作者:iii 欄目:編程語言

本篇內容主要講解“CommonJS是怎么導致打包后體積增大的”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“CommonJS是怎么導致打包后體積增大的”吧!

什么是 CommonJS?

CommonJS 是 2009 年發布的 JavaScript模塊化的一項標準,最初它只打算在瀏覽器之外的場景使用,主要用于服務器端的應用程序。

你可以使用 CommonJS 來定義模塊,并從中導出部分模塊。例如,下面的代碼定義了一個模塊,該模塊導出了五個函數:add、 subtract、  multiply、 divide、max:

// utils.js const { maxBy } = require('lodash-es'); const fns = {   add: (a, b) => a + b,   subtract: (a, b) => a - b,   multiply: (a, b) => a * b,   divide: (a, b) => a / b,   max: arr => maxBy(arr) };  Object.keys(fns).forEach(fnName => module.exports[fnName] = fns[fnName]);

其他模塊可以導入這個模塊的部分函數。

// index.js const { add } = require(‘./utils'); console.log(add(1, 2));

通過 node 運行 index.js ,會在控制臺輸出數字 3。

在 2010 年,由于瀏覽器缺乏標準化的模塊化能力,CommonJS 成了當時 JavaScript 客戶端較為流行的模塊化標準。

CommonJS 如何影響包體?

服務端的 JavaScript 程序對代碼體積并不像瀏覽器中那么敏感,這就是為什么在設計 CommonJS  的時候,并沒有考慮減少生產包大小的原因。同時,研表究明 JavaScript 代碼的體積依然是影響頁面加載速度的一個重要因素。

JavaScript  的打包工具(webpack、terser)會進行許多優化以減小最后生成的包體大小。他們在構建時,會分析你的代碼,盡可能的刪除不會使用的部分。例如,上面的代碼中,最終生成的包應該只包含  add 函數,因為這是 index.js 唯一從 utils.js 中導入的部分。

下面我們使用如下 webpack 配置對應用進行打包:

const path = require('path'); module.exports = {   entry: 'index.js',   output: {     filename: 'out.js',     path: path.resolve(__dirname, 'dist'),   },   mode: 'production', };

我們需要將 webpack 的 mode 指定為 production,并且將 index.js 作為入口。運行 webpack  后,會輸出一個文件:dist/out.js,可以通過如下方式統計它的大小:

$ cd dist && ls -lah 625K Apr 13 13:04 out.js

打包后的文件高達 625 KB。如果看下 out.js 文件,會發現 utils.js 導入 lodash 的所有模塊都打包到了輸出的文件中,盡管我們在  index.js 并沒有使用到 lodash 的任何方法,但是這給我們的包體帶來了巨大的影響。

現在我們將代碼的模塊化方案改為 ESM,utils.js 部分的代碼如下:

export const add = (a, b) => a + b; export const subtract = (a, b) => a - b; export const multiply = (a, b) => a * b; export const divide = (a, b) => a / b;  import { maxBy } from 'lodash-es';  export const max = arr => maxBy(arr);

index.js 也改為 ESM 的方式從 utils.js 導入模塊:

import { add } from './utils';  console.log(add(1, 2));

使用相同的 webpack 配置,構建完畢之后,我們打開 out.js ,僅有 40 字節,輸出如下:

(()=>{"use strict";console.log(1+2)})();

值得注意的是,最終的輸出并沒有包含 utils.js 的任何代碼,而且 lodash 也消失了。而且 terser(webpack 使用的壓縮工具)直接將  add 函數內聯到了 console.log 內部。

有的小朋友可能就會問了(此處采用了李永樂語法),為什么使用 CommonJS 會導致輸出的文件大了 16,000 倍?當然,這只是用來展示  CommonJS 與 ESM 差異的案例,實際上并不會出現這么大的差異,但是使用 CommonJS 肯定會導致打包后的體積更大。

一般情況下,CommonJS 模塊的體積更加難優化,因為它比 ES 模塊更加的動態化。為了確保構建工具以及壓縮工具能成功優化代碼,請避免使用  CommonJS 模塊。

當然,如果你只在 utils.js 采用了 ESM 的模塊化方案,而 index.js 還是維持 CommonJS,則包體依舊會受到影響。

為什么 CommonJS 會使包體更大?

要回答這個問題,我們需要研究 webpack 的 ModuleConcatenationPlugin  的行為,并且看看它是如何進行靜態分析的。該插件將所有的模塊都放入一個閉包內,這會讓你的代碼在瀏覽器中更快的執行。我們來看看下面的代碼:

// utils.js export const add = (a, b) => a + b; export const subtract = (a, b) => a - b;
// index.js import { add } from ‘./utils'; const subtract = (a, b) => a - b;  console.log(add(1, 2));

我們有一個新的 ESM 模塊(utils.js),將其導入 index.js 中,我們還重新定義一個 subtract 函數。接下來使用之前的  webpack 配置來構建項目,但是這次,我把禁用壓縮配置。

const path = require('path');  module.exports = {   entry: 'index.js',   output: {     filename: 'out.js',     path: path.resolve(__dirname, 'dist'),   }, + optimization: { +   minimize: false + },   mode: 'production', };

輸出的 out.js 如下:

/******/ (() => { // webpackBootstrap /******/  "use strict";  // CONCATENATED MODULE: ./utils.js** const add = (a, b) => a + b; const subtract = (a, b) => a - b;  // CONCATENATED MODULE: ./index.js** const index_subtract = (a, b) => a - b; console.log(add(1, 2));  /******/ })();

輸出的代碼中,所有的函數都在一個命名空間里,為了防止沖突,webpack 將 index.js 中的 subtract 函數重新命名為了  index_subtract 函數。

如果開啟壓縮配置,它會進行如下操作:

  1. 鴻蒙官方戰略合作共建——HarmonyOS技術社區

  2. 刪除沒有使用的 subtract 函數和 index_subtract 函數;

  3. 刪除所有的注釋和空格;

  4. console.log 中直接內聯 add 函數;

一些開發人員會把這種刪除未使用代碼的行為稱為“tree-shaking(樹搖)”。webpack 能夠通過導出、導入符號靜態的分析  utils.js(在構建的過程中),這使得 tree-shaking 有了可行性。當使用 ESM 時,這種行為是默認開啟的,因為相比于  CommonJS,它更加易于靜態分析。

讓我們看看另外的示例,這一次將 utils.js 改為 CommonJS 模塊,而不是 ESM 模塊。

// utils.js const { maxBy } = require('lodash-es');  const fns = {   add: (a, b) => a + b,   subtract: (a, b) => a - b,   multiply: (a, b) => a * b,   divide: (a, b) => a / b,   max: arr => maxBy(arr) };  Object.keys(fns).forEach(fnName => module.exports[fnName] = fns[fnName]);

這個小小的改動,明顯影響了輸出的代碼。由于輸出的文本太大,我們只展示其中的一小部分。

... (() => {  "use strict"; /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(288); const subtract = (a, b) => a - b; console.log((0,_utils__WEBPACK_IMPORTED_MODULE_0__/* .add */ .IH)(1, 2));  })();

可以看到,最終生成的代碼包含一些 webpack 的 runtime 代碼,這部分代碼負責模塊的導入導出的能力。這次并沒有將 utils.js 和  index.js 所有的變量放到了同一命名空間下,動態引入的模塊都是通過 __webpack_require__ 進行導入。

使用 CommonJS 的時候,我們可以通過任意的表達式構造導出名稱,例如下面的代碼也是能正常運行的:

module.exports[(Math.random()] = () => { … };

這導致構建工具在構建時,沒有辦法知道導出的變量名,因為這個名稱只有在用戶瀏覽器運行時才能夠真正確定。壓縮工具無法準確的知道 index.js  使用了模塊的哪部分內容,因此無法正確的進行 tree-shaking。如果我們從 node_modules 導入了 CommonJS  模塊,你的構建工具將無法正確的優化它。

對 CommonJS 使用 Tree-shaking

由于 CommonJS 的模塊化方案是動態的,想要分析他們是特別困難的。與通過表達式導入模塊的 CommonJS 相比,ESM  模塊的導入始終使用的是靜態的字符串文本。

在某些情況下,如果你使用的庫遵循 CommonJS 的相關的一些約定,你可以使用第三方的 webpack  插件:webpack-common-shake,在構建的過程中,刪除未使用的模塊。盡管該插件增加了 CommonJS 對 tree-shaking  的支持,但并沒有涵蓋所有的 CommonJS 依賴,這意味著你不能獲得 ESM 相同的效果。

此外,這并非是 webpack 默認行為,它會對你的構建耗時增加額外的成本。

到此,相信大家對“CommonJS是怎么導致打包后體積增大的”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

兴城市| 麦盖提县| 黄浦区| 广河县| 大宁县| 牙克石市| 锦州市| 东乌| 毕节市| 石首市| 丰台区| 汶川县| 依兰县| 盐亭县| 海林市| 怀集县| 博客| 晋江市| 崇信县| 河东区| 肥东县| 仙游县| 漳平市| 枣庄市| 河池市| 墨脱县| 景洪市| 忻城县| 安阳市| 上高县| 阜宁县| 金秀| 凤庆县| 兴山县| 新巴尔虎右旗| 霸州市| 丁青县| 余干县| 兴仁县| 友谊县| 郴州市|