Webpack-00前置内容理解webpack

理解 Webpack 实现流程

理解node 模块化

src目录有 如下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
//name.js
let name = 'my name is xxx'
exports.name = name

// action.js
let action = 'make webpack'
exports.action = action

// index.js
let action = require('./action.js').action
let name = require('./name.js').name
let msg = `${name} is ${action}`
console.log(msg)
  • 如果你学过模块化,or用过 require.js
  • 意思是每个文件代表一个模块,当一个文件(index.js)需要另一个文件内容的时候(name.js) ,我们可以 require('./name.js')
  • require得到的东西,就是这个模块文件如name.js 里 exports对象
  • 可以通过 require 拿到一个模块里的东西,同时可以用 exports 把模块需要暴露出的东西 暴露出去
  • require/exports 就实现了模块化

    • 好处是:代码更加清晰,修改模块的时候更加的方便
  • 运行 node src/index.js 得到执行

怎么就能执行了?

  • 因为我们使用的是 node环境,而node环境内部天生支持模块化,使用的是 commonJS规范

如何支持浏览器?

  • 不可以直接引入 index.js ,因为浏览器没有 require/exports 这些东西
  • 你需要对源码进行处理
  • 使用“一些工具”对代码进行处理加工变成一个文件,放到dist里 浏览器引入 dist里的js
  • 这个工具就是 webpack

实现思路

  • 浏览器是不认识 require/exports 的

step01先套壳(此时代码是无法运行的)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// index.js
function (require, exports, module) {
let action = require('./action.js').action
let name = require('./name.js').name
let msg = `${name} is ${action}`
console.log(msg)
}

// action.js
function (require, exports, module) {
let action = 'make webpack'
exports.action = action
}

// name.js
function (require, exports, module) {
let name = 'my name is xxx'
exports.name = name
}

step02 模块有一个模块id,放入到一个对象里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
modules = {
// index.js
0: function (require, exports) {
let action = require('./action.js').action
let name = require('./name.js').name
let msg = `${name} is ${action}`
console.log(msg)
},
// action.js
1: function (require, exports) {
let action = 'make webpack'
exports.action = action
},
// name.js
2: function (require, exports) {
let name = 'my name is xxx'
exports.name = name
}
}

// 所有的模块归拢到一处
// 用一个 modules 收集
// 过程就是,我们又一个工具 比如叫做 webpack,把我们的代码变成如下内容,然后把每个modules挨个执行一下

// 执行模块返回结果
function exec(id) {
let fn = modules[id]
let exports = {}
fn(require, exports)

// 浏览器不是 node环境,所以没有 require,我们需要创造一个require
function require(path) {
// 根据模块的路径,返回执行的结果
}
}

// 模块0 是我们的入口文件
exec(0)
  • 浏览器不是node环境没有require
  • 浏览器不是node环境没有require
  • 浏览器不是node环境没有require
  • 所以webpack的作用是把模块化的js处理成一个文件如 bundle.js 在浏览器执行

COMMONJS规范写源码的时候

  • 必须用 require(‘xx.js’) 去加载一个模块
  • 就是去执行这个模块,拿到这个模块里的 exports 对象
  • 同时模块希望被别人用的时候,我们需要在 exports 绑定东西

step03改变modules的数据格式

  • 资源映射和启动入口
  • 代码可以在 “node环境/浏览器”执行
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
modules = {
// index.js
0: [
function (require, exports) {
let action = require('./action.js').action
let name = require('./name.js').name
let msg = `${name} is ${action}`
console.log(msg)
},
// 依赖的模块 路径和 id的映射
{
'./action.js': 1,
'./name.js': 2
}
],
// action.js
1: [
function (require, exports) {
let action = 'make webpack'
exports.action = action
},
{}
],
// name.js
2: [
function (require, exports) {
let name = 'my name is xxx'
exports.name = name
},
{}
]
}

// 所有的模块归拢到一处
// 用一个 modules 收集
// 过程就是,我们又一个工具 比如叫做 webpack,把我们的代码变成如下内容,然后把每个modules挨个执行一下

// 执行模块返回结果
function exec(id) {
/*
mapping 形如
{
'./action.js': 1,
'./name.js': 2
}
*/
let [fn, mapping] = modules[id]
let exports = {}
fn && fn(require, exports)

// 浏览器不是 node环境,所以没有 require,我们需要创造一个require
function require(path) {
// 根据模块的路径,返回执行的结果
return exec(mapping[path])
}
return exports
}

// 模块0 是我们的入口文件
exec(0)