Last active
March 30, 2018 09:13
-
-
Save MrKou47/64832ea1fa4e8486cd8687a475e4cfbe to your computer and use it in GitHub Desktop.
dynamic import 测试
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
webpackJsonp([0],[ | |
/* 0 */, | |
/* 1 */ | |
/***/ (function(module, __webpack_exports__, __webpack_require__) { | |
"use strict"; | |
Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); | |
const a = 2; | |
/* harmony default export */ __webpack_exports__["default"] = (a); | |
function run() { | |
console.log(a); | |
} | |
run(); | |
/***/ }) | |
]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 立即执行函数 | |
* modules: any[] 传入entry module的id | |
* | |
* return: object | |
*/ | |
(function (modules) { // webpackBootstrap modules is an array | |
// install a JSONP callback for chunk loading | |
var parentJsonpFunction = window["webpackJsonp"]; | |
/** | |
* chunkIds: 异步加载的模块的id list -> [0] | |
* moreModules: [undefined, function(module, __webpack_exports__, __webpack_require__){}] | |
* executeModules: undefined | |
*/ | |
window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) { | |
// add "moreModules" to the modules object, | |
// 异步加载完成的模块 同样被 视为 模块,与同步的模块同等地位。但不表示此模块已安装,只是表示它是被依赖进来的 | |
// then flag all "chunkIds" as loaded and fire callback | |
// 如果 所有chunk 都已经被 **加载** 完毕 则触发callback | |
// 也就是说,webpack 并不保证异步模块中的代码全部执行完成,只要触发了 webpackJsonp 就代码此模块已经执行完成 | |
var moduleId, chunkId, i = 0, resolves = []/* 保存 promise resolve 函数的 list */, result; | |
for (; i < chunkIds.length; i++) { | |
chunkId = chunkIds[i]; | |
if (installedChunks[chunkId]) { | |
resolves.push(installedChunks[chunkId][0]); | |
} | |
installedChunks[chunkId] = 0; // 表示此需异步加载的模块已经加载完成,将其置为 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) { // 逐个执行resolve并从数组中移除 | |
resolves.shift()(); | |
} | |
}; | |
// The module cache | |
var installedModules = {}; | |
// objects to store loaded and loading chunks | |
var installedChunks = { | |
1: 0 | |
}; | |
/** The require function: realize commonjs require func | |
* 实现的 require 方法。代码中的require方法都将被此方法所代替 | |
* @param {*number} moduleId | |
*/ | |
function __webpack_require__(moduleId) { | |
// Check if module is in cache | |
// 如果当前模块已经被加载完成,则直接从 installedModules 中返回该模块 | |
if (installedModules[moduleId]) { | |
return installedModules[moduleId].exports; | |
} | |
// Create a new module (and put it into the cache) | |
/** | |
* 初始化一个空模块,包含了三个属性:模块id,是否已经load,和 暴露出的 变量/方法。 | |
* 同时将此模块插入到 installedModules 中 | |
*/ | |
var module = installedModules[moduleId] = { | |
i: moduleId, // module id | |
l: false, // load flag | |
exports: {} // what's export | |
}; | |
// Execute the module function | |
// 执行模块方法 | |
/** | |
* 我们定义的模块(文件), 都会被转换成函数的形式。例如: | |
* | |
* const a = 2; | |
* function test() { console.log(a) } | |
* test(); | |
* ⬇️️️️️️⬇️⬇️️⬇️⬇️ | |
* function(module, exports, __webpack_require__){ | |
* const a = 2; | |
* function test() { console.log(a) } | |
* test(); | |
* } | |
* | |
* 转换后的函数接收三个参数:整个模块,模块暴露的对象,以及 __webpck_require__ 方法。此方法用来替代代码中诸如 const http = require('http'); 代码中的 require 关键字 | |
* 通过 .call(module.exports, module, module.exports, __webpack_require__) 将模块的 this 替换为之前生成的空模块,然后执行模块中的方法。 | |
* | |
*/ | |
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; // 返回此模块暴露的对象 | |
} | |
/** | |
* 动态加载模块的方法,用来异步加载并执行一个模块 | |
* @param {*number} chunkId webpack 生成的文件的 chunkId。生成的文件名(如果未配置)形如 chunkId.[filename].js | |
* 如 __webpack_require__.e(0) 就是加载并执行 0.bundle.js | |
* | |
* 下面的注释将以 __webpack_require__.e(0) 为例子 | |
*/ | |
__webpack_require__.e = function requireEnsure(chunkId /* 传入 0 */) { | |
// 同样实现了一个缓存机制,和加载模块类似 | |
// 此时 installedChunks = { 1:0 }, 则 installedChunkData 为 undefined | |
var installedChunkData = installedChunks[chunkId]; | |
if (installedChunkData === 0) { // 没懂 | |
return new Promise(function (resolve) { resolve(); }); | |
} | |
// 用来表示正在加载模块的一个 Promise。installedChunkData === undefined 跳过 | |
if (installedChunkData) { | |
return installedChunkData[2]; | |
} | |
// setup Promise in chunk cache | |
var promise = new Promise(function (resolve, reject) { | |
installedChunkData = installedChunks[chunkId] = [resolve, reject]; | |
}); | |
/** | |
* installedChunkData: | |
* (2) [f, f] | |
* > 0: f () | |
* > 1: f () | |
*/ | |
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; | |
// nonce: number once 只被使用一次的随机数值 | |
if (__webpack_require__.nc) { | |
script.setAttribute("nonce", __webpack_require__.nc); | |
} | |
// 关键一步,设置script标签的src。可以看到是通过拼接预设的配置来完成的 | |
script.src = __webpack_require__.p + "" + chunkId + ".bundle.js"; | |
var timeout = setTimeout(onScriptComplete, 120000); // 超时 12000ms === 120s === 2min 的回调函数。目前没有找到设置超时时常的地方 | |
script.onerror = script.onload = onScriptComplete; | |
// 模块加载完成后 | |
function onScriptComplete() { | |
// avoid mem leaks in IE. 避免 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; | |
} | |
}; | |
/** | |
* 将 script 标签插入到 head。一般情况下,在插入成功后会执行 onScriptComplete。 | |
* 插入后会自动执行 0.bundle.js 的代码 | |
* | |
* 此时可以看一下 0.bundle.js 的代码。可以看到我们之前的 should-be-import 文件中的代码转换成了函数执行的方式。 | |
* 而执行的方式也就是上面向 window 对象中注入的 webpackJsonp函数 | |
*/ | |
head.appendChild(script); | |
return promise; | |
}; | |
// expose the modules object (__webpack_modules__) | |
__webpack_require__.m = modules; | |
// expose the module cache | |
__webpack_require__.c = installedModules; | |
// define getter function for harmony exports | |
__webpack_require__.d = function (exports, name, getter) { | |
if (!__webpack_require__.o(exports, name)) { | |
Object.defineProperty(exports, name, { | |
configurable: false, | |
enumerable: true, | |
get: getter | |
}); | |
} | |
}; | |
// getDefaultExport function for compatibility with non-harmony modules | |
__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; | |
}; | |
// Object.prototype.hasOwnProperty.call | |
__webpack_require__.o = function (object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; | |
// __webpack_public_path__ | |
__webpack_require__.p = ""; | |
// on error function for async loading | |
__webpack_require__.oe = function (err) { console.error(err); throw err; }; | |
// Load entry module and return exports | |
return __webpack_require__(__webpack_require__.s = 0); | |
}) | |
([ | |
/* 0 entry module */ | |
(function (module, exports, __webpack_require__) { | |
// 上面也说了异步加载的模块与同步依赖的模块同级别,只是未引入。 | |
// 在 __webpack_require__.e resolve 之后,使用 bind 创建一个新的 __webpack_require__ 函数,参数为 chunk 的 id | |
const importPromise = __webpack_require__.e(0).then(__webpack_require__.bind(null, 1)); | |
setTimeout(() => { | |
importPromise | |
.then(v => { | |
console.log(v); | |
}); | |
}, 4000); | |
}) | |
]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const importPromise = import('./should-be-import.js'); | |
setTimeout(() => { | |
importPromise | |
.then(v => { | |
console.log(v); | |
}); | |
}, 4000); | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const a = 2; | |
export default a; | |
function run() { | |
console.log(a); | |
} | |
run(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment