webpack务虚扫盲 打包工具的角色 打包工具的结构 为什么使用webpack? webpack的工作原理 打包工具的角色 打包工具的结构 为什么使用webpack? webpack的工作原理
http://www.cnblogs.com/libin-1/p/6938581.html
所谓打包工具在web开发中主要解决的问题是:
(1)文件依赖管理。毕竟现在都是模块化开发,打包工具首先就是要梳理文件之间的依赖关系。
(2)资源加载管理。web本质就是html、js和css的文件组合,文件的加载顺序(先后时机)和文件的加载数量(合并、嵌入、拆分)也是打包工具重点要解决的问题。
(3)效率与优化管理。提高开发效率,即写最少的代码,做最好的效果展示;尽可能的使用工具,减少机械coding和优化页面效果,这个是考验打包工具是否具备魅力的点。
打包工具的结构
由上图可以推出,打包工具的结构应该是tool+plugins的结构。tool提供基础能力,即文件依赖管理和资源加载管理;在此基础上通过一系列的plugins来丰富打包工具的能力。plugins类似互联网+的概念,文件经plugins处理之后,具备了web渲染中的某种优势。
为什么使用webpack?
决定打包工具能走多远的是plugins的丰富程度,而webpack目前恰恰是最丰富的,我这里对比了一下fis与webpack在npm包上数据,看完就知道为什么要使用webpack了。
webpack的工作原理
webpack处理文件的过程可以分为两个维度:文件间的关系和文件的内容。文件间的关系处理,主要是通过文件和模块标记方法来实现;文件内容的处理主要通过loaders和plugins来处理。
1.文件内容处理
在webpack的世界里,js是一等公民,是处理的入口,其他资源都是在js中通过类似require的方式引入。webpack虽然支持命令行操作,但是一般将配置写在webpack.conf.js文件中,文件内容是一个配置对象,基本配置项是:entry、ouput、module、plugins属性。
entry与output
这里引入了一个chunk的概念,chunk表示一个文件,默认情况下webpack的输入是一个入口文件,输出也是一个文件,这个文件就是一个chunk,chunkId就是产出时给每个文件一个唯一标识id,chunkhash就是文件内容的md5值,name就是在entry中指定的key值。
1
2
3
4
5
6
7
8
9
|
module.exports = { entry: {
collection: './src/main.js' // collection为chunk的名字,chunk的入口文件是main.js
},
output: {
path: './dist/js' ,
filename: '[name].[chunkhash].js' // 输出到dist/js目录下,以collection+chunk内容的md5值作为输出的文件名
}
}; |
输出:
module
moudle对应loader(加载器 )的配置,主要对指定类型的文件进行操作,举个例子:js类型的文件和css文件需要不同的loader来处理。最常用的加载器是eslint-loader和babel-loader。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
module.exports = { entry: {
collection: './src/main.js' // collection为chunk的名字,chunk的入口文件是main.js
},
output: {
path: './dist/js' ,
filename: '[name].[chunkhash].js' // 输出到dist/js目录下,以collection+chunk内容的md5值作为输出的文件名
}
module: {
rules: [ // rules为数组,保存每个加载器的配置
{ test: /.js$/, // test属性必须配置,值为正则表达式,用于匹配文件
loader: 'babel-loader?fakeoption=true!eslint-loader' , // loader属性必须配置,值为字符串,对于匹配的文件使用babel-loader和eslint-loader处理,处理顺序从右向左,先eslint-loader,后babel-loader,loader之间用!隔开,loader与options用?隔开
exclude: /node_module/, // 对于匹配的文件进行过滤,排除node_module目录下的文件
include: './src' // 指定匹配文件的范围
} ] }
}; |
其中,loader的options也可以单独使用options属性来配置
1
2
3
4
5
6
7
8
9
|
rules: [ {
test: /.js$/,
loader: 'babel-loader' ,
options: {
fakeoption: true
}
}
] |
另外通常babel-loader的配置项可以写在根目录下的.babelrc文件中
1
2
3
4
5
|
{ "presets" : [ "stage-2" ],
"plugins" : [ "transform-runtime" ]
} |
plugins
plugins用于扩展webpack的功能,相比着loader更加灵活,不用指定文件类型。常用的plugins有三个,html-webpack-plugin、commonChunkPlugin和ExtractTextPlugin。
1
2
3
4
5
6
7
8
9
10
11
|
var HtmlwebpackPlugin = require( 'html-webpack-plugin' );
module.exports = { ...
plugins: [
new HtmlwebpackPlugin({<br> filename: 'collection.html' , // 入口html文件名
template: './src/index.html' // 入口html文件模板
})
]
...
}; |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
module.exports = { ...
plugins: [
// 把通过npm包引用的第三方类库从入口文件中提取出来
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor' ,
minChunks: function (module, count) {
// 指定范围是js文件来自node_modules
return (module.resource && /.js$/.test(module.resource) &&module.resource.indexOf(path.join(__dirname, '../node_modules' )) === 0);
}
}),
// 把webpack的module管理相关基础代码从vendor中提取到manifest
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest' ,
chunks: [ 'vendor' ]
})
]
...
}; |
js是一等公民,webpack默认不产出css文件,产出css文件需要依赖ExtractTextPlugin插件来完成。
1
2
3
4
5
6
7
8
9
10
|
module.exports = { ...
plugins: [
// 把css片段从入口js文件中提取到对应入口名的css文件中
new ExtractTextPlugin({
filename: './dist/static/css/[name].[contenthash].css'
}),
]
...
}; |
2.文件间的关系处理
理清这个过程得倒推,先看一下经webpack处理后的js文件,下面的例子中主要涉及3个产出文件,manifest是webpack的module管理代码,vendor是第三方类库文件,collection是入口文件,加载的顺序是manifest-》vendor-》collection。
查看三个文件的内容可知:
vendor和collection的内容都是一个函数,类似jsonp请求回来的返回值。下面分别是vendor和collection中的代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
webpackJsonp([0],[ // chunkid为0
/* 0 */ /***/ ( function (module, exports, __webpack_require__) {
...
/***/ }),
/* 1 */ /***/ ( function (module, exports) {
...
/* 2 */ ...
/* 9 */ /***/ ( function (module, exports, __webpack_require__) {
...
/***/ }),
/* 10 */ , // 此处moduleid=10的模块为空
/* 11 */ /***/ ( function (module, exports) {
...
/***/ }),
...
]); |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
webpackJsonp([1],[ // chunkid为1
/* 0 */ , // moduleid为0-9的模块均为空
/* 1 */ ,
/* 2 */ ,
/* 3 */ ,
/* 4 */ ,
/* 5 */ ,
/* 6 */ ,
/* 7 */ ,
/* 8 */ ,
/* 9 */ ,
/* 10 */ /***/ ( function (module, __webpack_exports__, __webpack_require__) {
...
}; /***/ }),
/* 11 */ ,
/* 12 */ ,
....
/* 59 */ /***/ ( function (module, __webpack_exports__, __webpack_require__) {
"use strict" ;
Object.defineProperty(__webpack_exports__, "__esModule" , { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_vue__ = __webpack_require__(14);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_vue_validator__ = __webpack_require__(58);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_vue_validator___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_vue_validator__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__router__ = __webpack_require__(54);
...
/***/ }),
...
], [59]); // 此处多了一个参数,参数值为[59],即moduleid=59的模块名是入口模块
|
从以上两个文件可以发现出一个规律,
(1)每个文件的chunkid放在第一个参数;
(2)模块都放在第二个参数,每个模块都有对应的id,数组都是从moduleid=0开始,依次增加,如果该模块不在该文件中,则使用空值来代替;
(3)入口文件中的函数多了一个参数,参数里面传入了一个moduleid,视为入口模块。
接下来,我们看一下manifest文件的内容,来看看webpackJsonp函数究竟是怎么运行的。
总的来说是利用闭包传入了几个*变量:
modules:模块本身是一个函数,modules用于存储模块函数数组。
installedModules:用于缓存模块的返回值,即module.exports。
installedChunks:用于标记chunk文件是否已经被加载。
webpackJsonp:chunk文件加载后的callback函数,主要将文件中的模块存储到modules对象中,同时标记chunk文件的下载情况,对于入口chunk来说,等所有的模块都放入modules之后,执行入口模块函数。
__webpack_require__:模块加载函数,加载的策略是:根据moduleid读取,优先读取缓存installedModules,读取失败则读取modules,获取返回值,然后进行缓存。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
/******/ ( function (modules) { // webpackBootstrap
/******/ // install a JSONP callback for chunk loading
/******/ var parentJsonpFunction = window[ "webpackJsonp" ];
// webpackJsonp函数挂在window下,接收三个参数,chunkids:文件的id,moreModules: 文件中的module,executeModules:入口module
/******/ window[ "webpackJsonp" ] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
/******/ // 把moreModules中的module的放入modules中,缓存起来
/******/ // 利用传入的chunkid在installedChunks标记对应的文件已下载
/******/ var moduleId, chunkId, i = 0, resolves = [], result;
/******/ for (;i < chunkIds.length; i++) {
/******/ chunkId = chunkIds[i];
/******/ if (installedChunks[chunkId]) {
/******/ resolves.push(installedChunks[chunkId][0]);
/******/ }
/******/ installedChunks[chunkId] = 0;
/******/ }
/******/ for (moduleId in moreModules) {
/******/ if (Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
/******/ modules[moduleId] = moreModules[moduleId];
/******/ }
/******/ }
/******/ if (parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);
/******/ while (resolves.length) {
/******/ resolves.shift()();
/******/ }
// 存在入口模块,则加载对应的模块并执行
/******/ if (executeModules) {
/******/ for (i=0; i < executeModules.length; i++) {
/******/ result = __webpack_require__(__webpack_require__.s = executeModules[i]);
/******/ }
/******/ }
/******/ return result;
/******/ };
/******/ /******/ // 模块缓存对象,存放module的exports
/******/ var installedModules = {};
/******/ /******/ // chunk是否下载标记对象,key为chunkid,值为0表示已经下载
/******/ var installedChunks = {
/******/ 2: 0 // 表示chunkid=2的文件已下载,其实就是manifest文件本身
/******/ };
/******/ /******/ // 模块加载函数:先从缓存读取,没有则从modules中读取module函数,执行后返回exports,最后缓存起来
/******/ 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
/******/ 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;
/******/ }
/******/ /******/ // This file contains only the entry chunk.
/******/ // The chunk loading function for additional chunks
/******/ __webpack_require__.e = function requireEnsure(chunkId) {
...
/******/ };
/******/ /******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ /******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ /******/ // identity function for calling harmony imports with the correct context
/******/ __webpack_require__.i = function (value) { return value; };
/******/ /******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function (exports, name, getter) {
/******/ if (!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false ,
/******/ enumerable: true ,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/ /******/ // 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 = "./" ;
/******/ /******/ // on error function for async loading
/******/ __webpack_require__.oe = function (err) { console.error(err); throw err; };
/******/ })
/************************************************************************/ /******/ ([]);
//# sourceMappingURL=manifest.e7a81691a524d5b99b6b.js.map |
总体而言,下图可以简易的描述出webpack打包过程,该过程主要分为三个阶段:module构建、trunk构建和产出三个阶段。
打包工具的角色
所谓打包工具在web开发中主要解决的问题是:
(1)文件依赖管理。毕竟现在都是模块化开发,打包工具首先就是要梳理文件之间的依赖关系。
(2)资源加载管理。web本质就是html、js和css的文件组合,文件的加载顺序(先后时机)和文件的加载数量(合并、嵌入、拆分)也是打包工具重点要解决的问题。
(3)效率与优化管理。提高开发效率,即写最少的代码,做最好的效果展示;尽可能的使用工具,减少机械coding和优化页面效果,这个是考验打包工具是否具备魅力的点。
打包工具的结构
由上图可以推出,打包工具的结构应该是tool+plugins的结构。tool提供基础能力,即文件依赖管理和资源加载管理;在此基础上通过一系列的plugins来丰富打包工具的能力。plugins类似互联网+的概念,文件经plugins处理之后,具备了web渲染中的某种优势。
为什么使用webpack?
决定打包工具能走多远的是plugins的丰富程度,而webpack目前恰恰是最丰富的,我这里对比了一下fis与webpack在npm包上数据,看完就知道为什么要使用webpack了。
webpack的工作原理
webpack处理文件的过程可以分为两个维度:文件间的关系和文件的内容。文件间的关系处理,主要是通过文件和模块标记方法来实现;文件内容的处理主要通过loaders和plugins来处理。
1.文件内容处理
在webpack的世界里,js是一等公民,是处理的入口,其他资源都是在js中通过类似require的方式引入。webpack虽然支持命令行操作,但是一般将配置写在webpack.conf.js文件中,文件内容是一个配置对象,基本配置项是:entry、ouput、module、plugins属性。
entry与output
这里引入了一个chunk的概念,chunk表示一个文件,默认情况下webpack的输入是一个入口文件,输出也是一个文件,这个文件就是一个chunk,chunkId就是产出时给每个文件一个唯一标识id,chunkhash就是文件内容的md5值,name就是在entry中指定的key值。
1
2
3
4
5
6
7
8
9
|
module.exports = { entry: {
collection: './src/main.js' // collection为chunk的名字,chunk的入口文件是main.js
},
output: {
path: './dist/js' ,
filename: '[name].[chunkhash].js' // 输出到dist/js目录下,以collection+chunk内容的md5值作为输出的文件名
}
}; |
输出:
module
moudle对应loader(加载器 )的配置,主要对指定类型的文件进行操作,举个例子:js类型的文件和css文件需要不同的loader来处理。最常用的加载器是eslint-loader和babel-loader。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
module.exports = { entry: {
collection: './src/main.js' // collection为chunk的名字,chunk的入口文件是main.js
},
output: {
path: './dist/js' ,
filename: '[name].[chunkhash].js' // 输出到dist/js目录下,以collection+chunk内容的md5值作为输出的文件名
}
module: {
rules: [ // rules为数组,保存每个加载器的配置
{ test: /.js$/, // test属性必须配置,值为正则表达式,用于匹配文件
loader: 'babel-loader?fakeoption=true!eslint-loader' , // loader属性必须配置,值为字符串,对于匹配的文件使用babel-loader和eslint-loader处理,处理顺序从右向左,先eslint-loader,后babel-loader,loader之间用!隔开,loader与options用?隔开
exclude: /node_module/, // 对于匹配的文件进行过滤,排除node_module目录下的文件
include: './src' // 指定匹配文件的范围
} ] }
}; |
其中,loader的options也可以单独使用options属性来配置
1
2
3
4
5
6
7
8
9
|
rules: [ {
test: /.js$/,
loader: 'babel-loader' ,
options: {
fakeoption: true
}
}
] |
另外通常babel-loader的配置项可以写在根目录下的.babelrc文件中
1
2
3
4
5
|
{ "presets" : [ "stage-2" ],
"plugins" : [ "transform-runtime" ]
} |
plugins
plugins用于扩展webpack的功能,相比着loader更加灵活,不用指定文件类型。常用的plugins有三个,html-webpack-plugin、commonChunkPlugin和ExtractTextPlugin。
1
2
3
4
5
6
7
8
9
10
11
|
var HtmlwebpackPlugin = require( 'html-webpack-plugin' );
module.exports = { ...
plugins: [
new HtmlwebpackPlugin({<br> filename: 'collection.html' , // 入口html文件名
template: './src/index.html' // 入口html文件模板
})
]
...
}; |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
module.exports = { ...
plugins: [
// 把通过npm包引用的第三方类库从入口文件中提取出来
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor' ,
minChunks: function (module, count) {
// 指定范围是js文件来自node_modules
return (module.resource && /.js$/.test(module.resource) &&module.resource.indexOf(path.join(__dirname, '../node_modules' )) === 0);
}
}),
// 把webpack的module管理相关基础代码从vendor中提取到manifest
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest' ,
chunks: [ 'vendor' ]
})
]
...
}; |
js是一等公民,webpack默认不产出css文件,产出css文件需要依赖ExtractTextPlugin插件来完成。
1
2
3
4
5
6
7
8
9
10
|
module.exports = { ...
plugins: [
// 把css片段从入口js文件中提取到对应入口名的css文件中
new ExtractTextPlugin({
filename: './dist/static/css/[name].[contenthash].css'
}),
]
...
}; |
2.文件间的关系处理
理清这个过程得倒推,先看一下经webpack处理后的js文件,下面的例子中主要涉及3个产出文件,manifest是webpack的module管理代码,vendor是第三方类库文件,collection是入口文件,加载的顺序是manifest-》vendor-》collection。
查看三个文件的内容可知:
vendor和collection的内容都是一个函数,类似jsonp请求回来的返回值。下面分别是vendor和collection中的代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
webpackJsonp([0],[ // chunkid为0
/* 0 */ /***/ ( function (module, exports, __webpack_require__) {
...
/***/ }),
/* 1 */ /***/ ( function (module, exports) {
...
/* 2 */ ...
/* 9 */ /***/ ( function (module, exports, __webpack_require__) {
...
/***/ }),
/* 10 */ , // 此处moduleid=10的模块为空
/* 11 */ /***/ ( function (module, exports) {
...
/***/ }),
...
]); |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
webpackJsonp([1],[ // chunkid为1
/* 0 */ , // moduleid为0-9的模块均为空
/* 1 */ ,
/* 2 */ ,
/* 3 */ ,
/* 4 */ ,
/* 5 */ ,
/* 6 */ ,
/* 7 */ ,
/* 8 */ ,
/* 9 */ ,
/* 10 */ /***/ ( function (module, __webpack_exports__, __webpack_require__) {
...
}; /***/ }),
/* 11 */ ,
/* 12 */ ,
....
/* 59 */ /***/ ( function (module, __webpack_exports__, __webpack_require__) {
"use strict" ;
Object.defineProperty(__webpack_exports__, "__esModule" , { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_vue__ = __webpack_require__(14);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_vue_validator__ = __webpack_require__(58);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_vue_validator___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_vue_validator__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__router__ = __webpack_require__(54);
...
/***/ }),
...
], [59]); // 此处多了一个参数,参数值为[59],即moduleid=59的模块名是入口模块
|
从以上两个文件可以发现出一个规律,
(1)每个文件的chunkid放在第一个参数;
(2)模块都放在第二个参数,每个模块都有对应的id,数组都是从moduleid=0开始,依次增加,如果该模块不在该文件中,则使用空值来代替;
(3)入口文件中的函数多了一个参数,参数里面传入了一个moduleid,视为入口模块。
接下来,我们看一下manifest文件的内容,来看看webpackJsonp函数究竟是怎么运行的。
总的来说是利用闭包传入了几个*变量:
modules:模块本身是一个函数,modules用于存储模块函数数组。
installedModules:用于缓存模块的返回值,即module.exports。
installedChunks:用于标记chunk文件是否已经被加载。
webpackJsonp:chunk文件加载后的callback函数,主要将文件中的模块存储到modules对象中,同时标记chunk文件的下载情况,对于入口chunk来说,等所有的模块都放入modules之后,执行入口模块函数。
__webpack_require__:模块加载函数,加载的策略是:根据moduleid读取,优先读取缓存installedModules,读取失败则读取modules,获取返回值,然后进行缓存。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
/******/ ( function (modules) { // webpackBootstrap
/******/ // install a JSONP callback for chunk loading
/******/ var parentJsonpFunction = window[ "webpackJsonp" ];
// webpackJsonp函数挂在window下,接收三个参数,chunkids:文件的id,moreModules: 文件中的module,executeModules:入口module
/******/ window[ "webpackJsonp" ] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
/******/ // 把moreModules中的module的放入modules中,缓存起来
/******/ // 利用传入的chunkid在installedChunks标记对应的文件已下载
/******/ var moduleId, chunkId, i = 0, resolves = [], result;
/******/ for (;i < chunkIds.length; i++) {
/******/ chunkId = chunkIds[i];
/******/ if (installedChunks[chunkId]) {
/******/ resolves.push(installedChunks[chunkId][0]);
/******/ }
/******/ installedChunks[chunkId] = 0;
/******/ }
/******/ for (moduleId in moreModules) {
/******/ if (Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
/******/ modules[moduleId] = moreModules[moduleId];
/******/ }
/******/ }
/******/ if (parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);
/******/ while (resolves.length) {
/******/ resolves.shift()();
/******/ }
// 存在入口模块,则加载对应的模块并执行
/******/ if (executeModules) {
/******/ for (i=0; i < executeModules.length; i++) {
/******/ result = __webpack_require__(__webpack_require__.s = executeModules[i]);
/******/ }
/******/ }
/******/ return result;
/******/ };
/******/ /******/ // 模块缓存对象,存放module的exports
/******/ var installedModules = {};
/******/ /******/ // chunk是否下载标记对象,key为chunkid,值为0表示已经下载
/******/ var installedChunks = {
/******/ 2: 0 // 表示chunkid=2的文件已下载,其实就是manifest文件本身
/******/ };
/******/ /******/ // 模块加载函数:先从缓存读取,没有则从modules中读取module函数,执行后返回exports,最后缓存起来
/******/ 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
/******/ 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;
/******/ }
/******/ /******/ // This file contains only the entry chunk.
/******/ // The chunk loading function for additional chunks
/******/ __webpack_require__.e = function requireEnsure(chunkId) {
...
/******/ };
/******/ /******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ /******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ /******/ // identity function for calling harmony imports with the correct context
/******/ __webpack_require__.i = function (value) { return value; };
/******/ /******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function (exports, name, getter) {
/******/ if (!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false ,
/******/ enumerable: true ,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/ /******/ // 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 = "./" ;
/******/ /******/ // on error function for async loading
/******/ __webpack_require__.oe = function (err) { console.error(err); throw err; };
/******/ })
/************************************************************************/ /******/ ([]);
//# sourceMappingURL=manifest.e7a81691a524d5b99b6b.js.map |
总体而言,下图可以简易的描述出webpack打包过程,该过程主要分为三个阶段:module构建、trunk构建和产出三个阶段。