# 五.webpack-dev-server

前言

webpack-dev-server (opens new window) 是 webpack 官方提供的一个工具,可以基于当前的 webpack 构建配置快速启动一个静态服务。当 mode 为 development 时,会具备 hot reload 的功能,即当源码文件变化时,会即时更新当前页面,以便你看到最新的效果。

# 1.使用案例

  • 安装依赖

    npm install webpack-dev-server --save-dev
    
    1
  • package.json 配置

    "scripts": {
      "start": "webpack-dev-server --mode development"
    }
    
    1
    2
    3
  • 启动

    npm run start #默认使用 8080 端口,直接访问 http://localhost:8080/
    
    1

# 2.详细配置

  • public 字段用于指定静态服务的域名,默认是 http://localhost:8080/ ,当你使用 Nginx 来做反向代理时,应该就需要使用该配置来指定 Nginx 配置使用的服务域名。

  • port 字段用于指定静态服务的端口,如上,默认是 8080,通常情况下都不需要改动。

  • publicPath 字段用于指定构建好的静态文件在浏览器中用什么路径去访问,默认是 /,例如,对于一个构建好的文件 bundle.js,完整的访问路径是 http://localhost:8080/bundle.js,如果你配置了 - publicPath: 'assets/',那么上述 bundle.js 的完整访问路径就是 http://localhost:8080/assets/bundle.js。可以使用整个 URL 来作为 publicPath 的值,如 publicPath: 'http://localhost:8080/assets/'如果你使用了 HMR,那么要设置 publicPath 就必须使用完整的 URL

    建议将 devServer.publicPathoutput.publicPath 的值保持一致。

  • proxy:开发时跨域使用

    将特定 URL 的请求代理到另外一台服务器上,从而实现跨域。

    proxy: {
      '/api': {
        target: "http://localhost:3000", // 将 URL 中带有 /api 的请求代理到本地的 3000 端口的服务上
        pathRewrite: { '^/api': '' }, // 把 URL 中 path 部分的 `api` 移除掉
      },
    }
    
    1
    2
    3
    4
    5
    6

    webpack-dev-server 的 proxy 功能是使用 http-proxy-middleware (opens new window) 来实现的,如果需要更详细的 proxy 配置,可以参考官方文档 http-proxy-middleware (opens new window)

  • contentBase

    用于配置提供额外静态文件内容的目录,之前提到的 publicPath 是配置构建好的结果以什么样的路径去访问,而 contentBase 是配置额外的静态文件内容的访问路径,即那些不经过 webpack 构建,但是需要在 webpack-dev-server 中提供访问的静态资源(如部分图片等)

    // 使用当前目录下的 public
    contentBase: path.join(__dirname, "public")
    // 也可以使用数组提供多个路径
    contentBase: [path.join(__dirname, "public"), path.join(__dirname, "assets")]
    
    1
    2
    3
    4

    publicPath 的优先级高于 contentBase

  • beforeafter

    配置用于在 webpack-dev-server 定义额外的中间件,如

    before(app){
      app.get('/some/path', function(req, res) { // 当访问 /some/path 路径时,返回自定义的 json 数据
        res.json({ custom: 'response' })
      })
    }
    
    1
    2
    3
    4
    5

    before 在 webpack-dev-server 静态资源中间件处理之前,可以用于拦截部分请求返回特定内容,或者实现简单的数据 mock。

    after 在 webpack-dev-server 静态资源中间件处理之后,比较少用到,可以用于打印日志或者做一些额外处理。

# 3.webpack-dev-middleware

npm install webpack-dev-middleware --save-dev
1

Node.js 服务的脚本文件 app.js

const webpack = require("webpack")
const middleware = require("webpack-dev-middleware")
const webpackOptions = require("./webpack.config.js") // webpack 配置文件的路径
webpackOptions.mode = "development" // 本地的开发环境默认就是使用 development mode
const compiler = webpack(webpackOptions)
const express = require("express")
const app = express()

app.use(
  middleware(compiler, {
    // webpack-dev-middleware 的配置选项
  })
)
// 其他 Web 服务中间件
// app.use(...)
app.listen(3000, () => console.log("Example app listening on port 3000!"))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

然后用 Node.js 运行该文件即可:

node app.js # 使用刚才创建的 app.js 文件
1

使用 webpack-dev-server 的好处是相对简单,直接安装依赖后执行命令即可,而使用 webpack-dev-middleware 的好处是可以在既有的 Express 代码基础上快速添加 webpack-dev-server 的功能,同时利用 Express 来根据需要添加更多的功能,如 mock 服务、代理 API 请求等。

# 4.mock 服务

webpack-dev-server 的 beforeproxy 配置,又或者是 webpack-dev-middleware 结合 Express,都可以帮助我们来实现简单的 mock 服务。

module.export = function mock(app) {
  app.get("/some/path", (req, res) => {
    res.json({ data: "" })
  })
  // ... 其他的请求 mock
  // 如果 mock 代码过多,可以将其拆分成多个代码文件,然后 require 进来
}
1
2
3
4
5
6
7

然后应用到配置中的 before 字段:

const mock = require('./mock')
// ...
before(app) {
  mock(app) // 调用 mock 函数
}
1
2
3
4
5