背景

在我们的开发中,很多的代码会频繁的变动,如果每次改动都使用npm run build来打包的话,是一件效率很低的事情,而且这个服务,一般来说,打包的时候,才需要使用,因此需要一个本地服务的,可以快捷的看到打包后的内容

方案

webpack为这种情况,提供了观察者模式,在每次文件发生变动的时候,自动执行编译,就不用每次都npm run build来打包了

写法

watch 自动编译修改的文件

我们可以在scripts中,新加一条命令webpack --watch来启动观察者模式

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
//package.json
{
"dependencies": {
"babel-loader": "^8.0.6",
"copy-webpack-plugin": "^5.1.1",
"webpack": "^4.41.5",
"webpack-cli": "^3.3.10"
},
"name": "webpack_learn",
"version": "1.0.0",
"main": "index.js",
"devDependencies": {
"@babel/core": "^7.7.7",
"@babel/preset-env": "^7.7.7",
"babel-core": "^6.26.3",
"babel-preset-env": "^1.7.0"
},
"scripts": {
"build": "webpack",
+ "watch": "webpack --watch",
"dev": "webpack --mode development",
"product": "webpack --mode production",
"testParams": "webpack --mode production --env.production product --param1 1 --param2 2 --explane 这是一个说明",
"showColorAndProgress": "webpack --progress --colors",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"description": ""
}

然后在命令行中执行

1
npm run watch #也可以yarn watch

然后我们在浏览器中,打开刚才的文件,并且查看控制台,控制台中打印了大家好,我的名字是小明,然后我们修改一下/src/let.js,及index.html文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    //let.js
- let name = '小明';
+ let name = '小刚;
module.exports = name;


//index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
- <script src="./main.js" type="text/javascript" charset="utf-8"></script>
+ <script src="./bundle.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>

然后保存文件,然后在刚打开的浏览器里,刷新页面,然后控制台中,变成了大家好,我的名字是小刚。这样,每次修改就不用执行打包指令了

sourceMap 查找报错所在

开发中,最重要的一个环节,就是代码的调试,如果我们在写的代码中,出现了报错,希望很快的知道是哪里的报错,但是在webpack中,代码经过层层的模块打包,合并成了最后的一个js文件,里面的内容是编译后的内容,

我们尝试一下报错,将刚刚的get.js中,加一个报错信息。

1
2
3
4
5
    //get.js
module.exports = function(name){
console.log(name)
+ throw new Error('这里有个报错')
};
1
2
3
4
5
6
bundle.js:1 Uncaught Error: 这里有个报错
at e.exports (bundle.js:1)
at Object.<anonymous> (bundle.js:1)
at n (bundle.js:1)
at bundle.js:1
at bundle.js:1

报错信息指向了bundle.js打包后的文件,这显然不是我们想要的

这个时候,我们可以使用sourceMap来解决这个问题。

1
2
3
4
5
6
7
8
9
10
11
12
//webpack.config.js
module.exports = {
entry:{
...
},
output:{
...
},
+ devtool: 'inline-source-map',
module:{},
plugins:{}
}

然后重新执行

1
npm run watch

这样,控制台的报错就变成了

1
2
3
4
5
6
get.js:3 Uncaught Error: 这里有个报错
at e.exports (get.js:3)
at Object.<anonymous> (index.js:4)
at n (bootstrap:19)
at bootstrap:83
at bundle.js:1

指向了正确的位置,我们复原代码,进行下一步尝试

1
2
3
4
5
    //get.js
module.exports = function(name){
console.log(name)
- throw new Error('这里有个报错')
};

webpack-dev-server 自动刷新页面

前面讲述了观察者模式及报错位置查找,但是美中不足的是,我们每次需要手动刷新来观察变化,这种情况下,可以使用webpack中的的webpack-dev-server模块,来完成自动更新的行为

首先安装webpack-dev-server

1
npm install webpack-dev-server #或者yarn add webpack-dev-server

安装完毕后,修改一下webpack.config.js文件

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
    const path = require('path')
const CopyWebpackPlugin = require('copy-webpack-plugin')

module.exports = {
//配置函数接受两个参数env和argv
//env:环境对象
//Webpack-CLI 的命令行选项
entry: './src/index.js', //设置默认
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
devtool: 'inline-source-map',
+ devServer: {
+ contentBase: './dist'
+ },
module: {
rules: [{
//里面为匹配的规则
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}]
},
plugins: [
new CopyWebpackPlugin([
{
from: path.join(__dirname, '/staticFrom/'),
to: path.join(__dirname+'/dist/')
}
])
]
}

声明开发服务,并将 dist 目录下的文件,作为可访问文件,并且修改package.json中声明一条

1
2
3
4
5
6
7
    {
...,
"scripts":{
...,
+ "serve": "webpack-dev-server --open"
}
}

然后执行

1
npm run serve # 或者yarn serve

执行完毕后,浏览器自动打开了一个地址为localhost:8080的网页,打开控制台,可以看到我们刚刚写入的大家好,我的名字是小刚,然后我们继续把小刚,改回刚才的小明

1
2
3
4
    //let.js
- let name = '小刚;
+ let name = '小明';
module.exports = name;

然后保存,浏览器的控制台,自动的就变化成了大家好,我的名字是小明

这样就建立了一个开发用的服务器,且每次修改,都会重新编译。