亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 網站 > WEB開發 > 正文

webpack中moduleId和chunkId

2024-04-27 15:14:12
字體:
來源:轉載
供稿:網友

建議在github閱讀

1.webpack打包策略分析

1.1 單入口文件

通過下面的打包結果,并結合下面說的多入口文件打包問題,應該是不難理解的。

/************************************************************************//******/ ([/* 0 *//***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(1);/***/ },/* 1 *//***/ function(module, exports, __webpack_require__) { var util1 = __webpack_require__(2) var util2 = __webpack_require__(3)/***/ },/* 2 *//***/ function(module, exports, __webpack_require__) { var util2 = __webpack_require__(3)/***/ },/* 3 *//***/ function(module, exports) { module.exports = {"name": "util2.js"}/***/ }/******/ ]);

這里只是需要注意一點,就是雖然有entry.js和util1.js同時引用了util2模塊,但是我們最終也只會為util2生成一個id!webpack打包的原理為,在入口文件中,對每個require資源文件配置一個id, 也 就是說,對于同一個資源,就算是require多次的話,它的id也是一樣的,所以無論在多少個文件中 require,它都只會打包一份。

1.2 多入口文件打包分析

1.2.1 多入口文件打包ID分配

首先webpack.config.js配置如下:

var path = require('path')var HtmlWebpackPlugin = require('html-webpack-plugin')var ExtractTextPlugin = require('extract-text-webpack-plugin')var webpack = require('webpack')module.exports = { entry: { index: ['./src/js1/entry.js'], //配置兩個入口 index2: ['./src/js1/entry2.js'] }, output: { path: path.resolve(__dirname, './dist/static'), publicPath: 'static/', filename: '[name].[chunkhash].js' }, resolve: { extensions: ['', '.js', '.less', '.swig', '.html'] }, module: { loaders: [ ] }, plugins: [ ]}

此時會在./dist/static目錄中生成兩個文件,分別對應于index.[chunkhash].js和index2.[chunkhash].js。

其中index.[chunkhash].js文件內容如下:

/************************************************************************//******/ ([/* 0 *//***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(1);/***/ },/* 1 *//***/ function(module, exports, __webpack_require__) { var util1 = __webpack_require__(2) var util2 = __webpack_require__(3)/***/ },/* 2 *//***/ function(module, exports, __webpack_require__) { var util2 = __webpack_require__(3)/***/ },/* 3 *//***/ function(module, exports) { module.exports = {"name": "util2.js"}/***/ }/******/ ]);

很顯然,入口文件的id是1,而入口文件引用的資源的id依次增加。同時注意一點:

/* 0 *//***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(1);/***/ },

也就是id為0的打包模塊其實是對入口文件調用的模塊,其中通過module.exports對外導出!

其中index2.[chunkhash].js文件內容如下:

/************************************************************************//******/ ([/* 0 *//***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(4);/***/ },/* 1 */,/* 2 */,/* 3 *//***/ function(module, exports) { module.exports = {"name": "util2.js"}/***/ },/* 4 *//***/ function(module, exports, __webpack_require__) { var util2 = __webpack_require__(3) setTimeout(function() {console.log(util2.name), 2000})/***/ }/******/ ]);

首先,和上面分析的一樣,我們對入口文件調用的模塊id是0,通過module.exports向外導出。

