依赖版本
"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 = https://www.it610.com/article/__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");
【webpack简单文件打包实例】通过一个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 = https://www.it610.com/article/__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;
};
CommonJS导入EsModule
// log.js文件下EsMoudle导出
export default "jack"
export const age = 18;
// index.js文件下CommonsJS导入EsModule
let log = require('./log.js')
console.log('index.js内容')
console.log("log", log.default, log.age)
通过
yarn webpack
打包webpack默认支持
CommonJS
打包,而通过CommonJS规范引入EsMoudle导出对象,文章图片
export default "jack"
默认导出时,直接挂载default
属性。而export const age = 18;
首先调用r
方法标记为一个esModule
,然后调用d
方法往对象身上挂载一个age
属性,并且给age
属性通过一个getter
方法。文章图片
文章图片
EsModule导入CommonJS或者EsModule在于区分导入模块是否是EsModule,会通过
r
方法挂载EsModule标记