webpack-dev-server是利用express开启的dev服务器 。

基本使用

webpack v5 开启dev-server的方式是:

  1. {
  2. // ...
  3. devServer: {
  4. open: true, // 自动打开浏览器
  5. static: { // 以前的contentBase换成了static
  6. directory: path.join(__dirname, 'dist'),
  7. },
  8. compress: true, // gzip压缩
  9. port: 9000,
  10. },
  11. }

“static.directory ”就是把某个目录作为静态server的根目录。dev-server开启的时候,会自动打包,可能看不到打包输出,但是其实是打包并按照配置输出了。

配合HtmlWebpackPlugin

一般前端项目,js文件打包之后,最好指定html入口,所以配合插件HtmlWebpackPlugin:

  1. const HtmlWebpackPlugin = require("html-webpack-plugin")
  2. {
  3. //...
  4. plugins: [
  5. new HtmlWebpackPlugin({
  6. filename: 'index.html',
  7. template: path.join(__dirname, 'public', 'index.html')
  8. })
  9. ],
  10. }

这个插件的作用是生成一个index.html,其模版就是上面template指定的,然后输出到webpack配置的output里面。同时,生成的这个新的html中,自动将打包好的js文件插入为script标签。

请求代理proxy

dev-server常用的另一个功能就是proxy,将前端请求代理:

  1. {
  2. devServer : {
  3. // ...
  4. proxy: {
  5. '/api': {
  6. target: 'http://localhost:3000',
  7. // pathRewrite: { '^/api': '' },
  8. },
  9. },
  10. }
  11. }

配置好了以后,在开发过程中,前端中发起的请求将根据请求前缀,决定是否转发到target的地址中,这个转发是express做的,所以不会有跨域问题。

  1. fetch('/api/user').then(res => res.json()).then(data => {
  2. // do something
  3. })

比如上面这个请求,就会代理到:http://localhost:3000/api/user。
pathRewrite就是就是前缀的替换规则,比如开启pathRewrite后:pathRewrite: { ‘^/api’: ‘’ },把api替换成空字符串,那么上面的请求就会代理到:http://localhost:3000/user。

代理之后,如何debug代理请求的目标对不对呢,可以这样,利用bypass属性:

  1. {
  2. devServer : {
  3. // ...
  4. proxy: {
  5. '/api': {
  6. target: 'http://localhost:3000',
  7. // pathRewrite: { '^/api': '' },
  8. bypass: function (req, res, proxyOptions) {
  9. // req
  10. // res
  11. // 都是express的
  12. const urlPath = getRealUrl(req, proxyOptions)
  13. // 加一个自定义头
  14. res.setHeader('yxnne-real-url', urlPath)
  15. },
  16. },
  17. },
  18. },
  19. }
  20. }
  21. // 得到真实url
  22. function getRealUrl (req, proxyOptions) {
  23. const { pathRewrite, target } = proxyOptions
  24. let urlPath = req.path
  25. if (pathRewrite) {
  26. Object.keys(pathRewrite).forEach(key => {
  27. urlPath = urlPath.replace(new RegExp(key), pathRewrite[key])
  28. })
  29. urlPath = `${target.replace(/\/$/, '')}${urlPath}`
  30. } else {
  31. urlPath = target + req.path
  32. }
  33. return urlPath
  34. }

简单来讲,bypass就是代理的请求会走这个函数。
所以可以在里面拿到一些关心的信息,并设置在请求、返回头上,或者其他操作。