Webpack 自动刷新与代理配置实战:WDS、Nodemon 及底层原理解析
本文详解如何利用 webpack-dev-server 实现前端开发的自动刷新,解决手动编译与发布的繁琐流程。通过配置 Nodemon 监控配置文件变更,并结合代理功能转发 API 请求,提升开发效率。同时深入剖析 WDS 基于 Chokidar 和 SockJS 的底层通信机制,帮助开发者理解自动刷新的实现原理。
Webpack 自动刷新配置与代理实战
前端开发过程中,开发者需要频繁修改 JavaScript 代码和样式,并根据浏览器中的实时效果进行不断调整。此外,开发目录与本地发布目录通常不一致,每次修改后都需要执行发布操作。更复杂的是,部分页面效果无法通过直接双击 HTML 文件查看,往往需要在本地搭建 Nginx 站点进行观察,确认本地无误后再部署至测试环境。若依靠手工刷新浏览器、手动发布以及启动站点,将耗费大量精力。而这三项工作,Webpack 均能提供自动化支持。
webpack-dev-server
Webpack 通过 webpack-dev-server(简称 WDS)实现自动刷新功能。WDS 是一个运行在内存中的开发服务器,底层基于 Express 框架。启动后,它能够实时检测文件变更并自动重新编译代码。
WDS 安装与启动方式
1. 安装
npm install webpack-dev-server --save-dev
首先通过 npm 将其安装至开发目录。安装完成后,可在 node_modules/bin 目录下找到相关执行文件。
2. NPM 启动
接着修改 package.json 文件(基于上一节配置):
"scripts": {
"start": "webpack-dev-server --env development",
"build": "webpack --env production"
}
此时,即可通过 npm run start 或 npm start 命令启动服务。

启动后,控制台会显示 Project is running at http://localhost:8080。打开该页面即可访问。

这表明 WDS 已自动创建了一个站点。当我们修改 component.js 时,命令行中会出现编译日志,页面也会随之自动刷新。

3. 直接启动
官网介绍可以直接通过以下命令启动 WDS。
webpack-dev-server --env development
但可能会遇到提示 webpack-dev-server --env development 不是内部命令的错误。此类问题通常由环境变量配置引起,只需将开发环境的 bin 目录添加至系统环境变量即可。例如,若目录为 'E:\Html5\node_modules\.bin',则将其追加到环境变量路径中。
C:\Users\Administrator.9BBOFZPACSCXLG2\AppData\Roaming\npm;C:\Program Files (x86)\Microsoft VS Code\bin;E:\Html5\node_modules\.bin

4.8080端口占用
若默认的 8080 端口被占用,WDS 会自动切换至其他可用端口。例如,若已有 Nginx 占用了该端口。
server{
listen 8080;
location / {
root E:/Html5/build;
index index.html index.htm;
}
}
再次启动 WDS:

此时端口已切换至 8081。用户也可以手动指定端口:
devServer:{
//...
port: 9000
}
使用 Nodemon 监控配置文件
Nodemon 自动启动
WDS 仅监视开发文件,若 webpack.config.js 发生变更,并不会触发 WDS 的自动重启。因此,我们需要借助 Nodemon 来实现这一功能。
npm install nodemon --save-dev
首先在开发目录安装 Nodemon,然后修改 package.json:
"scripts": {
"start": "nodemon --watch webpack.config.js --exec \"webpack-dev-server --env development\"",
"build": "webpack --env production"
},
此举旨在让 Nodemon 监视 webpack.config.js,一旦文件发生变化,便自动启动 WDS。

