以下分析都是基于webpack4。
首先写一个最基础的webpack配置工程文件:
const path = require("path");
module.exports = {
entry: path.join(__dirname, 'index.js'),
output: {
path: path.join(__dirname, 'outs'),
filename: 'index.js'
},
mode: 'development'
};
入口文件index.js如下:
import Add from './add';
import math from './math';
console.log(Add(1, 2));
console.log(math.add(1, 2));
两个引用的模块也非常简单:
add.js
export default function(a, b) {
return a + b;
};
math.js
exports.add = function(a, b) {
return a + b;
}
exports.mult = function(a, b) {
return a * b;
}
这两个模块的导出形式也是ES6规定的两种导出形式。下面看一下webpack将文件打包的最终样子:
(function(modules) { // webpackBootstrap
// 已经加载的模块缓存
var installedModules = {};
// webpack的require函数实现
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__);
// l变量标示模块是否加载过了
module.l = true;
// 返回模块暴露给外面的对象
return module.exports;
}
// 暴露给外接的模块对象 这里的模块对象是所有的模块集合 (__webpack_modules__)
__webpack_require__.m = modules;
// 暴露的模块缓存
__webpack_require__.c = installedModules;
// 给exports出来的每一个属性都定义一个getter函数
__webpack_require__.d = function(exports, name, getter) {
if(!__webpack_require__.o(exports, name)) {
Object.defineProperty(exports, name, { enumerable: true, get: getter });
}
};
// 给exports对象定义__esModule属性
__webpack_require__.r = function(exports) {
if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
}
Object.defineProperty(exports, '__esModule', { value: true });
};
// create a fake namespace object
// mode & 1: value is a module id, require it
// mode & 2: merge all properties of value into the ns
// mode & 4: return value when already ns object
// mode & 8|1: behave like require
__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;
};
// 兼容 non-harmony 模块,这些模块如果设了__esModule属性,则被标记为non-harmony
__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 = "";
// 先require入口文件
return __webpack_require__(__webpack_require__.s = "./index.js");
})
/***/ "./add.js":
/*!****************!*\
!*** ./add.js ***!
\****************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (function(a, b) {\n return a + b;\n});;\n\n\n//# sourceURL=webpack:///./add.js?");
/***/ }),
/***/ "./index.js":
/*!******************!*\
!*** ./index.js ***!
\******************/
/*! no exports provided */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
console.log(__webpack_exports__);
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _add__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./add */ \"./add.js\");\n/* harmony import */ var _math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./math */ \"./math.js\");\n/* harmony import */ var _math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_math__WEBPACK_IMPORTED_MODULE_1__);\n\n\n\nconsole.log(Object(_add__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(1, 2));\n\nconsole.log(_math__WEBPACK_IMPORTED_MODULE_1___default.a.add(1, 2));\n\n\n//# sourceURL=webpack:///./index.js?");
/***/ }),
/***/ "./math.js":
/*!*****************!*\
!*** ./math.js ***!
\*****************/
/*! no static exports found */
/***/ (function(module, exports) {
eval("\nexports.add = function(a, b) {\n return a + b;\n}\nexports.mult = function(a, b) {\n return a * b;\n}\n\n//# sourceURL=webpack:///./math.js?");
/***/ })
/******/ });
代码文件打包后如何加载
再来看看打包后代码文件变成什么样子了,大致的结构就是一个对象,key是文件路径,其实就是moduleId,value是一个函数
(function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval(' // 模块代码的字符串');
})
什么时候执行呢,如上就是在webpack_require函数加载模块的时候,下面把入口文件的代码字符串拆出来看一下:
__webpack_require__.r(__webpack_exports__);
/* harmony import */
var _add__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./add */ "./add.js");
/* harmony import */
var _math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./math */ "./math.js");
/* harmony import */
var _math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_math__WEBPACK_IMPORTED_MODULE_1__);
console.log(Object(_add__WEBPACK_IMPORTED_MODULE_0__["default"])(1, 2));
console.log(_math__WEBPACK_IMPORTED_MODULE_1___default.a.add(1, 2));
首先调用的__webpack_require__.r, 只是定义了exports的属性而已 无关大局。
接下来就是调用webpack的require函数,加载两个依赖的模块。
最后再执行。在这里也可以看到了,webpack将文件的路径作为moduleId。
至此,webpack打包文件大致分析完了。
网友评论