Skip to main content

实时编译及重新加载

一般每次修改代码以后,都需要手动 npm run build 进行编译打包后才可以看到实际打包后的内容,这个过程的频繁操作非常影响开发效率,所以我们希望可以做到当文件发生变化时,自动的完成编译和展示。

webpack 中有几个不同的选项,可以使代码发生变化后自动完成编译:

一、webpack watch mode

webpack 提供了 watch 模式,在该模式下,webpack 依赖图中的所有文件,只要有一个发生了更新,代码就会被重新编译,就不需要手动去运行 npm run build 指令了,启用该模式的方式如下:

1、配置文件中添加 watch

在 webpack 的配置文件中添加 watch: true

webpack.config.js
const path = require('path')

module.exports = {
// ...
watch: true,
entry: './index.js',
output: {
filename: 'bundle.js',
path: path.join(__dirname, '/')
},
// ...
}

2、设置 watch 运行命令

在启动命令中,添加 --watch 的标识:

package.json
{
// ...
"scripts": {
"watch": "webpack --watch"
},
// ...
}

二、webpack-dev-server

使用 watch 进行代码监听存在一些问题:

  • watch 只能对代码进行实时编译,无法开启本地服务来运行代码,做到实时重新加载(live reloading)
  • 编译成功后,会形成新的打包文件夹,也就是会频繁操作 file stystem,而实际上我们只要在项目全编写完再生产打包文件夹;
  • 使用 watch 进行代码编译时,会刷新整个页面,无法保留页面的一些状态;
  • watch 方式编译文件,会对整个源代码进行编译,无论是否发生改变。

以上问题可以使用 webpack-dev-server(WDR)来进行优化,webpack-dev-server 提供了一个简单的 web 服务器,能够实时重新加载(live reloading),启用方式如下:

1、安装 webpack-dev-server

npm install --save-dev webpack-dev-server

2、设置 start 运行命令

如果没有自定义 webpack-dev-server 的相关配置,可以直接执行 webpack serve, webpack 会自动调用 webpack-dev-server

package.json
{
// ...
"scripts": {
"watch": "webpack --watch",
"start": "webpack serve"
},
// ...
}

如果要自定义 webpack-dev-server 的相关配置,则启动命令中执行 webpack-dev-server

package.json
{
// ...
"scripts": {
"watch": "webpack --watch",
"start": "webpack serve"
"start": "webpack-dev-server"
},
// ...
}

webpack-dev-server 带有许多可配置的选项,可在 webpack.config.js 中进行任何的配置。

3、自定义配置项

webpack.config.js
const path = require('path')

module.exports = {
entry: './index.js',
output: {
filename: 'bundle.js',
path: path.join(__dirname, '/')
},
devServer: {
hot: true, // 启动模块热更新 HMR
open: true, // 开启自动打开浏览器页面
},
}

常见配置项如下:

devServer: {
contentBase: path.join(__dirname, 'static'), // 告诉服务器从哪里提供内容(默认当前工作目录)
openPage: 'views/index.html', // 指定默认启动浏览器时打开的页面
index: 'views/index.html', // 指定首页位置
watchContentBase: true, // contentBase 下文件变动将 reload 页面 (默认 false)
host: 'localhost', // 默认 localhost, 想外部可访问用 '0.0.0.0'
port: 8080, // 默认 8080
inline: true, // 可以监控 JS 变化
hot: true, // 模块热替换(热启动)
open: true, // 启动时自动打开浏览器(指定打开 chrome,open: 'Google Chrome')
compress: true, // 一切服务都启用 gzip 压缩
disableHostCheck: true, // true:不进行 host 检查
quiet: false,
https: false,
clientLogLevel: 'none',
stats: { // 设置控制台的提示信息
chunks: false,
children: false,
modules: false,
entrypoints: false, // 是否输出入口信息
warnings: false,
performance: false, // 是否输出 webpack 建议(如文件体积大小)
},
historyApiFallback: {
disableDotRule: true,
},
watchOptions: {
ignored: /node_modules/, // 略过 node_modules 目录
},
proxy: { // 接口代理(这段配置更推荐:写到 package.json,再引入到这里)
"/api-dev": {
"target": "http://api.test.xxx.com",
"secure": false,
"changeOrigin": true,
"pathRewrite": { // 将 url 上的某段重写(例如此处是将 api-dev 替换成了空)
"^/api-dev": ""
}
}
},
before(app) { },
}

点击查看更多 webpack-dev-server 配置项

使用 webpack-dev-server 打包代码时,不会生成对应的打包文件夹的,因为 webpack-dev-server 内部用了一个 memfs 库,可以将打包后的文件夹直接加载到内存中,而不需要频繁操作 file system,从而提升编译效率。

三、webpack-dev-middleware

webpack-dev-server 内部默认使用 express 来搭建本地服务器,开启本地服务,但有时需要自定义对应的配置,此时可以用 webpack-dev-middleware

webpack-dev-middleware 是一个封装器(wrapper),可以把 webpack 处理后的文件传递给服务器(server) ,webpack-dev-server 在内部使用了它。

同时 webpack-dev-middleware 也可以作为一个单独的包来使用,以便根据需求进行更多自定义设置。

下面是一个 webpack-dev-middleware 配合 express server 的示例:

1、安装 webpack-dev-middleware

这里以 express 为例,也可以使用其它工具,如 koa

npm install --save-dev express webpack-dev-middleware

2、创建 server.js 文件

在项目根目录下,新建 server.js

server.js
const express = require('express')
const webpack = require('webpack')
const webpackDevMiddleware = require('webpack-dev-middleware')

// 创建服务器对象
const app = express()

// 使用 webpack 函数加载配置文件,生成一个 webpack 编译器
const complier = webpack(require('./webpack.config.js'))

// webpack-dev-middleware 会将 complire 转换为一个中间件
const middleware = webpackDevMiddleware(complier)

// 使用中间件
app.use(middleware)

// 开启服务,此时就可以对该服务进行任何需要的定制
app.listen(3000, () => console.log('serve is running'))

3、运行

# 执行
node server.js