诸如 LiveReload 或 Browsersync 之类的工具允许在开发应用程序时刷新浏览器,并且在仅仅是 CSS 更改时避免刷新。我可以通过 browser-sync-webpack-plugin 在 Webpack 中使用 Browsersync ,但是 Webpack 的工具箱中有更多技巧来达到这一目标。
Webpack watch Mode 和 webpack-dev-server
迈向更好的开发环境的第一步是在其 watch 模式下使用 Webpack 。您可以通过传递 --watch
给 Webpack 来激活它。示例:npm run build -- --watch
。
启用后,监视模式会检测文件的更改并自动重新编译。webpack-dev-server(WDS)实现了一种 watch 模式,甚至不止于此。
WDS 是在内存中运行的开发服务器,这意味着打包内容不会写入文件而是存储在内存中。这一区别在调试代码和样式时非常重要。
默认情况下,WDS 会在您开发应用程序时自动在浏览器中刷新内容,因此您无需亲自执行此操作。但它也支持高级 Webpack 功能——热模块更换(HMR)。
HMR 允许在没有完全刷新的情况下修补浏览器状态,这使得它更像 React 这样的库,完全刷新会破坏应用程序状态。热模块更换附录将详细介绍该功能。
WDS 提供了一个界面,可以动态修补代码,但为了使其高效工作,您必须为客户端代码实现此接口。对 CSS 之类的东西来说这是微不足道的,因为它是无状态的,但 JavaScript 框架和库的话就要麻烦一些。
从 WDS 导出文件
出于性能考虑,默认情况下,WDS 是运行在内存中的,但有时我们还是要将文件发送到文件系统。如果要与其他文件服务器集成,则这变得至关重要。write-file-webpack-plugin 可以做到这一点。
开发环境里,一般使用 WDS。如果要部署应用程序的话,请考虑其他标准解决方案,例如 Apache 或 Nginx。
WDS 入门
要开始使用 WDS,请先安装它:
npm install webpack-dev-server --save-dev
和以前一样,安装成功后会在在 npm bin
目录下面生成一个命令,你可以从那里运行 webpack-dev-server。运行 WDS 后,就可以在 http://localhost:8080
访问开发服务器了。现在,自动浏览器刷新已经到位,尽管目前还比较基础。
将 WDS 添加到项目中
为了将 WDS 集成到项目中,我们定义一个 npm script 来启动它。按照 npm 的约定,将其称为 start ,如下所示:
package.json
"scripts": {
"start": "webpack-dev-server --mode development",
"build": "webpack --mode production"
},
WDS 的配置方式是和 Webpack 是一致的
如果你在终端里面执行 npm run start
或者 npm start
,就会看到如下信息:
> webpack-dev-server --mode development
ℹ 「wds」: Project is running at http://localhost:8080/
ℹ 「wds」: webpack output is served from /
ℹ 「wdm」: Hash: eb06816060088d633767
Version: webpack 4.1.1
Time: 608ms
Built at: 3/16/2018 3:44:04 PM
Asset Size Chunks Chunk Names
main.js 338 KiB main [emitted] [big] main
index.html 181 bytes [emitted]
Entrypoint main [big] = main.js
...,
服务器已经运行起来了,在浏览器中打开 http://localhost:8080/ ,你就会看到熟悉的 Hello World:
如果你尝试修改代码,你应该会在终端里看到一些输出信息。浏览器也会根据变动做一些强制更新。
如果默认端口被占用了,WDS 会尝试使用其他的端口。终端输出会告诉你最终运行的位置。你可以使用
netstat -na | grep 8080
来查看 8080 端口的使用情况。
除了 development 和 production 两种模式以外,还有第三种模式:none。它会禁止所有的内容,比较类似于 Webpack 4 之前版本的行为。
通过 Webpack 配置 WDS
可以通过 Webpack 配置中的 devServer
字段自定义 WDS 功能。您也可以通过 CLI 设置大多数这些选项,但通过 Webpack 管理它们是一种不错的方法。
配置方法,如下所示:
webpack.config.js
...
module.exports = {
devServer: {
// 仅显示错误级别的输出,从而减少输出信息
stats: "errors-only",
// 从环境变量中传入 host 和 port,从而达到可配置
//
// 如果你使用 Docker, Vagrant 或者 Cloud9, 那么把
// host 设置为 "0.0.0.0";
//
// 0.0.0.0 对于所有的网络设备都是可用的
// 而默认的 `localhost` 不行.
host: process.env.HOST, // 默认为 `localhost`
port: process.env.PORT, // 默认为 8080
open: true, // 在浏览器中打开
},
...
};
完成此更改后,您可以通过环境变量配置服务器主机和端口。(例如:PORT=3000 npm start
)
dotenv 允许您通过 .env 文件定义环境变量,这样您就可以快速方便地设置主机地址和端口了。
如果您的网页应用使用基于 HTML5 历史记录 API 的路由,你可以启用
devServer.historyApiFallback
。
启用错误提示
WDS 提供了 overlay 属性,开启后可以捕获与编译相关的错误和警告:
webpack.config.js
module.exports = {
devServer: {
...
overlay: true,
},
...
};
立即运行服务器(npm start
)并中断代码以在浏览器中查看提示信息:
如果你想要更全面的提示信息,请考虑 error-overlay-webpack-plugin,因为它更好地显示了错误的起源。
WDS overlay 并没有捕捉到应用程序的运行时错误,它只是捕捉编译时错误。
启用热模块更换(HMR)
热模块更换是让 Webpack 与众不同的一个功能亮点。要实现它,需要在服务器端和客户端上做许多额外的工作。热模块更换附录将更详细地讨论这个话题。如果要将 HMR 集成到项目中,可以看看这个附录。但是,完成本教程并不需要它。
通过网络访问开发服务器
我们可以通过环境变量来设置主机地址和端口(例如:在 Unix 中使用 export PORT=3000
,在 Windows 中使用 set PORT=3000
)。但是,在大多数平台上,默认的设置已经足够了。
为了访问你的服务器,你必须要知道服务器的 IP 地址,在 Unix 机器上,可以通过 ifconfig | grep inet
来获取,Windows 上可以通过 ipconfig
获取。另外,有一个叫做 node-ip 的 npm 包也能够很方便的获取到 IP 地址。Windows 上更为特殊,你要将 HOST 环境变量设置为你的服务器 IP 地址,这样服务才可以被访问。
更快捷地配置 Webpack
当打包文件发生变化时,开发服务器会自动重启;但是,当 Webpack 配置变化了呢?如果说,每次配置变动你就要手动重启开发服务器,没过一会儿,你就会厌烦不堪了。如 GitHub 中所讨论的那样,我们可以使用 nodemon 监视工具自动执行该过程。
要使其工作,您必须先安装它(npm install nodemon --save-dev
)。之后,您可以让它观察 Webpack 配置,并在更改时重启 WDS。以下是运行脚本,您可以参照着试一试:
package.json
"scripts": {
"start": "nodemon --watch webpack.config.js --exec \"webpack-dev-server --mode development\"",
"build": "webpack --mode production"
},
WDS 可能会在未来支持此功能。但是现在,我们可以通过上述方法来实现。
轮询而不是监测文件
有时,WDS 提供的文件监测设置将无法在您的系统上运行。在旧版本的Windows,Ubuntu,Vagrant 和 Docker上可能会出现问题。启用轮询是一个很好的选择:
webpack.config.js
const path = require("path");
const webpack = require("webpack");
module.exports = {
devServer: {
watchOptions: {
// 首次更改后延迟多少时间再重新构建
aggregateTimeout: 300,
// 轮询的时间间隔 (单位 ms, 接受 Boolean 类型的值)
poll: 1000,
},
},
plugins: [
// 忽略 node_modules 目录,节省 CPU 资源
new webpack.WatchIgnorePlugin([
path.join(__dirname, "node_modules")
]),
],
};
动手做一些自己需要的设置比默认配置要耗费一些时间,但还是值得尝试的。
webpack-dev-server 的其他使用方式
你可以在终端传入一些 WDS 的设置选项,但是通过 Webpack 的配置文件来管理这些选项,会使得 package.json
文件更加整洁小巧。查看配置文档,你也可以清晰地知道当前正在发生的事情。
另外,您还可以使用 Express
服务器和一些中间件来使用 webpack-dev-server,有以下几种选择:
如果你希望有更多的灵活性,那么你可以使用 Node API。
CLI 和 Node API 会有些许的不同。
webpack-dev-server 的其他功能
WDS 还提供了许多其他功能,有几项您需要注意一下:
devServer.contentBase
- 假设您没有动态生成 index.html 并且希望自己在特定目录中维护它,则需要将 WDS 指向它。contentBase
接受路径(例如"build"
)或路径数组(例如["build", "images"]
)。该值默认为项目根目录。devServer.proxy
- 如果您使用多台服务器,则必须为 WDS 设置代理。代理设置接受代理映射的对象(例如,{ "/api": "http://localhost:3000/api" }
),通过代理,我们将匹配的查询解析到相应的服务器。默认情况下禁用代理设置。devServer.headers
- 在此处为您的请求附加自定义头部。
更多选项请参考官方文档。
开发时使用到的插件
webpack 插件生态系统是非常丰富的,有很多插件可以满足我们一些特殊的开发需求:
- case-sensitive-paths-webpack-plugin - 当你在不区分大小写的环境(如 macOS 或 Windows)下开发,但生产部署是用像 Linux 这样的区分大小写的环境时,这个插件会非常的方便。
- npm-install-webpack-plugin - 当您在项目里导入新的包时,这个插件会自动为您安装这个包,并在 package.json 中保存依赖。
- react-dev-utils - 包含为 Create React App 开发的 Webpack 实用程序。尽管它的名字含有 React,但它的用途不限于 React。如果您只想要格式化 Webpack 消息,请考虑 webpack-format-messages。
- start-server-webpack-plugin - 能够在 Webpack 构建完成后启动您的服务器。
输出相关的插件
还有一些插件会让 Webpack 的输出信息更容易阅读和理解:
- system-bell-webpack-plugin - 失败时响铃,而不是让 Webpack 无声地失败。
- webpack-notifier - 使用系统通知来通知您 Webpack 状态。
- nyan-progress-webpack-plugin - 可用于在构建过程中获得更整洁的输出。如果您使用像 Travis 这样的持续集成(CI)系统,请小心,因为它们可能破坏输出结果。Webpack 提供的
ProgressPlugin
也可以达到同样的效果。 - friendly-errors-webpack-plugin - 改进了 Webpack 的错误报告。它捕获常见错误并以更友好的方式显示它们。
- webpack-dashboard - 在标准 Webpack 输出上提供了一个完整的基于终端的仪表板。如果你喜欢清晰的视觉输出,这个就派上用场了。
总结
WDS 补充了 Webpack,并通过提供面向开发的功能使其对开发人员更友好。
回顾一下:
- Webpack 的
watch
模式是迈向更好的开发体验的第一步。在你编辑源代码时可以使 Webpack 自动打包。 - WDS 可以在更改时刷新浏览器,它还实现了热模块替换。
- 默认 WDS 设置在特定系统上可能存在问题。因此,资源密集型轮询是另一种选择。
- 可以使用中间件将 WDS 集成到现有节点服务器中,这样做比依赖命令行界面更容易控制。
- WDS 远不止刷新和 HMR。例如,代理允许您将其连接到其他服务器。
在下一章中,您将学习如何组合配置,以便可以在本书后面进一步开发。