webpack-dev-server

诸如 LiveReloadBrowsersync 之类的工具允许在开发应用程序时刷新浏览器,并且在仅仅是 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:
hello-world,Demo,Output
如果你尝试修改代码,你应该会在终端里看到一些输出信息。浏览器也会根据变动做一些强制更新。

如果默认端口被占用了,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)并中断代码以在浏览器中查看提示信息:

webpack 错误提示, webpack-dev-server overlay 属性

如果你想要更全面的提示信息,请考虑 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 插件生态系统是非常丰富的,有很多插件可以满足我们一些特殊的开发需求:

输出相关的插件

还有一些插件会让 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。例如,代理允许您将其连接到其他服务器。

在下一章中,您将学习如何组合配置,以便可以在本书后面进一步开发。

用户头像
登录后发表评论