【讀書筆記】《深入淺出Webpack》

Webpack版本

分析版本為3.6.0
4.0為最近升級的版本,與之前版本變化較大,編譯輸出的文件與3.0版本會不一致,目前項目中使用的版本3.0版本,所以基于3.0版本進行分析學習。

Webpack構建流程

  • 初始化:啟動構建,讀取與合并配置參數,加載Plugin,實例化Complier
  • 編譯:從Entry發出,針對每個Module串行調用對應的Loader去轉換文件內容,再找到該Module依賴的Module,遞歸進行編譯處理。
  • 輸出:對編譯后對Module組合成Chunk,把Chunk轉換成文件,輸出到文件系統。

輸出文件分析

原輸出文件結構:

簡化后的文件結構:

(function(modules) {// 模擬 require 語句function __webpack_require__() {}// 執行存放所有模塊數組中的第0個模塊__webpack_require__(0);
})([/*存放所有模塊的數組*/])

分割代碼時輸出

當使用按需加載加載文件時,Webpack的輸出文件會發生變化。

// 異步加載 show.js
import('./show').then((show) => {// 執行 show 函數show('Webpack');
});

重新構建后會輸出兩個文件,分別是執行入口文件bundle.js和異步加載文件0.bundle.js
異步加載文件默認輸入的文件名為 [id].js,可以在Webpack配置文件的output項中配置輸出文件名
其中0.bundle.js內容如下:

// 加載在本文件(0.bundle.js)中包含的模塊
webpackJsonp(// 在其它文件中存放著的模塊的 ID[0],// 本文件所包含的模塊[// show.js 所對應的模塊(function (module, exports) {function show(content) {window.document.getElementById('app').innerText = 'Hello,' + content;}module.exports = show;})]
);

bundle.js內容如下:

