Webpack 编译后代码解读 模块原理 异步加载原理
2021/8/6 6:08:02
本文主要是介绍Webpack 编译后代码解读 模块原理 异步加载原理,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
webpack编译后源码分析
分模块
- 定义缓存模块的数组为空
- 有一个起始模块执行
- 当请求(require)起始模块时,查找缓存是否存在,不存在需要从模块列表加载并缓存,并且通过call传递
module
,exports
,__webpack_require__
// 01 自执行 (function (modules) { // 02 require缓存 var installedModules = {} // 03 require函数封装 function __webpack_require__(moduleId) { // 05 判断缓存 if (installedModules[moduleId]) { return installedModules[moduleId].exports } // 06 封装需要传递到模块的module,export,require var module = installedModules[moduleId] = { i: moduleId, l: false, exports: {} } // 07 call调用模块函数 modules[moduleId].call(module.exports, module, module.exports, __webpack_require__) 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, { enumerable: true, get: getter }) } } __webpack_require__.r = function (exports) { if (typeof Symbol !== 'undefined' && Symbol.toStringTag) { Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }) } Object.defineProperty(exports, '__esModule', { value: true }) } __webpack_require__.t = function (value, mode) { if (mode & 1) value = __webpack_require__(value) if (mode & 8) return value if ((mode & 4) && typeof value === 'object' && value && value.__esModule) return value var ns = Object.create(null) __webpack_require__.r(ns) Object.defineProperty(ns, 'default', { enumerable: true, value: value }) if (mode & 2 && typeof value != 'string') for (var key in value) __webpack_require__.d(ns, key, function (key) { return value[key] }.bind(null, key)) return ns } __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 = '' // 04 起始模块启动 return __webpack_require__(__webpack_require__.s = 'A7Gu') })({ 'A7Gu': (function (module, exports, __webpack_require__) { // 08 请求react,react-dom var React = __webpack_require__('u6V5') var ReactDom = __webpack_require__('I7V5') // 09 起始方法的内容执行 var app = React.createElement('div', { id: 'app', onClick: function () { alert('message') } }, '\u4ECA\u5929\u5929\u6C14\u4E0D\u597D') ReactDom.render(app, document.getElementById('app')) }), 'u6V5': (function (module, exports, __webpack_require__) { var react = { createElement(type, attrs, children) { return { type, attrs, children } } } module.exports = react }), 'I7V5': (function (module, exports, __webpack_require__) { var ReactDom = { render({ attrs }, container) { let ele = document.createElement(element.type) for (var attr in attrs) { if (attr === 'onClick') { ele.onclick = attrs[attr] } else { ele.setAttribute(attr, attrs[attr]) } } if (typeof element.children === 'string') { let text = document.createTextNode(element.children) ele.appendChild(text) } if (container) { container.appendChild(ele) } else { document.body.appendChild(ele) } } } module.exports = ReactDom }) })
异步加载
- 在上面的前提上
- 当异步加载时,包装成promise方式,then之后require模块
- 包装script标签加载
- 请求完成自执行,添加到异步缓存标记表示已经加载(当下次异步请求直接返回)
- 然后放到模块列表中,之后执行resove()到then中
- then中在require模块,添加到缓存并传递module,export,require call调用当前函数
- 产生闭包,后面使用模块下面的函数,属性即可
下面标记async是表示,和上面的区别
// main.js (function (modules) { var installedModules = {} /*async*/ // 01 异步标记缓存 var installedChunks = { 'main': 0 // main是起始,可以删除 } /*async*/ function webpackJsonpCallback(data) { // 05 push到这里 var chunkIds = data[0] var moreModules = data[1] var moduleId, chunkId, i = 0, resolves = [] // 06 异步加载的模块可以是多个 for (; i < chunkIds.length; i++) { chunkId = chunkIds[i] if (Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) { // 07 promise的resolve resolves.push(installedChunks[chunkId][0]) } installedChunks[chunkId] = 0 } for (moduleId in moreModules) { if (Object.prototype.hasOwnProperty.call(moreModules, moduleId)) { // 08 缓存到模块列表 modules[moduleId] = moreModules[moduleId] } } if (parentJsonpFunction) parentJsonpFunction(data) // 09 依次调用resove,即then的逻辑 while (resolves.length) { resolves.shift()() } } 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__) 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, { enumerable: true, get: getter }) } } /*async*/ function jsonpScriptSrc(chunkId) { return __webpack_require__.p + '' + ({}[chunkId] || chunkId) + '.js' } /*async*/ __webpack_require__.e = function requireEnsure(chunkId) { var promises = [] var installedChunkData = installedChunks[chunkId] if (installedChunkData !== 0) { if (installedChunkData) { promises.push(installedChunkData[2]) } else { // 03 创建promise var promise = new Promise(function (resolve, reject) { installedChunkData = installedChunks[chunkId] = [resolve, reject] }) promises.push(installedChunkData[2] = promise) // 04 创建script标签,请求 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) { // 10 收尾 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) } __webpack_require__.r = function (exports) { if (typeof Symbol !== 'undefined' && Symbol.toStringTag) { Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }) } Object.defineProperty(exports, '__esModule', { value: true }) } __webpack_require__.t = function (value, mode) { if (mode & 1) value = __webpack_require__(value) if (mode & 8) return value if ((mode & 4) && typeof value === 'object' && value && value.__esModule) return value var ns = Object.create(null) __webpack_require__.r(ns) Object.defineProperty(ns, 'default', { enumerable: true, value: value }) if (mode & 2 && typeof value != 'string') for (var key in value) __webpack_require__.d(ns, key, function (key) { return value[key] }.bind(null, key)) return ns } __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 = '' /*async*/ __webpack_require__.oe = function (err) { console.error(err) throw err } var jsonpArray = window['webpackJsonp'] = window['webpackJsonp'] || [] var oldJsonpFunction = jsonpArray.push.bind(jsonpArray) jsonpArray.push = webpackJsonpCallback jsonpArray = jsonpArray.slice() for (var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]) var parentJsonpFunction = oldJsonpFunction return __webpack_require__(__webpack_require__.s = 'A7Gu') })({ 'A7Gu': (function (module, exports, __webpack_require__) { var React = __webpack_require__('u6V5') var ReactDom = __webpack_require__('I7V5') var htdiv = React.createElement('div', { id: 'my', onClick: function () { // 02 包装,请求异步模块,完成之后在require __webpack_require__.e(0).then((function () { var A = __webpack_require__('46Hr') A.log('哈哈哈') alert(A.message) }).bind(null, __webpack_require__)).catch(__webpack_require__.oe) } },'\u4ECA\u5929\u5929\u6C14\u4E0D\u597D') ReactDom.render(htdiv, document.getElementById('app')) }), 'u6V5': (function (module, exports, __webpack_require__) { var react = { createElement(type, attrs, children) { return { type, attrs, children } } } module.exports = react }), 'I7V5': (function (module, exports, __webpack_require__) { var ReactDom = { render(element, container) { let ele = document.createElement(element.type) for (var attr in element.attrs) { if (attr === 'onClick') { ele.onclick = element.attrs[attr] } else { ele.setAttribute(attr, element.attrs[attr]) } } if (typeof element.children === 'string') { let text = document.createTextNode(element.children) ele.appendChild(text) } if (container) { container.appendChild(ele) } else { document.body.appendChild(ele) } } } module.exports = ReactDom }) })
// 0.js // 04 push操作 (window['webpackJsonp'] = window['webpackJsonp'] || []).push([[0], { '46Hr': (function (module, exports) { var A = { log() { console.log(...arguments) }, message: 'hello ' } module.exports = A }) }])
这篇关于Webpack 编译后代码解读 模块原理 异步加载原理的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-26怎么使用nsenter命令进入容器?-icode9专业技术文章分享
- 2024-12-26导入文件提示存在乱码,请确定使用的是UTF-8编码怎么解决?-icode9专业技术文章分享
- 2024-12-26csv文件怎么设置编码?-icode9专业技术文章分享
- 2024-12-25TypeScript基础知识详解
- 2024-12-25安卓NDK 是什么?-icode9专业技术文章分享
- 2024-12-25caddy 可以定义日志到 文件吗?-icode9专业技术文章分享
- 2024-12-25wordfence如何设置密码规则?-icode9专业技术文章分享
- 2024-12-25有哪些方法可以实现 DLL 文件路径的管理?-icode9专业技术文章分享
- 2024-12-25错误信息 "At least one element in the source array could not be cast down to the destination array-icode9专业技术文章分享
- 2024-12-25'flutter' 不是内部或外部命令,也不是可运行的程序 或批处理文件。错误信息提示什么意思?-icode9专业技术文章分享