1.单一模块
index.js
export let num = 9;
let def = 44;
export default def;
打包后输出的文件(eval sourcemap部分删除)
(function(modules) { // webpackBootstrap
var installedModules = {};
function __webpack_require__(moduleId) {
if(installedModules[moduleId]) {
return installedModules[moduleId].exports;
}
var module = installedModules[moduleId] = {
i: moduleId,
l: false,
exports: {}
};
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);console.log(module)
module.l = true;
return module.exports;
}
__webpack_require__.m = modules;
__webpack_require__.c = installedModules;
__webpack_require__.d = function(exports, name, getter) {
if(!__webpack_require__.o(exports, name)) {
Object.defineProperty(exports, name, {
configurable: false,
enumerable: true,
get: getter
});
}
};
__webpack_require__.r = function(exports) {
Object.defineProperty(exports, '__esModule', { value: true });
};
__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;
};
__webpack_require__.o = function(object, property) {
return Object.prototype.hasOwnProperty.call(object, property);
};
__webpack_require__.p = "";
return __webpack_require__(__webpack_require__.s = "./src/index.js");
})({
"./src/index.js": (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n __webpack_require__.d(__webpack_exports__, \"num\", function() { return num; });\n let num = 9;\r\n let def = 44;\r\n __webpack_exports__[\"default\"] = (def);");
})
});
打包后的文件为一个自执行的函数匿名,参数为入口文件及其依赖的模块(此处没有依赖模块)
(function(modules) {
var installedModules = {};
function __webpack_require__(moduleId) {
...
}
__webpack_require__.m = modules;
__webpack_require__.c = installedModules;
__webpack_require__.d = function(){
...
}
__webpack_require__.r = function(){
...
}
__webpack_require__.n = function(){
...
}
__webpack_require__.o = function(){
...
}
__webpack_require__.p = '';
return __webpack_require__(__webpack_require__.s = "./src/index.js");
})({
"./src/index.js": (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("...");
})
匿名函数声明了一个installedModules对象,用于缓存加载进来的模块(加载进来的模块不一定加载完成)
声明了__webpack_require__,并为其添加了一些方法和属性:m、c、d、r、n、o
m:保存传入的模块对象
c:保存缓存的模块
d:在exports对象上添加属性
r:在exports对象上添加__esModule,用于标识es6模块
n:getDefaultExport
o:判断对象上是否有某一属性
__webpack_require__函数
function __webpack_require__(moduleId) {
//是否有缓存
if(installedModules[moduleId]) {
return installedModules[moduleId].exports;
}
var module = installedModules[moduleId] = {
i: moduleId, //模块id
l: false, //模块是否已加载
exports: {}
};
//加载模块
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
module.l = true;
return module.exports;
}
index.js模块里的东西通过modules[moduleId].call()中加载进来,最终的module包含如下内容
参数
{
"./src/index.js": (function(module, __webpack_exports__, __webpack_require__) {
//es6模块为严格模式
"use strict";
//每个模块都被eval执行
eval("__webpack_require__.r(__webpack_exports__);\n __webpack_require__.d(__webpack_exports__, \"num\", function() { return num; });\n let num = 9;\r\n let def = 44;\r\n __webpack_exports__[\"default\"] = (def);");
/*eval中执行了以下内容
* __webpack_require__.r(__webpack_exports__);
* __webpack_require__.d(__webpack_exports__, "num", function() { return num; });
* let num = 9;
* let def = 44;
* __webpack_exports__["default"] = def;
* */
}
"./src/index.js"为文件路径也是该模块的id
eval中为通过__webpack_require__.r给export添加__esModule属性,并定义num、default属性
2.依赖模块
chunk.js
let def = 44;
export default def;
index.js
import def from './chunk1.js';
export let num = 9;
打包后的文件(自执行函数体部分不变,仅展示参数部分)
{
"./src/chunk1.js": (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n let def = 44;\r\n __webpack_exports__[\"default\"] = (def);");
}),
"./src/index.js": (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n __webpack_require__.d(__webpack_exports__, \"num\", function() { return num; });\n var _chunk1_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(\"./src/chunk.js\");\n\r\n let num = 9;\r\n console.log(_chunk1_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"])");
})
}
index.js模块中调用__webpack_require__("./src/chunk1.js")加载chunk.js,最终installedModules如下
3.依赖重复模块
index.js
import chunk1 from './chunk1.js';
import chunk2 from './chunk2.js';
export let index1 = 9;
console.log(chunk1);
console.log(chunk2);
chunk1.js
import chunk2 from './chunk2.js';
let chunk1 = 1;
export default chunk1;
chunk2.js
let chunk2 = 2;
export default chunk2;
打包后的参数部分
({
"./src/chunk1.js": (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n var _chunk2_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(\"./src/chunk2.js\");\n\r\n let chunk1 = 1;\r\n __webpack_exports__[\"default\"] = (chunk1);");
}),
"./src/chunk2.js": (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n let chunk2 = 2;\r\n __webpack_exports__[\"default\"] = (chunk2);");
}),
"./src/index.js": (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n __webpack_require__.d(__webpack_exports__, \"index1\", function() { return index1; });\n var _chunk1_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(\"./src/chunk1.js\");\n var _chunk2_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(\"./src/chunk2.js\");\n\r let index1 = 9;\r\n console.log(_chunk1_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\r\n console.log(_chunk2_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);");
})
});
模块不会重复加载,chunk1中import chunk2.js __webpack_require__直接返回缓存中的数据
4.入口为数组
(function(modules) {
...
return __webpack_require__(__webpack_require__.s = 0);
})({
"./src/chunk1.js": (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n let chunk1 = 1;\r\n __webpack_exports__[\"default\"] = (chunk1);");
}),
"./src/index.js": (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n __webpack_require__.d(__webpack_exports__, \"index1\", function() { return index1; });\n var _chunk1_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(\"./src/chunk1.js\");\n\r\nlet index1 = 9;\r\n console.log(_chunk1_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);");
}),
"./src/index2.js": (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n __webpack_require__.d(__webpack_exports__, \"index2\", function() { return index2; });\n var _chunk1_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(\"./src/chunk1.js\");\n\r\nlet index2 = 66;");
}),
0: (function(module, exports, __webpack_require__) {
eval("__webpack_require__(\"./src/index.js\");\n module.exports = __webpack_require__(\"./src/index2.js\");");
})
});
相比字符串入口return的不再是index.js,而是moduleId为0的模块,在0模块中触发index、index2模块的加载并返回index2模块(数组中的最后一项)
5.使用splitChunks
runtimeChunk为true
index.bundle.js
(function(modules) {
// install a JSONP callback for chunk loading
function webpackJsonpCallback(data) {
var chunkIds = data[0];
var moreModules = data[1];
var executeModules = data[2];
// add "moreModules" to the modules object,
// then flag all "chunkIds" as loaded and fire callback
var moduleId, chunkId, i = 0, resolves = [];
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];
}
}
if(parentJsonpFunction) parentJsonpFunction(data);
while(resolves.length) {
resolves.shift()();
}
// add entry modules from loaded chunk to deferred list
deferredModules.push.apply(deferredModules, executeModules || []);
// run deferred modules when all chunks ready
return checkDeferredModules();
};
function checkDeferredModules() {
var result;
for(var i = 0; i < deferredModules.length; i++) {
var deferredModule = deferredModules[i];
var fulfilled = true;
for(var j = 1; j < deferredModule.length; j++) {
var depId = deferredModule[j];
if(installedChunks[depId] !== 0) fulfilled = false;
}
if(fulfilled) {
deferredModules.splice(i--, 1);
result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
}
}
return result;
}
var installedModules = {};
// object to store loaded and loading chunks
// undefined = chunk not loaded, null = chunk preloaded/prefetched
// Promise = chunk loading, 0 = chunk loaded
var installedChunks = {
"runtime~main": 0
};
// script path function
function jsonpScriptSrc(chunkId) {
return __webpack_require__.p + "" + chunkId + ".index.bundle.js"
}
var deferredModules = [];
// 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;
}
__webpack_require__.m = modules;
__webpack_require__.c = installedModules;
__webpack_require__.d = function(exports, name, getter) {
if(!__webpack_require__.o(exports, name)) {
Object.defineProperty(exports, name, {
configurable: false,
enumerable: true,
get: getter
});
}
};
__webpack_require__.r = function(exports) {
Object.defineProperty(exports, '__esModule', { value: true });
};
__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;
};
__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
__webpack_require__.p = "";
var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || [];
var oldJsonpFunction = jsonpArray.push.bind(jsonpArray);
//改写push方法,main中调用该方法
jsonpArray.push = webpackJsonpCallback;
jsonpArray = jsonpArray.slice();
//main.index.bundle.js push之前jsonpArray为空
for(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);
//保留原始的push方法,webpackJsonpCallback中通过该方法将main.inde.bundle.js中的数组添加进window["webpackJsonp"]
var parentJsonpFunction = oldJsonpFunction;
// run deferred modules from other chunks
checkDeferredModules();
})([]);
整体为一个自执行函数,因此时参数为空,index.bundle.js中只是绑定了一些属性、方法,并未加载具体的模块。
installedModules缓存已加载的模块
installedChunks缓存chunnk,值为undefined表示模块尚未加载,null表示preloaded/prefetched,promise表示加载中,0表示已加载
webpackJsonpCallback中处理数据绑定及回调
checkDeferredModules中检测chunks的加载情况,全部loaded后调用__webpack_require__('./src/index.js')处理具体模块的加载(./src/index.js为入口模块的id)
main.index.bundle.js
(window["webpackJsonp"] = window["webpackJsonp"] || []).push([
["main"],
{
"./src/chunk1.js": (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _chunk2_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./chunk2.js */ \"./src/chunk2.js\");\n\r\nlet chunk1 = 1;\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (chunk1);\n\n//# sourceURL=webpack:///./src/chunk1.js?");
}),
"./src/chunk2.js": (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\nlet chunk2 = 2;\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (chunk2);\n\n//# sourceURL=webpack:///./src/chunk2.js?");
}),
"./src/index.js": (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"index1\", function() { return index1; });\n/* harmony import */ var _chunk1_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./chunk1.js */ \"./src/chunk1.js\");\n/* harmony import */ var _chunk2_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./chunk2.js */ \"./src/chunk2.js\");\n\r\n\r\nlet index1 = 9;\r\nconsole.log(_chunk1_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n\n//# sourceURL=webpack:///./src/index.js?");
})
},
[["./src/index.js","runtime~main"]]
]);
window["webpackJsonp"].push会调用webpackJsonpCallback方法
6.动态加载
index.js
import chunk1 from './chunk1.js';
export let index1 = 9;
import('./chunk2.js').then(res=>{
console.log(res);
}).catch(e=>{
console.log(e)
})
打包后的代码仅main.index.bundle.js的"./src/index.js"eval部分不同
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, "index1", function() { return index1; });
var _chunk1_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/chunk1.js");
let index1 = 9;
Promise.resolve()
.then(__webpack_require__.bind(null, "./src/chunk2.js"))
.then(res=>{
console.log(res);
})
.catch(e=>{
console.log(e)
});
import()的promise直接resolve,回调在then(__webpack_require__.bind(null, "./src/chunk2.js"))后执行
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。