从打包之后的代码,看一下webpack如何实现的懒加载
懒加载的本质,代码分离,按需加载
这里使用的是最常用的import
先看一下懒加载效果
首次进入

点击div元素后加载module


test代码
export default ()=>{
console.log('%c +>>><<<<+','color:blue')
console.log('懒加载测试')
}
const com = require('./com')
console.log('模块导出测试')
emodule.export = {
name:'ljt'
}
const click =async ()=>{
const mod = await import('./com')
console.dir(mod)
}
const div = document.querySelector('#root')
document.addEventListener('click',click,div)
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>test</title>
</head>
<body>
<div id="root">
点击
</div>
<script src="./dist/main.js"></script>
</body>
</html>
打包之后的代码
main
/******/ (() => {
/******/ var __webpack_modules__ = {};
/******/ var __webpack_module_cache__ = {};
/******/ function __webpack_require__(moduleId) {
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
}
/******/ var module = (__webpack_module_cache__[moduleId] = {
/******/ exports: {},
});
/******/ __webpack_modules__[moduleId](
module,
module.exports,
__webpack_require__
);
/******/ return module.exports;
}
/******/ __webpack_require__.m = __webpack_modules__;
/******/ (() => {
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for (var key in definition) {
/******/ if (
__webpack_require__.o(definition, key) &&
!__webpack_require__.o(exports, key)
) {
/******/ Object.defineProperty(exports, key, {
enumerable: true,
get: definition[key],
});
}
}
};
})();
/******/ (() => {
/******/ __webpack_require__.f = {};
/******/ __webpack_require__.e = (chunkId) => {
/******/ return Promise.all(
Object.keys(__webpack_require__.f).reduce((promises, key) => {
/******/ __webpack_require__.f[key](chunkId, promises);
/******/ return promises;
}, [])
);
};
})();
/******/ (() => {
/******/ __webpack_require__.u = (chunkId) => {
/******/ return "" + chunkId + ".main.js";
};
})();
/******/ (() => {
/******/ __webpack_require__.g = (function () {
/******/ if (typeof globalThis === "object") return globalThis;
/******/ try {
/******/ return this || new Function("return this")();
} catch (e) {
/******/ if (typeof window === "object") return window;
}
})();
})();
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) =>
Object.prototype.hasOwnProperty.call(obj, prop);
/******/
})();
/******/ (() => {
/******/ var inProgress = {};
/******/ var dataWebpackPrefix = "test:";
/******/ __webpack_require__.l = (url, done, key, chunkId) => {
/******/ if (inProgress[url]) {
inProgress[url].push(done);
return;
}
/******/ var script, needAttach;
/******/ if (key !== undefined) {
/******/ var scripts = document.getElementsByTagName("script");
/******/ for (var i = 0; i < scripts.length; i++) {
/******/ var s = scripts[i];
/******/ if (
s.getAttribute("src") == url ||
s.getAttribute("data-webpack") == dataWebpackPrefix + key
) {
script = s;
break;
}
}
}
/******/ if (!script) {
/******/ needAttach = true;
/******/ script = document.createElement("script");
/******/ script.charset = "utf-8";
/******/ script.timeout = 120;
/******/ if (__webpack_require__.nc) {
/******/ script.setAttribute("nonce", __webpack_require__.nc);
/******/
}
/******/ script.setAttribute("data-webpack", dataWebpackPrefix + key);
/******/ script.src = url;
}
/******/ inProgress[url] = [done];
/******/ var onScriptComplete = (prev, event) => {
/******/ script.onerror = script.onload = null;
/******/ clearTimeout(timeout);
/******/ var doneFns = inProgress[url];
/******/ delete inProgress[url];
/******/ script.parentNode && script.parentNode.removeChild(script);
/******/ doneFns && doneFns.forEach((fn) => fn(event));
/******/ if (prev) return prev(event);
/******/
};
/******/ var timeout = setTimeout(
onScriptComplete.bind(null, undefined, {
type: "timeout",
target: script,
}),
120000
);
/******/ script.onerror = onScriptComplete.bind(null, script.onerror);
/******/ script.onload = onScriptComplete.bind(null, script.onload);
/******/ needAttach && document.head.appendChild(script);
};
})();
/******/ (() => {
/******/ __webpack_require__.r = (exports) => {
/******/ if (typeof Symbol !== "undefined" && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, {
value: "Module",
});
}
/******/ Object.defineProperty(exports, "__esModule", { value: true });
};
})();
/******/ (() => {
/******/ var scriptUrl;
/******/ if (__webpack_require__.g.importScripts)
scriptUrl = __webpack_require__.g.location + "";
/******/ var document = __webpack_require__.g.document;
/******/ if (!scriptUrl && document) {
/******/ if (document.currentScript)
/******/ scriptUrl = document.currentScript.src;
/******/ if (!scriptUrl) {
/******/ var scripts = document.getElementsByTagName("script");
/******/ if (scripts.length) {
/******/ var i = scripts.length - 1;
/******/ while (
i > -1 &&
(!scriptUrl || !/^http(s?):/.test(scriptUrl))
)
scriptUrl = scripts[i--].src;
}
}
}
/******/ if (!scriptUrl)
throw new Error("Automatic publicPath is not supported in this browser");
/******/ scriptUrl = scriptUrl
.replace(/#.*$/, "")
.replace(/\?.*$/, "")
.replace(/\/[^\/]+$/, "/");
/******/ __webpack_require__.p = scriptUrl;
/******/
})();
/******/ (() => {
/******/ var installedChunks = {
/******/ main: 0,
};
/******/ __webpack_require__.f.j = (chunkId, promises) => {
/******/ var installedChunkData = __webpack_require__.o(
installedChunks,
chunkId
)
? installedChunks[chunkId]
: undefined;
/******/ if (installedChunkData !== 0) {
/******/ if (installedChunkData) {
/******/ promises.push(installedChunkData[2]);
} else {
/******/ if (true) {
/******/ var promise = new Promise(
(resolve, reject) =>
(installedChunkData = installedChunks[chunkId] =
[resolve, reject])
);
/******/ promises.push((installedChunkData[2] = promise));
/******/ var url =
__webpack_require__.p + __webpack_require__.u(chunkId);
/******/ var error = new Error();
/******/ var loadingEnded = (event) => {
/******/ if (__webpack_require__.o(installedChunks, chunkId)) {
/******/ installedChunkData = installedChunks[chunkId];
/******/ if (installedChunkData !== 0)
installedChunks[chunkId] = undefined;
/******/ if (installedChunkData) {
/******/ 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;
/******/ installedChunkData[1](error);
}
}
};
/******/ __webpack_require__.l(
url,
loadingEnded,
"chunk-" + chunkId,
chunkId
);
}
}
}
};
/******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
/******/ var [chunkIds, moreModules, runtime] = data;
/******/ var moduleId,
chunkId,
i = 0;
/******/ if (chunkIds.some((id) => installedChunks[id] !== 0)) {
/******/ for (moduleId in moreModules) {
/******/ if (__webpack_require__.o(moreModules, moduleId)) {
/******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
}
}
/******/ if (runtime) var result = runtime(__webpack_require__);
}
/******/ if (parentChunkLoadingFunction) parentChunkLoadingFunction(data);
/******/ for (; i < chunkIds.length; i++) {
/******/ chunkId = chunkIds[i];
/******/ if (
__webpack_require__.o(installedChunks, chunkId) &&
installedChunks[chunkId]
) {
/******/ installedChunks[chunkId][0]();
}
/******/ installedChunks[chunkId] = 0;
}
};
/******/ var chunkLoadingGlobal = (self["webpackChunktest"] =
self["webpackChunktest"] || []);
/******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
/******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(
null,
chunkLoadingGlobal.push.bind(chunkLoadingGlobal)
);
/******/
})();
var __webpack_exports__ = {};
const click = async () => {
const mod = await __webpack_require__
.e(/*! import() */ "src_com_js")
.then(
__webpack_require__.bind(
__webpack_require__,
/*! ./com */ "./src/com.js"
)
);
console.dir(mod);
};
const div = document.querySelector("#root");
document.addEventListener("click", click, div);
})();
test
"use strict";
(self["webpackChunktest"] = self["webpackChunktest"] || []).push([["src_com_js"],{
/***/ "./src/com.js":
/*!********************!*\
!*** ./src/com.js ***!
\********************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (()=>{
console.log('%c +>>><<<<+','color:blue')
console.log('懒加载测试')
});
/***/ })
}]);
首先就是 en 是如何去加载异步模块的, 最开始 我也是认为是通过cdn,拿到js文件,然后通过script的onLoad事件去做的实现,但是并没有按照这种方式去实现
拿测试代码来说,首先就是我们点击后,触发了click,
首先会通过jsonp的方式去加载test文件
加载回来后,执行,然后加模块定义合并到modules中去,
最后在走的require。
看一下具体的代码
首先就是
__webpack_require__
.e(/*! import() */ "src_com_js")方法,这一步主要做了什么,主要是根据chunid去加载test文件,当然,这里其实使用了变量
installedChunks
去记录了我们哪一些模块是已经加载了的和loading中的,0 代表着已经加载完成了的
加载回来之后,需要执行此js,并合并到modules中去,这一步做的很巧妙
/******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
/******/ var [chunkIds, moreModules, runtime] = data;
/******/ // add "moreModules" to the modules object,
/******/ // then flag all "chunkIds" as loaded and fire callback
/******/ var moduleId,
chunkId,
i = 0;
/******/ if (chunkIds.some((id) => installedChunks[id] !== 0)) {
/******/ for (moduleId in moreModules) {
/******/ if (__webpack_require__.o(moreModules, moduleId)) {
/******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
/******/
}
/******/
}
/******/ if (runtime) var result = runtime(__webpack_require__);
/******/
}
/******/ if (parentChunkLoadingFunction) parentChunkLoadingFunction(data);
/******/ for (; i < chunkIds.length; i++) {
/******/ chunkId = chunkIds[i];
/******/ if (
__webpack_require__.o(installedChunks, chunkId) &&
installedChunks[chunkId]
) {
/******/ installedChunks[chunkId][0]();
/******/
}
/******/ installedChunks[chunkId] = 0;
/******/
}
/******/
/******/
};
/******/
/******/ var chunkLoadingGlobal = (self["webpackChunktest"] =
self["webpackChunktest"] || []);
/******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
/******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(
null,
chunkLoadingGlobal.push.bind(chunkLoadingGlobal)
);
/******/
这里绑定了push方法,在结合test文件看一下
"use strict";
(self["webpackChunktest"] = self["webpackChunktest"] || []).push([["src_com_js"],{
/***/ "./src/com.js":
/*!********************!*\
!*** ./src/com.js ***!
\********************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (()=>{
console.log('%c +>>><<<<+','color:blue')
console.log('懒加载测试')
});
/***/ })
}]);
这里的self就是window
合并完之后,去加载这个模块
const mod = await __webpack_require__
.e(/*! import() */ "src_com_js")
.then(
__webpack_require__.bind(
__webpack_require__,
/*! ./com */ "./src/com.js"
)
);
还是通过require去做的加载,但是require里也没有用到this,所以我想__webpack_require__.bind只是为了快速生成then的回调函数
- THE END -
非特殊说明,本博所有文章均为博主原创。
共有 0 条评论