(function (modules) {/**** webpackJsonp 用于從異步加載的文件中安裝模塊。* 把 webpackJsonp 掛載到全局是為了方便在其它文件中調用。** @param chunkIds 異步加載的文件中存放的需要安裝的模塊對應的 Chunk ID* @param moreModules 異步加載的文件中存放的需要安裝的模塊列表* @param executeModules 在異步加載的文件中存放的需要安裝的模塊都安裝成功后,需要執行的模塊對應的 index*/window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {// 把 moreModules 添加到 modules 對象中// 把所有 chunkIds 對應的模塊都標記成已經加載成功 var moduleId, chunkId, i = 0, resolves = [], result;for (; i < chunkIds.length; i++) {chunkId = chunkIds[i];if (installedChunks[chunkId]) {resolves.push(installedChunks[chunkId][0]);}installedChunks[chunkId] = 0;}for (moduleId in moreModules) {if (Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {modules[moduleId] = moreModules[moduleId];}}while (resolves.length) {resolves.shift()();}};// 緩存已經安裝的模塊var installedModules = {};// 存儲每個 Chunk 的加載狀態;// 鍵為 Chunk 的 ID,值為0代表已經加載成功var installedChunks = {1: 0};// 模擬 require 語句,和上面介紹的一致function __webpack_require__(moduleId) {// ... 省略和上面一樣的內容}/*** 用于加載被分割出去的,需要異步加載的 Chunk 對應的文件* @param chunkId 需要異步加載的 Chunk 對應的 ID* @returns {Promise}*/__webpack_require__.e = function requireEnsure(chunkId) {// 從上面定義的 installedChunks 中獲取 chunkId 對應的 Chunk 的加載狀態var installedChunkData = installedChunks[chunkId];// 如果加載狀態為0表示該 Chunk 已經加載成功了,直接返回 resolve Promiseif (installedChunkData === 0) {return new Promise(function (resolve) {resolve();});}// installedChunkData 不為空且不為0表示該 Chunk 正在網絡加載中if (installedChunkData) {// 返回存放在 installedChunkData 數組中的 Promise 對象return installedChunkData[2];}// installedChunkData 為空,表示該 Chunk 還沒有加載過,去加載該 Chunk 對應的文件var promise = new Promise(function (resolve, reject) {installedChunkData = installedChunks[chunkId] = [resolve, reject];});installedChunkData[2] = promise;// 通過 DOM 操作,往 HTML head 中插入一個 script 標簽去異步加載 Chunk 對應的 JavaScript 文件var head = document.getElementsByTagName('head')[0];var script = document.createElement('script');script.type = 'text/javascript';script.charset = 'utf-8';script.async = true;script.timeout = 120000;// 文件的路徑為配置的 publicPath、chunkId 拼接而成script.src = __webpack_require__.p + "" + chunkId + ".bundle.js";// 設置異步加載的最長超時時間var timeout = setTimeout(onScriptComplete, 120000);script.onerror = script.onload = onScriptComplete;// 在 script 加載和執行完成時回調function onScriptComplete() {// 防止內存泄露script.onerror = script.onload = null;clearTimeout(timeout);// 去檢查 chunkId 對應的 Chunk 是否安裝成功,安裝成功時才會存在于 installedChunks 中var chunk = installedChunks[chunkId];if (chunk !== 0) {if (chunk) {chunk[1](new Error('Loading chunk ' + chunkId + ' failed.'));}installedChunks[chunkId] = undefined;}};head.appendChild(script);return promise;};// 加載并執行入口模塊,和上面介紹的一致return __webpack_require__(__webpack_require__.s = 0);
})
(// 存放所有沒有經過異步加載的,隨著執行入口文件加載的模塊[// main.js 對應的模塊(function (module, exports, __webpack_require__) {// 通過 __webpack_require__.e 去異步加載 show.js 對應的 Chunk__webpack_require__.e(0).then(__webpack_require__.bind(null, 1)).then((show) => {// 執行 show 函數show('Webpack');});})]
);

這里的 bundle.js 和上面所講的 bundle.js 非常相似,區別在于:

  • 多了一個 webpack_require.e 用于加載被分割出去的,需要異步加載的 Chunk 對應的文件;
  • 多了一個 webpackJsonp 函數用于從異步加載的文件中安裝模塊。

參考

深入淺出WebPack

轉載于:https://www.cnblogs.com/GeniusLyzh/p/8823749.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/251961.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/251961.shtml
英文地址,請注明出處:http://en.pswp.cn/news/251961.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

《JAVA與模式》之橋梁模式

在閻宏博士的《JAVA與模式》一書中開頭是這樣描述橋梁&#xff08;Bridge&#xff09;模式的&#xff1a; 橋梁模式是對象的結構模式。又稱為柄體(Handle and Body)模式或接口(Interface)模式。橋梁模式的用意是“將抽象化(Abstraction)與實現化(Implementation)脫耦&#xff0…

LABLEME UPDATE DAMOD

Labelme的改進——海量圖片的自動標注 深度學習一般需要對大量的圖片進行標注&#xff0c;但是手動標注耗時耗力&#xff0c;所以模仿labelme軟件的功能&#xff0c;使用程序對大批量的圖片進行自動標注&#xff0c;大大減少手動操作。下面介紹如何實現對大批量的圖片進行標…

Java基礎教程:面向對象編程[2]

Java基礎教程&#xff1a;面向對象編程[2] 內容大綱 訪問修飾符 四種訪問修飾符 Java中&#xff0c;可以使用訪問控制符來保護對類、變量、方法和構造方法的訪問。Java 支持 4 種不同的訪問權限。 default (即缺省&#xff0c;什么也不寫&#xff09;: 在同一包內可見&#xff…

【javascript】異步編年史,從“純回調”到Promise

異步和分塊——程序的分塊執行 一開始學習javascript的時候&#xff0c; 我對異步的概念一臉懵逼&#xff0c; 因為當時百度了很多文章&#xff0c;但很多各種文章不負責任的把籠統的描述混雜在一起&#xff0c;讓我對這個 JS中的重要概念難以理解&#xff0c; “異步是非阻塞的…

Shell編程之if語法練習(LNMP)全過程

大家好&#xff0c;我是延凱&#xff0c;本人原來在CSDN寫作已經快一年了 都是相關Linux運維這方面的技術知識&#xff0c;現在搬到博客園也是我一直想的&#xff0c;本博客主要寫Python&#xff0c;docker&#xff0c;shell等偏向開發云計算等知識點&#xff0c;謝謝各位&…

基于UNet和camvid數據集的道路分割

基于UNet和camvid數據集的道路分割h(1.3.0)&#xff1a; 背景 語義分割是深度學習中的一個非常重要的研究方向&#xff0c;并且UNet是語義分割中一個非常經典的模型。在本次博客中&#xff0c;我嘗試用UNet對camvid dataset數據集進行道路分割&#xff0c;大致期望的效果如下&…

二分法查找和普通查找

一、普通查找 對于數組和一個需要查找的元素來說&#xff0c;普通查找的原理很簡單&#xff0c;即為從數組的第一個元素到最后一個元素進行遍歷&#xff0c;如果第i個元素的值等于我們需要查找的值&#xff0c;那么返回找到的角標i&#xff0c;否則返回-1表示沒有查找到。這里以…

Linux下安裝zookeeper集群(奇數個)

1、 解壓zookeeper壓縮包 2、 data里創建“myid”文件&#xff08;命令touch myid&#xff09;&#xff0c;內容是1&#xff08;命令 echo 1 >> myid&#xff09; 3、 zoo.cnf里配置dataDir、clientport、server.nIP:端口1&#xff08;2881&#xff09;&#xff1a;端…

立體標定

立體標定應用標定數據轉換成深度圖標定 由于攝像頭目前是我們手動進行定位的&#xff0c;我們現在還不知道兩張圖像與世界坐標之間的耦合關系&#xff0c;所以下一步要進行的是標定&#xff0c;用來確定分別獲取兩個攝像頭的內部參數&#xff0c;并且根據兩個攝像頭在同一個世…

if _name_ == _main_

1.作用 py文件有2種使用方法&#xff0c;第1是自己本腳本自己獨立執行&#xff1b;第2是被import到其他文件腳本中執行. if _name_ " _main_" 該語句控制其他下一步的腳本是否執行。如果是自己本腳本獨立執行&#xff0c;那就運行該if條件下的腳本&#xff1b;如果…

LLVM完整參考安裝

文章目錄 一、直接下載編譯好的,見圖片命令二、下載源代碼自己編譯安裝 下面提供下載并mv完全的文件包三、安裝LLVM編譯器一、直接下載編譯好的,見圖片命令 這里使用llvm官網編譯好的包, 直接解壓即可用LLVM下載官網點擊這里下載llvm-6.0.1 下載完成后解壓tar -vxf clangllv…

微軟正式釋出基于 Chromium 的 Edge 預覽版本

百度智能云域名服務&#xff0c;.com新用戶首購僅需25元 微軟基于 Chromium 的全新版本 Edge 一直吸引著開發者與用戶的目光&#xff0c;當地時間 8 日&#xff0c;官方終于釋出了第一個 Dev 和 Canary 頻道構建版本。 Dev 與 Canary build 都是開發者預覽版&#xff0c;同屬…

下載和安裝R、RStudio !

現如今&#xff0c;R語言是統計領域廣泛使用的工具&#xff0c;是屬于GNU系統的一個自由、免費、源代碼開放的軟件&#xff0c;是用于統計計算和統計繪圖的優秀工具。而RStudio是R的集成開發環境&#xff0c;用它進行R編程的學習和實踐會更加輕松和方便。下面就教大家如何下載并…

豆瓣首頁話題輸入框的實現

在做問答的時候&#xff0c;遇到一個需求&#xff0c;用戶的問題需要限制字數&#xff0c;不僅顯示計算的超出字數&#xff0c;還需在超出的內容上加一些提醒的效果&#xff0c;例如豆瓣首頁的話題輸入框&#xff0c;抽時間研究了下&#xff0c;需要考慮下面幾個問題&#xff1…

pytorch 吸煙檢測yolov5s

YOLOV5s 吸煙目標檢測 參考學習 文章目錄 本原創項目長期更新&#xff0c;旨在完成校園異常行為實時精檢測&#xff0c;作到集成N次開發優化&#xff08;不止局限于調包&#xff09;為止&#xff0c;近期將不斷更新如下模型數據標注文件教程。關注博主&#xff0c;Star 一下g…

JQuery的ajax函數執行失敗,alert函數彈框一閃而過

先查看<form>標簽是否有action屬性&#xff0c;如果沒有&#xff0c;并且最后<button>標簽的type屬性為submit‘時&#xff0c;默認提交位置就是當前頁面 如果在頁面右鍵檢查&#xff0c;點擊網絡&#xff0c;會在開頭發現這樣的post包&#xff1a; 在右側消息頭處…

C#中Request.ServerVariables詳細說明及代理

Request.ServerVariables("Url") 返回服務器地址Request.ServerVariables("Path_Info") 客戶端提供的路徑信息Request.ServerVariables("Appl_Physical_Path") 與應用程序元數據庫路徑相應的物理路徑Request.ServerVariables("Path_Transla…

coco與voc相互轉化

把LabelImg標注的YOLO格式標簽轉化為VOC格式標簽 和 把VOC格式標簽轉化為YOLO格式標簽 點亮&#xff5e;黑夜 2020-07-07 11:08:24 3537 已收藏 90 分類專欄&#xff1a; 19—目標檢測 文章標簽&#xff1a; voc yolo 版權 把LabelImg標注的YOLO格式標簽轉化為VOC格式標簽 和…

angular中封裝fancyBox(圖片預覽)

首先在官網下載最新版的fancyBox(一定要去最新網站&#xff0c;以前依賴的jquery版本偏低)&#xff0c;附上鏈接&#xff1a;http://fancyapps.com/fancybox/3/ 然后在項目中引用jquery&#xff0c;然后在引用jquery.fancybox.min.css和jquery.fancybox.min.js。 如果需要動畫和…

十二省聯考題解 - JLOI2019 題解

十二省聯考題解 - JLOI2019 題解 兩個T3的難度較大 平均代碼量遠大于去年省選 套路題考查居多 A 難度等級 1 $n^2$暴力可以拿到$60$分的優秀成績 然后可以想到把區間異或轉化為前綴兩點異或 可以想到使用二分答案的方法可持久化Trie解決&#xff0c;但是時間復雜度為$n\log^2 (…