本文通过实际打包查看bundle.js的源码的方式来理解webpack的打包输出。
项目目录如下:
+ index.js
+ package.json
+ webpack.config.js
其中webpack.config.js的配置如下
const path = require('path');
module.exports = {
entry: './index.js',
mode: 'development',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
library: 'demo',
libraryTarget: 'umd'
},
}
index.js来模拟一个需要导出的包。并使用了esmodule的方式导出。
function demo() {
console.log('this is demo');
}export default demo;
以上的配置是希望打包出一个支持umd模块规范的lib库。执行webpack打包出了./dist/bundle.js,最好配合node中commonjs的规范对比理解。
我这里先把commonjs执行的过程列一下,详细见这里
// 1. 检查 Module._cache,是否缓存之中有指定模块
// 2. 如果缓存之中没有,就创建一个新的Module实例
// 3. 将它保存到缓存
// 4. 使用 module.load() 加载指定的模块文件,
// 读取文件内容之后,使用 module.compile() 执行文件代码
// 5. 如果加载/解析过程报错,就从缓存删除该模块
// 6. 返回该模块的 module.exports
打包出的文件源码内容摘略如下,请仔细看注释。
// umd规范
(function webpackUniversalModuleDefinition(root, factory) {
// commonjs2
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
// amd
else if(typeof define === 'function' && define.amd)
define([], factory);
// commonjs
else if(typeof exports === 'object')
exports["demo"] = factory();
else
// 注入到全局
root["demo"] = factory();
})(self, function() {
return /******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
// index.js 即为需要导出的模块,可以看出这就是一个kv组成的模块的map
/***/ "./index.js":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("...")
})
});
// 如同nodejs的commonjs,webpack也会缓存已经加载的模块。
var __webpack_module_cache__ = {};
/******/
/******/ // The require 函数
/******/ function __webpack_require__(moduleId) {
/******/ // 检查是否在缓存中
/******/ if(__webpack_module_cache__[moduleId]) {
/******/ return __webpack_module_cache__[moduleId].exports;
/******/ }
/******/ // 创建一个新的模块并放入到缓存,其实可以看出只是一个对象字面量
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // 执行Module中的代码
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // 导出模块。
/******/ return module.exports;
/******/ }
// 运行入口文件,并导出
/******/ return __webpack_require__("./index.js");
/******/ })()
;
});
可以看出,几乎就是Node.js commonjs规范的浏览器实现。可参考阮一峰的模块加载机制进行对比。这样相互印证,更好去理解和记忆。