### 1.一个入口,一个档案
webpack.config.js
````
模块. 导出 = {
Entry: './main.js', // 一个条目
输出: {
文件名:'bundle.js'
};
````
main.js
````
document.write('你好世界'); // 一份文件
````
捆绑包.js
````
/*****/ (函数(模块) { // webpackBootstrap
/*****/ // 模块缓存对象
/ ***** / var installModules = {};
/*****/
/*****/ // 需要函数
/*****/ 函数 __webpack_require__(moduleId) {
/*****/
/*****/ // 检查模块是否在缓存中,如果在,则返回exports对象
/*****/ if(installedModules[moduleId]) {
/ ***** /返回installedModules [moduleId] .exports;
/*****/ }
/*****/ // 如果不存在,则创建一个以 moduleId 为键的模块webpack export 函数,并将其加载到缓存中。
/*****/ var module =installedModules[moduleId] = {
/*****/ i: 模块Id,
/ ***** / l:假,
/*****/ 导出:{}
/*****/ };
/*****/
/*****/ //执行模块函数
/*****/ 模块[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/*****/
/*****/ // 标志模块已加载
/******/ module.l = true;
/*****/
/*****/ // 返回 module 导入的模块
/*****/ 返回模块.exports;
/*****/ }
/*****/
/*****/
/*****/ // 公开模块对象 (__webpack_modules__)
/*****/ __webpack_require__.m = 模块;
/*****/
/*****/ // 暴露模块缓存
/*****/ __webpack_require__.c =InstalledModules;
/*****/
/*****/ // 验证 Harmony 导出模块是否具有正确上下文的函数
/*****/ __webpack_require__.i = 函数(值) { 返回值; };
/*****/
/*****/ // 为 Harmony 导出模块定义 getter 函数
/*****/ __webpack_require__.d = 函数(导出、名称、getter){
/*****/ if(!__webpack_require__.o(exports, name)) {
/ ***** / Object.defineProperty(导出,名称,{
/ ***** /可配置:假,
/ ***** /可枚举:true,
/*****/ 获取:吸气剂
/*****/ });
/*****/ }
/*****/ };
/*****/
/*****/ // 兼容非和谐模块的getDefaultExport函数
/*****/ __webpack_require__.n = 函数(模块){
/*****/ var getter = module && module.__esModule ?
/*****/ function getDefault() { return module['default']; } } :
/******/ 函数 getModuleExports() { 返回模块; };
/*****/ __webpack_require__.d(getter, 'a', getter);
/*****/ 返回吸气剂;
/*****/ };
/*****/
/*****/ // Object.prototype.hasOwnProperty.call
/*****/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); } };
/*****/
/*****/ // 设置webpack公共路径 __webpack_public_path__
/*****/ __webpack_require__.p = "";
/*****/
/*****/ // 读取入口模块并返回exports import
/*****/ 返回 __webpack_require__(__webpack_require__.s = 0);
/*****/ })
/******************************************************** ***** *************************/
/*****/([
/* 0 */
/***/ (function(module,exports) { // 模块 ID 为 0
document.write('你好世界');
/***/ })
/*****/]);
````
整体分析
整个bundle.js是一个立即执行的函数表达式(IIFE),传入的参数modules是一个字段,数组中的每一项都是一个匿名函数,代表一个模块。 这里,数组的第一个参数是一个函数,里面的内容是main.js中的原始内容。
IIFE 已关闭。 _webpack_require__ 是模块加载函数。 它的作用是声明对其他模块的依赖并返回导出。 参数为模块的Id(每个模块都有唯一的id),不需要提供模块的相对路径,可以省去模块标识符的解析过程(准确的说,webpack提前了解析将需求模块的流程转移到构建期),从而获得更好的运行性能。
执行模块功能:
````
模块[moduleId].call(module.exports, module, module.exports, __webpack_require__);
````
通过借用调用,函数的 this 始终是模块本身。 参数__webpack_require__是让模块有能力加载其他模块。
程序流程图
该包通过 __webpack_require__(__webpack_require__.s = 0) 启动整个程序。 首先检查缓存中是否存在ID为0的模块。 如果存在,则返回缓存中exports暴露的对象; 如果不存在,则创建一个新的模块对象并将其加载到缓存中。 此时模块对象和模块的缓存对象installedModules[moduleId]还没有数据,所以需要执行该模块来返回具体需要的其他模块的数据。 传入的上下文是 module.exports (等于installedModules[moduleId].exports)。
### 2. 一个条目,多个文件
webpack.config.js
````
模块. 导出 = {
条目:'./main1.js',
输出: {
文件名:'bundle.js'
````
main1.js
````
var main = require('./main2.js')
document.write('你好世界');
main.webpack();
````
main2.js
````
导出.webpack = 函数() {
document.write('Hello Webpack');
````
捆绑包.js
````
/*****/ (函数(模块) { // webpackBootstrap
/*****/ 这部分与上部分相同
/*****/ // 加载入口模块并返回导出
/*****/ 返回 __webpack_require__(__webpack_require__.s = 1);
/*****/ })
/******************************************************** ***** *************************/
/*****/([
/* 0 */
/***/(函数(模块webpack export 函数,导出){
导出.webpack = 函数() {
document.write('Hello Webpack');
/***/ }),
/* 1 */
/***/ (函数(模块, 导出, __webpack_require__) {
var main = __webpack_require__(0)
document.write('你好世界');
主要的。 网页包();
/***/ })
/*****/]);
````
![]()
**整体分析**
webpack打包时,会分析模块之间的依赖关系,并对导出和导入模块相关的内容进行替换。 例如,在main1.js文件中,如果遇到var main = require('./main2.js'),则会转化为var __WEBPACK_IMPORTED_MODULE_0__main__ = __webpack_require__(0)。
由于有两个文件,所以IIFE的参数是一个宽度为2的链表,按照require的顺序排列。
**程序流程**
该包通过 __webpack_require__(__webpack_require__.s = 1) 启动整个程序。 与第一种情况不同的是,这里首先检查缓存中是否有ID为1的模块,因为main1.js依赖于main2.js,所以在main.js中调用了模块加载函数。 执行 var main = __webpack_require__(0) 时,会执行 module[0].call (这里的调用是为了保证每个模块中的 this 指向模块本身),然后执行 document.write('Hello World' ); ,最后执行 document.write('Hello Webpack'); 。 至此,__webpack_require__(1)已经执行完毕,这是一个递归的过程。
### 3.两个入口和两个导出文件
main1 包含inner1; main2 包含inner1 和inner2。
webpack.config.js
````
模块. 导出 = {
入口: {
Bundle1: './main1.js',
Bundle2: './main2.js'
},
输出: {
文件名:'[名称].js'
};
````
main1.js
````
var inner1 = require('./inner1.js');
内部1。 内部1();
document.write("我是main1")
````
main2.js
````
var inner1 = require('./inner1.js');
var inner2 = require('./inner2.js');
内部1。 内部1();
内部2。 内部2();
document.write("我是main2");
````
捆绑包1.js
````
/*****/ (函数(模块) { // webpackBootstrap
/*****/ 这部分与上部分相同
/*****/ // 加载入口模块并返回导出
/*****/ 返回 __webpack_require__(__webpack_require__.s = 2);
/*****/ })
/******************************************************** *** **************************/
/*****/([
/* 0 */
/***/(函数(模块,导出){
导出.inner1 = 函数() {
document.write('我是inner1');
/***/ }),
/* 1 */,
/* 2 */
/***/ (函数(模块, 导出, __webpack_require__) {
var inner1 = __webpack_require__(0);
内部1.内部1();
document.write("我是main1")
/***/ })
/*****/]);
````
Bundle2.js
````
/*****/ (函数(模块) { // webpackBootstrap
/*****/ 这部分与上部分相同
/*****/ // 加载入口模块并返回导出
/*****/ 返回 __webpack_require__(__webpack_require__.s = 3);
/*****/ })
/******************************************************** *** **************************/
/*****/([
/* 0 */
/***/(函数(模块,导出){
导出.inner1 = 函数() {
document.write('我是inner1');
/***/ }),
/* 1 */
/***/(函数(模块,导出){
导出.inner2 = 函数() {
document.write('我是inner2');
/***/ }),
/* 2 */,
/* 3 */
/***/ (函数(模块, 导出, __webpack_require__) {
var inner1 = __webpack_require__(0);
var inner2 = __webpack_require__(1);
内部1.内部1();
内部2.内部2();
document.write("我是main2");
/***/ })
/*****/]);
````
![]()
整体分析
对于多个条目文件的情况,如果单个条目独立执行,则各个条目文件不会互相干扰。
从里面可以看到,main1.js和main2.js这两个入口文件的module id都是0,所以可以知道每个入口文件对应的模块id都是0。而且由于每个模块id都是全局的唯一,main1中没有1; main2中没有2。
静态分析打包预先生成chunk,重复包含inner1.js文件。 如果需要消除模块冗余,可以通过CommonsChunkPlugin插件提取公共依赖模块。
![]()
四。 概括
-bundle.js文件是一个立即执行的函数表达式,传入的参数是一个模块的链表。 真正执行module的是modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);。
- Modules链表用于保存模块初始化函数,里面存储了实际使用的模块内容和一些ID信息。
-installedModules对象用于保存模块缓存对象,方便其他模块使用。
- __webpack_require__ 模块加载函数,require时获取的对象,参数为模块id。
-InstalledModules[moduleId].exports === module.exports === __webpack_exports__
- 一般情况下,webpack会解析获取所有必需的模块并合并它们; 为这些模块有序执行提供一个环境。