devServer配置详解

534 阅读3分钟

1、基本用法

// vue.config.js
devServer: {
  proxy: {
    '/api': {
      target: 'http://localhost:81',
    }
  }
}

// vue/src/api/index.js
import http from './httpInstance'
const prefix = process.env.NODE_ENV === 'development' ? '/api' : '/api'
const getList = data => {
  return http({
    method: 'post',
    url: prefix + '/getList',
    data
  })
}

现在,请求到 /api/xxx 现在会被代理到请求http://localhost:81/api/xxx,例如 /api/getList现在会被代理到请求 http://localhost:81/api/getList。

2、忽略API前缀 如果不希望传递/api,则需要重写路径:

devServer: {
  proxy: {
    '/api': {
      target: 'http://localhost:81',
      pathRewrite: { '^/api': '' },
    }
  }
}

现在,请求到 /api/xxx 现在会被代理到请求 http://localhost:81/xxx, 例如 /api/getList 现在会被代理到请求 http://localhost:81/getList

3、代理多个路径 如果想将多个特定路径代理到同一目标,则可以使用一个或多个带有context属性的对象的数组:

devServer: {
  proxy: [{
    context: ['/auth', '/api'],
    target: 'http://localhost:81',
  }]
}

4、忽略https安全提示 默认情况下,不接受运行在https上,且使用了无效证书的后端服务器。如果你想要接受,只要设置 secure: false 就行。修改配置如下:

devServer: {
  proxy: {
    '/api': {
      target: 'http://localhost:81',
      secure: false,
    }
  }
}

5、解决跨域原理 默认情况下,代理时会保留主机头的来源,可以将changeOrigin设置为true以覆盖此行为:

devServer: {
  proxy: {
    '/api': {
      target: 'http://localhost:81',
      changeOrigin: true,
    }
  }
}

6、自定义规则 有时如果不想代理所有的请求。可以基于一个函数的返回值绕过代理。 在函数中可以访问请求体、响应体和代理选项。必须返回 false 或路径,来跳过代理请求。 例如:对于浏览器请求,你想要提供一个 HTML 页面,但是对于 API 请求则保持代理。你可以这样做:

devServer: {
  proxy: {
    '/api': {
      target: 'http://localhost:81',
      bypass: function (req, res, proxyOptions) {
        if (req.headers.accept.indexOf('html') !== -1) {
          return '/index.html';
        }
      },
    }
  }
}

7、更多参数

target:"xxx",            // 要使用url模块解析的url字符串
forward:"xxx",           // 要使用url模块解析的url字符串
agent:{},                // 要传递给http(s).request的对象
ssl:{},                  // 要传递给https.createServer()的对象
ws:true/false,           // 是否代理websockets
xfwd:true/false,         // 添加x-forward标头
secure:true/false,       // 是否验证SSL Certs
toProxy:true/false,      // 传递绝对URL作为路径(对代理代理很有用)
prependPath:true/false,  // 默认值:true 指定是否要将目标的路径添加到代理路径
ignorePath:true/false,   // 默认值:false 指定是否要忽略传入请求的代理路径
localAddress:"xxx",      // 要为传出连接绑定的本地接口字符串
changeOrigin:true/false, // 默认值:false 将主机标头的原点更改为目标URL

webpack配置hot是否需要配置HotModuleReplacementPlugin

webpack官方文档(devserverhot)中介绍,使用hmr的时候,需要满足两个条件:

配置devServer.hot为true

配置webpack.HotModuleReplacementPlugin插件

Note that webpack.HotModuleReplacementPlugin is required to fully enable HMR. If webpack or webpack-dev-server are launched with the --hot option, this plugin will be added automatically, so you may not need to add this to your webpack.config.js*.

请注意:webpack要完全启用HMR需要使用webpack.HotModuleReplacementPlugin。如果webpack或webpack-dev-server 通过命令行添加 --hot 选项启动,这个插件会自动添加,所以您不需要将它添加到webpack.config.js

但是,经实际使用 webpack-dev-server 时发现,在webpack.config.js中仅仅配置了devServer.hot:true,而未添加这个插件的状态下,仍然实现了HMR。

原来 webpack-dev-server 内部自动帮我们完成了这个事情。

通过在Github 的 webpack-dev-server 搜索,找到以下代码(源码地址):

if (options.hot || options.hotOnly) {
  config.plugins = config.plugins || [];
  if (
    !config.plugins.find(
      // Check for the name rather than the constructor reference in case
      // there are multiple copies of webpack installed
      (plugin) => plugin.constructor.name === 'HotModuleReplacementPlugin'
    )
  ) {
    config.plugins.push(new webpack.HotModuleReplacementPlugin());
  }
}

代码判断了配置的插件中是否包含名为HotModuleReplacementPlugin的插件,如果没有则添加。

再查看搜索结果中的Commits:fix: check for name of HotModuleReplacementPlugin to avoid RangeError

这段代码还被调整过,调整前判断的依据是constructor,调整后用name判断。

至此,我们确定,webpack-dev-sever内部对HotModuleReplacementPlugin插件做了判断,当配置了devServer.hot:true时,就自动添加这个插件。

但是webpack源码中未搜到类似操作,所以使用其他工具启用服务器并开启HMR时,应该仍需手动添加这个插件。