一起探索最真实的世界
上一篇我们探讨了 webpack打包后的文件如何在浏览器中运行 涉及到了同步模块的加载
本次我们对main.js进行修改
main.js
// 异步加载 show.js
import('./show').then((show) => {
// 执行 show 函数
show('Webpack');
});
webpack
打包后的文件
| -- dist
| ---- bundle.js
| ---- 0.bundle.js
这边如果还是使用之前的webpack配置,会出现一个问题,加载0.bundle.js时会出现加载失败的问题,我们可以看下我们之前配置
webpack.config.js
const path = require('path');
module.exports = {
// JS 执行入口文件
entry: './main.js',
output: {
// 把所有依赖的模块合并输出到一个 bundle.js 文件
filename: 'bundle.js',
// 输出文件都放到 dist 目录下
path: path.resolve(__dirname, './dist'),
}
};
我们把所有的模块都输出到当前目录的dist路径下,在bundle文件中有一行代码是
script.src = __webpack_require__.p + "" + chunkId + ".bundle.js";
// **
// __webpack_public_path__
__webpack_require__.p = "";
我们可以看到我们去加载0.bundle.js时是直接加载index.html文件的同级目录下的0.bundle.js,这肯定会加载失败,那我们怎么去改变这个webpack_require_.p呢,从注释我们可以看到这个定义的是publicPath,webpack配置中就有publicPath
const path = require('path');
module.exports = {
// JS 执行入口文件
entry: './main.js',
output: {
// 把所有依赖的模块合并输出到一个 bundle.js 文件
filename: 'bundle.js',
// 配置publicPath
publicPath: './dist/',
// 输出文件都放到 dist 目录下
path: path.resolve(__dirname, './dist'),
}
};
此时重新
webpack
bundle.js
(function (modules) { // webpackBootstrap
// install a JSONP callback for chunk loading
var parentJsonpFunction = window["webpackJsonp"];
window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
// 把moreModules加入到modules中,
// then flag all "chunkIds" as loaded and fire callback
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];
}
}
if (parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);
while (resolves.length) {
resolves.shift()();
}
};
// The module cache
var installedModules = {};
// objects to store loaded and loading chunks
var installedChunks = {
1: 0
};
// 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;
}
// This file contains only the entry chunk.
// The chunk loading function for additional chunks
__webpack_require__.e = function requireEnsure(chunkId) {
var installedChunkData = installedChunks[chunkId];
// 如果installedChunkData 为0 那代表这个模块已经被加载直接返回Promise,并resolve
if (installedChunkData === 0) {
return new Promise(function (resolve) {
resolve();
});
}
// 如果installedChunkData非空且非0,那代表现在正在请求中,返回请求的promise
if (installedChunkData) {
return installedChunkData[2];
}
// setup Promise in chunk cache
var promise = new Promise(function (resolve, reject) {
installedChunkData = installedChunks[chunkId] = [resolve, reject];
});
installedChunkData[2] = promise;
// start chunk loading
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;
if (__webpack_require__.nc) {
script.setAttribute("nonce", __webpack_require__.nc);
}
script.src = __webpack_require__.p + "" + chunkId + ".bundle.js";
var timeout = setTimeout(onScriptComplete, 120000);
script.onerror = script.onload = onScriptComplete;
function onScriptComplete() {
// avoid mem leaks in IE.
script.onerror = script.onload = null;
clearTimeout(timeout);
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;
};
// __webpack_public_path__
__webpack_require__.p = "./dist/";
// Load entry module and return exports
return __webpack_require__(__webpack_require__.s = 0);
})
/************************************************************************/
([
/* 0 */
/***/
(function (module, exports, __webpack_require__) {
// 异步加载 show.js
__webpack_require__.e /* import() */ (0).then(__webpack_require__.bind(null, 1)).then((show) => {
// 执行 show 函数
show('Webpack');
});
})
]);
可以看到,webpack异步加载模块是通过jsonp的方式,我们看到入口模块函数中,先去调用 webpack_require.e(0) 加载模块0.bundle.js
0.bundle.js
webpackJsonp([0],[
/* 0 */,
/* 1 */
/***/ (function(module, exports) {
function show(content) {
window.document.getElementById('app').innerText = 'Hello,' + content;
}
// 通过 CommonJS 规范导出 show 函数
module.exports = show;
/***/ })
]);
一旦通过动态创建的script加载0.bundle.js后,就会执行webapckJsonp··