/* 4 *//***/ function(module, exports) { // removed by extract-text-webpack-plugin/***/ },/* 5 */,/* 6 */,/* 7 */,/* 8 *//***/ function(module, exports) { // removed by extract-text-webpack-plugin/***/ },/* 9 */,/* 10 *//***/ function(module, exports) { // removed by extract-text-webpack-plugin/***/ }

很清楚的知道id為5,6,7,8的情況沒有被分配,因為沒有被打包進來,這在單入口文件中也是存在的,而和extract-text-webpack-plugin沒有關系!而之所以是這樣,我猜測(需要證實)是webpack在打包的過程中自己生成了很多文件,而這些文件也分配了ID值,但是在我們的文件中并不需要這些模塊,所以就沒有引入為空!這可能和webpack自身的功能有關系。

1.2.2 多入口文件打包結果

下面給出了控制臺打包信息:

其中asset部分就是生產的文件的文件名,是name+chunkhash的格式;chunks就是對生成的文件的數字標注;chunkName就是我們在webpack配置中指定;

結合上面的分析很容易知道,對于入口文件調用的模塊Asset(打包資源)部分都是0,而其余資源的部分都是webpac打包后生成的id值!

1.2.3 CommonChunkPlugin插件作用

之前提到過,每個入口文件,都會獨立打包自己依賴的模塊,那就會造成很多重復打包的模塊,有沒有一種方法 能把多個入口文件中,共同依賴的部分給獨立出來呢? 肯定是有的 CommonsChunkPlugin

這個插件使用非常簡單,它原理就是把多個入口共同的依賴都給定義成一個新入口。為何我這里說是定義成新入口呢,因為這個名字不僅僅對應著js 而且對于著和它相關的CSS等,比如 HtmlWebpackPlugin 中 就能體現出來,可以它的 chunks中 加入 common 新入口,它會自動把common 的css也導入html

什么是chunkid?

可以參見控制臺的部分:

從圖中可以看到,我們最終輸出的common.js也是會有自己獨立的chunkid的(也就是chunks列),雖然我們在webpack的entry配置中并沒有指明(每個chunkid對應的是一個js文件):

entry: { index: ['./src/js1/entry.js'], index2: ['./src/js1/entry2.js'] },

這是CommonChunkPlugin插件完成的。為何要出來一個chunkid呢? 這個chunkid的作用就是,標記這個js文件是否已經加載過了。我們首先分析下這個plugin抽取出來的多個入口公共的代碼部分:

/******/ (function(modules) { // webpackBootstrap/******/ // install a JSONP callback for chunk loading/******/ var parentJsonpFunction = window["webpackJsonp"];/******/ window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules) {/******/ // add "moreModules" to the modules object,/******/ // then flag all "chunkIds" as loaded and fire callback/******/ var moduleId, chunkId, i = 0, callbacks = [];/******/ for(;i < chunkIds.length; i++) {/******/ chunkId = chunkIds[i];/******/ if(installedChunks[chunkId])//非0表示沒有加載完成,否則是數組,數組元素是函數/******/ callbacks.push.apply(callbacks, installedChunks[chunkId]);/******/ installedChunks[chunkId] = 0;//加載完成/******/ }/******/ for(moduleId in moreModules) {/******/ modules[moduleId] = moreModules[moduleId];/******/ }//modules中得到的都是函數,in遍歷數組的時候key是下標,此處modules存儲的是鍵值是每一個函數/******/ if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules); //首先調用父級jsonpFunction/******/ while(callbacks.length)/******/ callbacks.shift().call(null, __webpack_require__); //得到callback數組中的函數并調用,每一個回調函數傳入一個__webpack_require__就可以了/******/ if(moreModules[0]) {/******/ installedModules[0] = 0;/******/ return __webpack_require__(0);/******/ } //加載第一個模塊0,這個模塊是我們的入口文件的exports對象,相當于執行模塊了!其他的模塊只是打包進去,這個0表示直接執行了/******/ };/******/ // The module cache/******/ var installedModules = {};/******/ // object to store loaded and loading chunks/******/ // "0" means "already loaded"/******/ // Array means "loading", array contains callbacks //如果是正在加載那么這里就是一個數組,而且數組中包含的是回調函數/******/ var installedChunks = {/******/ 2:0 //common.js的chunkID是2表示一開始的時候就加載完成,因為他是通用模塊必須先加載,然后加載其他的/******/ };/******/ // 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] = {/******/ exports: {},/******/ id: moduleId,/******/ loaded: false/******/ };/******/ // Execute the module function //入口執行模塊是函數簽名是function(module, exports, __webpack_require__) /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);/******/ // Flag the module as loaded //模塊加載完成/******/ module.loaded = true;/******/ // Return the exports of the module/******/ return module.exports;/******/ }/******/ // This file contains only the entry chunk./******/ // The chunk loading function for additional chunks/******/ __webpack_require__.e = function requireEnsure(chunkId, callback) {/******/ // "0" is the signal for "already loaded"/******/ if(installedChunks[chunkId] === 0)/******/ return callback.call(null, __webpack_require__);/******/ // an array means "currently loading"./******/ if(installedChunks[chunkId] !== undefined) {/******/ installedChunks[chunkId].push(callback);/******/ } else {/******/ // start chunk loading/******/ installedChunks[chunkId] = [callback];/******/ var head = document.getElementsByTagName('head')[0];/******/ var script = document.createElement('script');/******/ script.type = 'text/javascript';/******/ script.charset = 'utf-8';/******/ script.async = true;/******/ script.src = __webpack_require__.p + "" + chunkId + "." + ({"0":"index","1":"index2"}[chunkId]||chunkId) + "." + {"0":"2a3a9ad51d7007de1a89","1":"e7a73c1617697d3e2912"}[chunkId] + ".js";/******/ head.appendChild(script);/******/ }/******/ };/******/ // expose the modules object (__webpack_modules__) //向外導出的modules包含了common.js這個文件,同時也包含我們的moreModules數組中的modules/******/ __webpack_require__.m = modules;/******/ // expose the module cache //webpack緩存模塊/******/ __webpack_require__.c = installedModules;/******/ // __webpack_public_path__ //webpack的__webpack_public_path__/******/ __webpack_require__.p = "static/";/******/ })/************************************************************************//******/ ({/***/ 3:/***/ function(module, exports) { module.exports = {"name": "util2.js"}/***/ }/******/ });

(1)webpackJsonp第一個參數是chunkId,但是我們的CommonChunkPlugin抽取出來的部分是作為modules參數傳入的,而且是一個引用,所以每次加載一個chunk的時候,他們引用的都是同一個

(2)這里要看清楚什么是chunk,什么是module,在webpackJsonp這個函數中第一個參數就是chunkId對應于chunk,而而第二個參數就是chunk中被打包進去的多個module,這也是為什么下面的webpackJsonpCallback的函數簽名是如下:

js webpackJsonpCallback(chunkIds, moreModules)

但是仔細想想,我們的common.js其實更像是一個module而不是chunk(因為他會被modules形參接受)。但是從控制臺中的輸出你可以知道其實webpack已經把它當做chunk了。我們common.js雖然沒有在entry中配置,但是我們實際上在common.js中被當做自執行函數的參數傳入最后放在modules中,以后再每一個chunk中require公有的這個文件的時候就直接require這個參數指定的內容就可以了

(3)modules得到的是一個chunk中所有的moreModules以及共有的commmon.js這個module(執行的時候只要運行moreModules[0]就可以了)。每次加載一個chunk,其modules最終都會包含我們的CommonChunkPlugin抽取出來的部分

(4)webpack_require方法最后返回的是modules[moduleId].call(module.exports, module, module.exports, webpack_require);也就是執行了id為0的入口文件的exports后得到的對象,這就是這個模塊的最后返回值

(5)在html中必須先加載common.js文件

<script src="{{ root }}common.js"><//script> <script src="{{ root }}index.js"><//script>

下面是每一個打包后的文件對common.js部分的依賴:

webpackJsonp([1],[/* 0 *//***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(4);/***/ },/* 1 */,/* 2 */,/* 3 */,/* 4 *//***/ function(module, exports, __webpack_require__) { var util2 = __webpack_require__(3) setTimeout(function() {console.log(util2.name), 2000})/***/ }]);
什么是moduleid?

結合上面的chunkid應該不難理解

2.參考資料

webpack打包原理解析


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91欧美视频网站| 欧美在线视频观看免费网站| 亚洲第一av在线| 日韩欧美国产视频| 91sao在线观看国产| 亚洲精品在线视频| 成人黄色av免费在线观看| 91在线观看免费高清完整版在线观看| 最近免费中文字幕视频2019| 久久久在线视频| 中文字幕日韩在线观看| 成人疯狂猛交xxx| 久久精品这里热有精品| 激情懂色av一区av二区av| 日韩精品在线影院| 午夜精品久久久久久久99热浪潮| 久久精品国产v日韩v亚洲| 日韩在线视频中文字幕| 久久亚洲成人精品| 亚洲免费一在线| 91精品国产色综合| 国产精品久久91| 久久全国免费视频| 38少妇精品导航| 久久琪琪电影院| 在线观看91久久久久久| 欧美日韩视频免费播放| 97香蕉久久夜色精品国产| 日韩中文字幕在线精品| 91成品人片a无限观看| 中文字幕精品www乱入免费视频| 美女黄色丝袜一区| 色综合久综合久久综合久鬼88| 亚洲人在线视频| 亚洲欧美另类国产| 国产九九精品视频| 日韩av免费观影| 搡老女人一区二区三区视频tv| 97视频在线观看成人| 91在线看www| 国产一级揄自揄精品视频| 国产精品丝袜一区二区三区| 欧美中文字幕视频在线观看| 欧美日韩免费网站| 久久国产精彩视频| 色综合天天综合网国产成人网| 欧美午夜视频在线观看| 黑人与娇小精品av专区| 91a在线视频| 欧美影院在线播放| www.欧美精品一二三区| 亚洲加勒比久久88色综合| 国产成人免费91av在线| 久久久97精品| 亚洲自拍偷拍网址| 精品露脸国产偷人在视频| 亚洲精品一区中文字幕乱码| 亚洲图片欧洲图片av| 57pao国产成人免费| www.国产精品一二区| 欧美精品国产精品日韩精品| 日韩精品在线第一页| 久久精品这里热有精品| 久久久久久久999精品视频| 在线观看91久久久久久| 96sao精品视频在线观看| 爽爽爽爽爽爽爽成人免费观看| 亚洲xxxx视频| 欧美一级片一区| 日韩中文视频免费在线观看| 精品国偷自产在线视频| 亚洲性线免费观看视频成熟| 91精品久久久久久久久久| 7m精品福利视频导航| 久久久久亚洲精品国产| 亚洲xxxx18| 精品亚洲国产成av人片传媒| 欧美乱大交xxxxx| 久久九九免费视频| 国产精品第一视频| 欧美午夜精品久久久久久久| 欧美日韩国产页| 国产精品久久77777| 亚洲国产精品免费| 国产69精品久久久久9999| 日韩欧美高清视频| 亚洲一区二区在线播放| 中文字幕亚洲二区| 国产午夜一区二区| 中文字幕亚洲无线码在线一区| 色婷婷久久一区二区| 成人福利在线视频| 欧美激情小视频| 国产精品久久久久久久久| 亚洲系列中文字幕| 久久九九有精品国产23| 97国产在线观看| 综合av色偷偷网| 久久免费视频观看| 国产精品wwww| 亚洲精品欧美日韩专区| 久久在线观看视频| 国产精品偷伦一区二区| 久久久久国产精品免费网站| 亚洲黄色av网站| 另类色图亚洲色图| 日韩毛片在线看| 亚洲最大成人在线| 精品日韩视频在线观看| 亚洲精品电影网| 美女av一区二区| 91国在线精品国内播放| 日产精品久久久一区二区福利| 亚洲视频在线播放| 在线看国产精品| 精品国产乱码久久久久久虫虫漫画| 欧美性猛xxx| 欧美xxxx14xxxxx性爽| 成人午夜激情免费视频| 国内精品久久久久伊人av| 久久这里有精品| 欧美日韩在线观看视频| 亚洲欧美在线免费观看| 日韩av男人的天堂| 精品国产一区二区三区久久| 欧美天天综合色影久久精品| 91老司机精品视频| 欧美精品在线观看91| 亚洲老板91色精品久久| 性色av一区二区三区红粉影视| 最近2019年手机中文字幕| 欧美又大又粗又长| 正在播放欧美一区| 亚洲xxxx妇黄裸体| 国产乱人伦真实精品视频| 成人在线国产精品| 精品久久久久久久久久久久久久| 精品亚洲一区二区三区四区五区| 国产性猛交xxxx免费看久久| 国产精品久久久久久久久久久久久久| 久久天天躁狠狠躁老女人| 欧美最猛性xxxxx(亚洲精品)| 久久久精品影院| 久久久久久国产精品三级玉女聊斋| 国产成人精品综合久久久| 国产精品日韩在线一区| 亚洲成人免费网站| 欧美男插女视频| 亚洲欧洲午夜一线一品| 永久555www成人免费| 亚洲精品一区二区三区婷婷月| 亚洲视频第一页| 综合久久五月天| 日本精品视频在线| 日韩欧美中文字幕在线观看| 性欧美长视频免费观看不卡| 成人精品网站在线观看| 久久久久99精品久久久久| 亚洲国产欧美一区二区三区同亚洲| 欧美日韩国产成人在线| 2025国产精品视频| 国产偷国产偷亚洲清高网站| 成人中文字幕+乱码+中文字幕| 日韩高清免费观看|