前言
webpack可以将模块化代码转成浏览器所识别的模块化代码
你将学到的知识点
- webpack模块化原理
- webpack3异步加载模块原理
webpack模块化原理
解读:通过一个自执行函数传入一个模块化数组,通过数组索引来调用该模块函数。
//从零实现一个模块化函数
(function(modules) {
var installModules = {}
function __webpack_require__(moduleId) {
if(installModules[moduleId]) {
return installModules.exports
}
var module = installModules[moduleId] = {
i: moduleId,
l: false,
exports: {}
}
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__)
module.l = true
return module.exports
}
return __webpack_require__(0)
})([
(function(module, exports, __webpack_require__) {
//访问自身变量
var log = __webpack_require__(1)
log(1)
}),
(function(module, exports, __webpack_require__) {
module.exports = function(str) {
console.log(str)
}
})
])
webpack3异步加载模块原理
源代码实现异步加载模块
main.js
import('./util/index').then(_ => {
console.log(_.add(3,3))
})
util/index.js
module.exports = {
add: function(a, b) {
return a + b
}
}
webpack3源码实现异步加载模块(一)
解读:追加一个异步加载script标签,将Promise对象放到installedChunks对象,返回Promise实例对象。
main.js
(function(modules) {
var installedChunks = {
0: 0 //已经安装过的模块
}
var installedModule = {}
//导出一个模块
function __webpack_require__(moduleId) {
//...省略代码
}
//异步加载模块(按需加载)
__webpack_require__.e = function requireEnsure(chunkId) {
//加载模块
var moduleCurrent = installedChunks[chunkId]
if(moduleCurrent === 0) {
return new Promise(function(resolve) { resolve() })
}
if(moduleCurrent) {
return moduleCurrent[2]
}
var promise = new Promise(function(resolve, reject) {
moduleCurrent = installedChunks[chunkId] = [resolve, reject]
})
moduleCurrent[2] = promise
var head = document.getElementsByTagName('head')[0],
script = document.createElement('script');
script.src = chunkId + '.bundle.js'
script.async = true;
head.appendChild(script)
return promise
}
})([
(function(module, exports, __webpack_require__) {
__webpack_require__.e(1).then(__webpack_require__.bind(null, 1)).then(_ => {
_.add(3,3)
})
})
])
webpack3源码实现异步加载模块(二)
解读:通过以下步骤来执行代码,实现异步加载模块
1.bundle.js
//异步加载的文件
webpackJsonp(
[1],
[
,
(function(module, exports) {
function add(a,b) {
return a + b
}
module.exports = add
})
]
)
main.js
(function(modules) {
//异步加载模块
window['webpackJsonp'] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
var moduleId, chunkId, i = 0, resolve = [], result;
//循环拿到所有Promise
for(; i < chunkIds.length; i++) {
chunkId = chunkIds[i]
if(installedChunks[chunkId]) {
resolve.push(installedChunks[chunkId][0])
}
installedChunks[chunkId] = 0 //已经加载过了
}
//循环调用所有模块
for(moduleId in moreModules) {
if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
modules[moduleId] = moreModules[moduleId]
}
while(resolve.length) {
resolve.shift()()
}
}
}
var installedChunks = {
0: 0 //已经安装过的模块
}
var installedModule = {}
//导出一个模块
function __webpack_require__(moduleId) {
//...省略代码
}
//异步加载模块(按需加载)
__webpack_require__.e = function requireEnsure(chunkId) {
//...省略代码
}
})([
(function(module, exports, __webpack_require__) {
__webpack_require__.e(1).then(__webpack_require__.bind(null, 1)).then(_ => {
_.add(3,3)
})
})
])
结语
我们从零实现了
- webpack模块化代码
- webpack异步加载模块