Webpack中懒加载的方式
1.第一种:import()
import('./a').then((data) => {
console.log(data);
});
2.第二种:require.ensure()
const home = resolve => {
require.ensure(['./home.vue'], () => {
resolve(require('./home.vue'))
}, 'home')
}
const routes = [
{
path: '/',
component: home
}
]
分析
- webpack版本4.43.0(公司用的这个版本)
构建项目
- package.json
{
"name": "webpack-test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack --config ./webpack.config.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"webpack": "^5.76.2",
"webpack-cli": "^5.0.1"
},
"devDependencies": {}
}
- webpack.config.js
const path = require('path');
module.exports = {
mode: 'development',
entry: './index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
}
- a.js
const a = 'a模块';
export default a;
- index.js
import('./a').then((data) => {
console.log(data);
});
代码
- 有删减只剩下觉得有用的部分
index.js被编译后
__webpack_require__
.e(/*! import() */ 0)
.then(__webpack_require__.bind(null, /*! ./a */ \"./a.js\"))
.then((data) => {console.log(data);});
- 将import()编译成了__webpack_require__.e函数
webpack_require.e函数
- 疑问点:这里只是将
resolve和reject全部存入了installedChunks,并没有执行resolve
// 加载过的js
var installedChunks = {
"main": 0
}
__webpack_require__.e = function requireEnsure(chunkId) {
var promises = [];
var installedChunkData = installedChunks[ chunkId ];
/**
* 等于0代表加载过了直接传入一个空数组
* 等于promises代表正在加载,继续传入Promise.all
* 等于null代表还未加载过
*/
if (installedChunkData !== 0) {
if (installedChunkData) {
promises.push(installedChunkData[ 2 ]);
} else {
var promise = new Promise(function (resolve, reject) {
// 将resolve, reject放入installedChunks的对应chunkId中
installedChunkData = installedChunks[ chunkId ] = [ resolve, reject ];
})
promises.push(installedChunkData[ 2 ] = promise);
// 创建script标签-jsonp
var script = document.createElement('script');
var onScriptComplete;
script.charset = 'utf-8';
// 设置超时时间
script.timeout = 120;
if (__webpack_require__.nc) {
script.setAttribute("nonce", __webpack_require__.nc);
}
script.src = jsonpScriptSrc(chunkId);
var error = new Error();
// 加载完成后
onScriptComplete = function (event) {
script.onerror = script.onload = null;
clearTimeout(timeout);
var chunk = installedChunks[ chunkId ];
// 未能成功加载
if (chunk !== 0) {
if (chunk) {
var errorType = event && (event.type === 'load' ? 'missing' : event.type);
var realSrc = event && event.target && event.target.src;
error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')';
error.name = 'ChunkLoadError';
error.type = errorType;
error.request = realSrc;
chunk[ 1 ](error);
}
installedChunks[ chunkId ] = undefined;
}
};
var timeout = setTimeout(function () {
onScriptComplete({ type: 'timeout', target: script });
}, 120000);
// 注意:加载成功或失败走的是一个函数
script.onerror = script.onload = onScriptComplete;
document.head.appendChild(script);
}
}
return Promise.all(promises);
};
0.bundle.js
- 这里调用了
window["webpackJsonp"].push()函数 - 在
push()执行完后最后会回到onScriptComplete清除定时器
(window[ "webpackJsonp" ] = window[ "webpackJsonp" ] || []).push([ [ 0 ], {
"./a.js":
(function (module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\nconst a = 'a模块';\n/* harmony default export */ __webpack_exports__[\"default\"] = (a);\n\n//# sourceURL=webpack:///./a.js?");
})
} ]);
window["webpackJsonp"].push()
- 将
installedChunks\[chunkId]置为0
function webpackJsonpCallback(data) {
var chunkIds = data[ 0 ];
var moreModules = data[ 1 ];
var moduleId, chunkId, i = 0, resolves = [];
for (; i < chunkIds.length; i++) {
chunkId = chunkIds[ i ];
if (Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[ chunkId ]) {
// 保存resolve
resolves.push(installedChunks[ chunkId ][ 0 ]);
}
// 把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);
// 执行resolve
while (resolves.length) {
resolves.shift()();
}
};
var jsonpArray = window[ "webpackJsonp" ] = window[ "webpackJsonp" ] || [];
var oldJsonpFunction = jsonpArray.push.bind(jsonpArray);
jsonpArray.push = webpackJsonpCallback;
jsonpArray = jsonpArray.slice();
总结
- Webpack的懒加载就是依赖于Jsonp方式直接引入+Promise来实现的
- 最后说一句,第一次写文章如果有错误请@一下,会立马改正的,谢谢啦🙏