麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 網(wǎng)站 > WEB開發(fā) > 正文

webpack中moduleId和chunkId

2024-04-27 15:14:12
字體:
供稿:網(wǎng)友

建議在github閱讀

1.webpack打包策略分析

1.1 單入口文件

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

/************************************************************************//******/ ([/* 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目錄中生成兩個文件,分別對應(yīng)于index.[chunkhash].js和index2.[chunkhash].js。

其中index.[chunkhash].js文件內(nèi)容如下:

/************************************************************************//******/ ([/* 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的打包模塊其實是對入口文件調(diào)用的模塊,其中通過module.exports對外導(dǎo)出!

其中index2.[chunkhash].js文件內(nèi)容如下:

/************************************************************************//******/ ([/* 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})/***/ }/******/ ]);

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

/* 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的情況沒有被分配,因為沒有被打包進(jìn)來,這在單入口文件中也是存在的,而和extract-text-webpack-plugin沒有關(guān)系!而之所以是這樣,我猜測(需要證實)是webpack在打包的過程中自己生成了很多文件,而這些文件也分配了ID值,但是在我們的文件中并不需要這些模塊,所以就沒有引入為空!這可能和webpack自身的功能有關(guān)系。

1.2.2 多入口文件打包結(jié)果

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

其中asset部分就是生產(chǎn)的文件的文件名,是name+chunkhash的格式;chunks就是對生成的文件的數(shù)字標(biāo)注;chunkName就是我們在webpack配置中指定;

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

1.2.3 CommonChunkPlugin插件作用

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

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

什么是chunkid?

可以參見控制臺的部分:

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

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

這是CommonChunkPlugin插件完成的。為何要出來一個chunkid呢? 這個chunkid的作用就是,標(biāo)記這個js文件是否已經(jīng)加載過了。我們首先分析下這個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表示沒有加載完成,否則是數(shù)組,數(shù)組元素是函數(shù)/******/ callbacks.push.apply(callbacks, installedChunks[chunkId]);/******/ installedChunks[chunkId] = 0;//加載完成/******/ }/******/ for(moduleId in moreModules) {/******/ modules[moduleId] = moreModules[moduleId];/******/ }//modules中得到的都是函數(shù),in遍歷數(shù)組的時候key是下標(biāo),此處modules存儲的是鍵值是每一個函數(shù)/******/ if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules); //首先調(diào)用父級jsonpFunction/******/ while(callbacks.length)/******/ callbacks.shift().call(null, __webpack_require__); //得到callback數(shù)組中的函數(shù)并調(diào)用,每一個回調(diào)函數(shù)傳入一個__webpack_require__就可以了/******/ if(moreModules[0]) {/******/ installedModules[0] = 0;/******/ return __webpack_require__(0);/******/ } //加載第一個模塊0,這個模塊是我們的入口文件的exports對象,相當(dāng)于執(zhí)行模塊了!其他的模塊只是打包進(jìn)去,這個0表示直接執(zhí)行了/******/ };/******/ // The module cache/******/ var installedModules = {};/******/ // object to store loaded and loading chunks/******/ // "0" means "already loaded"/******/ // Array means "loading", array contains callbacks //如果是正在加載那么這里就是一個數(shù)組,而且數(shù)組中包含的是回調(diào)函數(shù)/******/ 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 //入口執(zhí)行模塊是函數(shù)簽名是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__) //向外導(dǎo)出的modules包含了common.js這個文件,同時也包含我們的moreModules數(shù)組中的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第一個參數(shù)是chunkId,但是我們的CommonChunkPlugin抽取出來的部分是作為modules參數(shù)傳入的,而且是一個引用,所以每次加載一個chunk的時候,他們引用的都是同一個

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

js webpackJsonpCallback(chunkIds, moreModules)

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

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

(4)webpack_require方法最后返回的是modules[moduleId].call(module.exports, module, module.exports, webpack_require);也就是執(zhí)行了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?

結(jié)合上面的chunkid應(yīng)該不難理解

2.參考資料

webpack打包原理解析


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 亚洲成人福利在线观看 | 人人玩人人爽 | 思思久而久而蕉人 | 国产一级性生活视频 | 啪啪毛片 | 欧美乱淫 | 免费看欧美一级特黄a大片 久久免费视频一区二区三区 | 中文字幕免费播放 | 欧美国产第一页 | 伊人久操视频 | 国产亚洲欧美在线视频 | 久久久99精品视频 | 成人店女老板视频在线看 | 亚洲午夜一区二区三区 | 精品成人国产在线观看男人呻吟 | 欧美高清在线精品一区二区不卡 | 日本a v免费观看 | 在线视频观看一区二区 | 欧美黄色免费视频 | 亚洲无马在线观看 | www深夜成人 | 亚洲国产美女视频 | 国产妞干网 | 在线看免电影网站 | 欧美一级特级 | 日本在线看片 | 国产69精品久久久久久野外 | 性生活视频软件 | 91在线视频网址 | 久久艳片 | 色女人在线 | 婷婷一区二区三区四区 | 日韩激情一区二区三区 | 涩涩伊人| 国产人成精品综合欧美成人 | 久久亚洲精品久久国产一区二区 | 日本一区二区久久 | 成av人在线观看 | www.99re14.com| 狼伊千合综网中文 | 久久精品视频亚洲 |