依赖版本
"webpack": "^4.44.2",
"webpack-cli": "^3.3.12"
一个简略的文件通过 webpack 打包
// 导出
console.log('index.js')
module.exports = '导出内容'
// 导入
let log = require('./log.js')
console.log('index.js 内容')
console.log(log)
打包后文件
(function (modules) { // webpackBootstrap
// The module cache
var installedModules = {};
// The require function
function __webpack_require__(moduleId) {
// Check if module is in cache
if (installedModules[moduleId]) {return installedModules[moduleId].exports;
}
// Create a new module (and put it into the cache)
var module = installedModules[moduleId] = {
i: moduleId,
l: false,
exports: {}};
// Execute the module function
// 把 index.js 导出内容挂载到 exports 上
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;
}
// 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, {
enumerable: true,
get: getter
});
}
};
// define __esModule on exports
__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;
};
// 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 = "";
// Load entry module and return exports
return __webpack_require__(__webpack_require__.s = "./src/index.js");
})
({
"./src/index.js":
/*! no static exports found */
(function (module, exports) {console.log('index.js 内容')
module.exports = '入口文件导出内容'
})
});
打包文件剖析特点剖析
- 打包后的文件就是一个函数自调用,以后函数调用时传入一个对象。这个对象是一个键值对
- 这个键名就是以后被加载模块的文件名与某个目录的拼接()
- 这个键值就是一个函数,和 node.js 里的模块加载有一些相似,会将被加载模块中的内容包裹于一个函数中
- 这个函数在未来某个工夫点上会被调用,同时会接管到肯定的参数,利用这些参数就能够实现模块的加载操作
- 针对于上述的代码就相当于是将 {}(模块定义)传递给了 modules
__webpack_require__
办法是 webpack 当中自定义的,它的核心作用就是返回模块的 exports。
单文件模块打包产出文件,会失去一个自调用函数,模块定义会传给 modules, 在文件中会调用 __webpack_require__
办法,传入主入口文件 id,导出内容会挂载到 module.exports 上,最初被返回给
return __webpack_require__(__webpack_require__.s = "./src/index.js");
通过一个 CommonJS 单步调试,联合打包后代码能够晓得打包后文件一些办法的大略作用
// 定义对象用于缓存已加载过的模块
var installedModules = {};
//__webpack_require__办法是 webpack 自定义的一个加载办法,外围性能就是返回被加载模块中导出的内容(具体外部是如何实现的,后续再剖析)function __webpack_require__(moduleId)
// 将模块定义保留一份,通过 m 属性挂载到自定义的办法身上
__webpack_require__.m = modules;
// o 属性判断被传入的对象 obj 身上是否具备指定的属性 *, 如果有则返回 true
__webpack_require__.o = function (object, property) {return Object.prototype.hasOwnProperty.call(object, property);
};
// define getter function for harmony exports
__webpack_require__.d = function (exports, name, getter) {
// 如果以后 exports 身上不具备 name 属性,则条件成立,增加成员属性 name
if (!__webpack_require__.o(exports, name)) {
Object.defineProperty(exports, name, {
enumerable: true,
get: getter
});
}
// define __esModule on exports, 给对象加一个标记,判断是否是 esModule
__webpack_require__.r = function (exports) {
// 解决 esModule
if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {// Object.prototype.toString.call(exports), 增加键,值是 Module
Object.defineProperty(exports, Symbol.toStringTag, {value: 'Module'});
}
// 如果条件不成立,咱们也间接在 exports 对象的身上增加一个 __esModule 属性,它的值就是 true
Object.defineProperty(exports, '__esModule', {value: true});
};
// 调用 t 办法之后,咱们会拿到被加载模块中的内容 value,对于 value 来说咱们可能会间接返回,也可能会解决之后再返回
__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;
};