这样,开发者即可专注于代码编写,无需手动干预启动流程。
WDS 代理配置与底层原理
代理
然而存在一个疑问:WDS 站点的替代性问题。由于我们自行部署的 Nginx 配置了部分 API 代理,若直接挂载在 WDS 默认站点上,将无法访问这些接口。换言之,是否可以为 WDS 配置刷新路径?如果文件改变,能否刷新指定地址,或者配置代理?既然 WDS 本身是一个 HTTP 服务器,理应具备代理功能。经搜索,果然找到相关示例:https://github.com/webpack/webpack-dev-server/tree/master/examples/proxy-advanced
module.exports = {
context: __dirname,
entry: "./app.js",
devServer: {
proxy: {
"/api": {
target: "http://jsonplaceholder.typicode.com/",
changeOrigin: true,
pathRewrite: {
"^/api": ""
},
bypass: function(req) {
if(req.url === "/api/nope") {
return "/bypass.html";
}
}
}
}
}
}
即将 api 这个字段替换成 http://jsonplaceholder.typicode.com/,并将其从原地址中删掉,这样就可以自己实现代理了。皆大欢喜!WDS 是通过 http-proxy-middleware 来实现代理。更多参考:http://webpack.github.io/docs/webpack-dev-server.html;https://github.com/chimurai/http-proxy-middleware#options
但是,这种刷新是如何实现的呢?因为页面上没有嵌入什么别的 js,去翻原码 web-dev-server/server.js 中有这么一段:
Server.prototype._watch = function(path) {
const watcher = chokidar.watch(path).on("change", function() {
this.sockWrite(this.sockets, "content-changed");
}.bind(this))
this.contentBaseWatchers.push(watcher);
}
用 chokidar 来监视文件变化,server的内部维护的有一个socket集合:
Server.prototype.sockWrite = function(sockets, type, data) {
sockets.forEach(function(sock) {
sock.write(JSON.stringify({
type: type,
data: data
}));
});
}
sock 是一个 sockjs 对象。https://github.com/sockjs/sockjs-client,从 http://localhost:8080/webpack-dev-server/ 页面来看,sockjs 是用来通信记录日志的。
var onSocketMsg = {
hot: function() {
hot = true;
log("info", "[WDS] Hot Module Replacement enabled.");
},
invalid: function() {
log("info", "[WDS] App updated. Recompiling...");
sendMsg("Invalid");
},
hash: function(hash) {
currentHash = hash;
},
...
}
我们在看 app.js,其中有一个 OnSocketMsg 对象。
var onSocketMsg = {
hot: function() {
hot = true;
log("info", "[WDS] Hot Module Replacement enabled.");
},
invalid: function() {
log("info", "[WDS] App updated. Recompiling...");
sendMsg("Invalid");
},
hash: function(hash) {
currentHash = hash;
},
"still-ok": function() {
log("info", "[WDS] Nothing changed.")
if(useWarningOverlay || useErrorOverlay) overlay.clear();
sendMsg("StillOk");
},
"log-level": function(level) {
logLevel = level;
},
"overlay": function(overlay) {
if(typeof document !== "undefined") {
if(typeof(overlay) === "boolean") {
useWarningOverlay = overlay;
useErrorOverlay = overlay;
} else if(overlay) {
useWarningOverlay = overlay.warnings;
useErrorOverlay = overlay.errors;
}
}
},
ok: function() {
sendMsg("Ok");
if(useWarningOverlay || useErrorOverlay) overlay.clear();
if(initial) return initial = false;
reloadApp();
},
"content-changed": function() {
log("info", "[WDS] Content base changed. Reloading...")
self.location.reload();
},
warnings: function(warnings) {
log("info", "[WDS] Warnings while compiling.");
var strippedWarnings = warnings.map(function(warning) {
return stripAnsi(warning);
});
sendMsg("Warnings", strippedWarnings);
for(var i = 0; i < strippedWarnings.length; i++)
console.warn(strippedWarnings[i]);
if(useWarningOverlay) overlay.showMessage(warnings);
if(initial) return initial = false;
reloadApp();
},
errors: function(errors) {
log("info", "[WDS] Errors while compiling. Reload prevented.");
var strippedErrors = errors.map(function(error) {
return stripAnsi(error);
});
sendMsg("Errors", strippedErrors);
for(var i = 0; i < strippedErrors.length; i++)
console.error(strippedErrors[i]);
if(useErrorOverlay) overlay.showMessage(errors);
},
close: function() {
log("error", "[WDS] Disconnected!");
sendMsg("Close");
}
};
ok 的时候触发一个 reloadApp
function reloadApp() {
if(hot) {
log("info", "[WDS] App hot update...");
var hotEmitter = __webpack_require__("./node_modules/webpack/hot/emitter.js");
hotEmitter.emit("webpackHotUpdate", currentHash);
if(typeof self !== "undefined") {
// broadcast update to window
self.postMessage("webpackHotUpdate" + currentHash, "*");
}
} else {
log("info", "[WDS] App updated. Reloading...");
self.location.reload();
}
}
也就是说 WDS 先检测文件是否变化,然后通过 sockjs 通知到客户端,这样就实现了刷新。之前 WebSocket 的第三方只用过 socket.io,看起来 sockjs 也蛮好用的。不必外带一个 js,在主 js 里面就可以写了。
小结:效率提高的一方面是将一些机械的重复性流程或动作自动化起来。WDS 和 nodemon 就是两个为你干活的小弟。
demo:webpack-ch2_jb51.rar
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
生产环境怎么自动移除JS的console.log语句?
2026-11-03 10:59:54
面试刷题必备:怎么利用在线JS沙箱高效验证算法
2026-11-03 09:11:28
使用 Vite 构建 Phaser.js 项目的配置与资源管理
2026-11-02 10:26:07
webpack 自动清理 dist 文件夹的两种实现方法
2026-10-31 14:14:29
Docker部署Jackett完整指南:CLI与Compose配置及索引器使用
2026-10-31 12:57:10
