终于彻底搞明白了,webpack-devServer使用、运行流程、实现原理、常用配置项

如果你想学到更多实用前端知识。
可以关注我的公众号:【前端驿站Lite】,一个不止分享前端的地方 ᕦ( •̀∀•́)ᕤ

阅读收获

阅读完本篇文章,你将会有以下收获:

  1. webpack-dev-middleware 是什么、如何进行工作的。
  2. webpack-dev-server 是什么、如何进行工作的、实现原理是什么。
  3. webpack-dev-server 常用配置项static、hot、proxy重点解读。
  4. webpack-dev-server 如何使用、其他常用配置项设置。

前言

我们使用webpack打包时,每次修改代码后,都需要重新打包,然后刷新浏览器才能看到效果,这样的开发体验是非常不友好的。

所以我们需要一个工具,能够实现代码修改后自动打包自动刷新浏览器,从而提高我们的开发效率。

这也就是我们本文章的主角 webpack-dev-server。

watch模式

开始之前,我们需要了解一下启动webpack的 watch 模式,watch 模式可以实现对文件的实时监听,监听到文件变化后,会重新编译打包,将产物输出到磁盘中。

# webpack 启动时增加 `watch`参数
npx webpack --watch

webpack-dev-middleware

学习webpack-dev-server之前,我们还需要了解一下webpack-dev-middleware是什么?

webpack-dev-middleware 是一个容器(wrapper),它会将 webpack 编译后的文件存储到内存中,然后在用户访问 express 服务时,将内存中对应的资源输出返回。

那webpack-dev-middleware如何进行工作的呢?

  1. webpack-dev-server会用webpack进行实时编译,再用webpack-dev-middleware 将webpack编译后文件会输出到内存中。可以将webpack-dev-middleware看作一个内存型的文件系统,目录与内存中的产物会形成映射关系。
  2. 当我们访问express服务时,express会将请求转发给webpack-dev-middleware,webpack-dev-middleware会根据映射关系,找到对应的文件,再将文件内容返回给express。

webpack-dev-server

我们了解了webpack-dev-middleware之后,就可以很轻松的理解webpack-dev-server了。

webpack-dev-server是 webpack 官方推出的一款开发工具,这款工具可以实现代码修改后自动编译自动打包自动刷新浏览器的功能。

webpack-dev-server 会将打包后的产物放入内存中,这样就大大提升了 构建速度访问速度,同时也不会有磁盘的 IO 开销,延长硬盘使用寿命。

因为前面我们已经对webpack-dev-middleware有了了解,所以我们可以很轻松的理解webpack-dev-server的工作原理了。

// webpack有以下配置
output: {
    filename: 'bundle.js',
},
  • 当我们使用webpack正常打包的时,会将产物生成到配置项output.path指定的目录下,比如我们指定的是dist目录,那么打包后的产物就会生成到dist目录下。
  • devServer也会将打包产物输出的一个类型output.path的目录下,所以我们可以通过 http://localhost:8080/bundle.js 来访问打包后的产物。

webpack-dev-server实现原理

有了前面的铺垫,我们就可以很轻松的理解webpack-dev-server的实现原理了。

webpack-dev-server的实现原理,实际就使用 webpack-dev-middleware 中间件来处理 webpack 的打包资源,并且和 express 服务器进行关联。

同时提供一个 socket 服务,将 webpack 编译打包的各个阶段的状态信息告知给客户端,通知网页调用reload接口刷新页面,从而实现实时重新加载(live reloading)和模块热替换(hot module replacement)功能。

webpack-dev-server配置项

在学习使用webpack-dev-server之前,我们需要讲解几个不好理解的配置项。

static

该配置项用来提供静态资源,默认为public目录。

假设我们的目录结构如下:

├── css
│   ├── a.css
├── assets
│   ├── b.jpg
├── src
│   └── index.js
├── package.json
└── webpack.config.js

1. 不指定publicPath (默认publicPath为/),此时我们可以直接访问静态资源,如下:

static: ['assets', 'css'],
    
// 或
static: {
    directory: path.join(__dirname, 'assets'),
},

// 或
static: [
    {
        directory: path.join(__dirname, 'assets'),
    },
    {
        directory: path.join(__dirname, 'css'),
    },
],

这样我们就可以在开发环境下,直接去访问我们配置的静态资源了,如下:

http://localhost:8080/b.jpg
http://localhost:8080/a.css

2. 我们也可以指定publicPath

static: [
    {
        directory: path.join(__dirname, 'css'),
        publicPath: '/css',
    },
    {
        directory: path.join(__dirname, 'assets'),
        publicPath: '/assets',
    },
],

此时,我们需要拼上publicPath才能访问到静态资源,如下:

http://localhost:8080/css/a.css
http://localhost:8080/assets/b.jpg

hot

配置hot为true,开启模块热替换功能。

什么是模块热替换呢?

官方解释,模块热替换(HMR - hot module replacement)功能会在应用程序运行过程中,替换、添加或删除 模块,而无需重新加载整个页面。

主要是通过以下几种方式,来显著加快开发速度:

  • 保留在完全重新加载页面期间丢失的应用程序状态。
  • 只更新变更内容,以节省宝贵的开发时间。
  • 在源代码中 CSS/JS 产生修改时,会立刻在浏览器中进行更新,这几乎相当于在浏览器 devtools 直接更改样式。

总之,它可以提升我们开发效率,如果不开启,我们每次修改代码,页面都会进行整体刷新,降低我们的开发效率。

proxy

我们项目开发中,经常会遇到跨域的问题,我们可以使用代理的方式来解决跨域问题。

客户端请求->同源服务端A,服务端A->请求服务端B,将响应数据,由服务端A响应给页面

proxy就是使用http-proxy-middleware这个http代理中间件, 在本地起一个代理服务器,将请求转发到目标服务器上,从而解决跨域问题。

proxy: {
  "/bili": { // 以 /bili 开头的请求,会转发到下面的 target 配置
    target: "https://api.bilibili.com", // 目标服务器
    pathRewrite: {"^/bili" : ""}, // 重写路径
    secure: false, // https接口,需要配置这个参数
  },
  '/api': {
    target: 'http://82.25.101.11:8000', 
    changeOrigin: true, // 将请求头中的host 配置为 target
  },
}

接下来,我们的请求就会变成这样:

  • /bili/user => https://api.bilibili.com/user
  • /api/user => http://82.25.101.11:8000/api/user

那为什么要更改请求头中的host呢?

大家都知道,一台服务器上可以部署多个项目,当我们发送请求时,DNS 会将域名解析为 IP 地址,此时,也就确定了我们目标服务器,那如何确定我们要访问的是哪个项目呢?这就需要用到 host 字段了。

请求头中Host用来指定请求的 域名/ip地址端口号,通常用于指定服务器的地址,端口号可以省略,省略时默认为80端口。

此时我们将host指定为a.com就会访问到淘宝服务了。
终于彻底搞明白了,webpack-devServer使用、运行流程、实现原理、常用配置项_第1张图片

所以如果一台服务器上部署多个项目时,我们需要更改请求头中的host,来指定我们要访问的项目。

一台服务器只有一个项目时,我们可以不用更改请求头中的host,因为DNS解析后,就确定了我们要访问的项目。

但为了以后用起来方便,就统一将这个配置项changeOrigin设置为true。

webpack-dev-server的使用

知其然,知其所以然,接下来,我们看一下webpack-dev-server如何使用吧。

1. 首先我们需要安装webpack-dev-server

npm install webpack-dev-server --save-dev

2.我们需要修改webpack.config.js配置文件,增加devServer配置项

module.exports = {
  // ...
  devServer: {
      // 将public设为静态资源目录
      static: {
          directory: path.join(__dirname, 'public'),
      },
      // 开启服务器时,浏览器自动打开页面,也可以配置为['/my-page']打开指定页面
      open: true,
      // 开启 gzip 压缩
      compress: true,
      // 自定义端口号,也可以设置为 auto
      port: 9000,
      // 客户端配置
      client: {
          // 当出现编译错误或警告时,在浏览器中显示全屏覆盖。
          overlay: {
              // 日志级别为errors时,浏览器中全屏显示错误信息
              errors: true,
              //  日志级别为warnings时,不去全屏覆盖,只在控制台中展示
              warnings: false,
          },
      },
      // 为所有响应添加 headers:
      headers: { 
          "X-Custom-Foo": "bar"
      },
      // 默认情况下dev-server使用http协议,通过配置可以支持https,
      https: true,
      // 注意:默认使用自签名证书,也可以配置自己的证书
      // https: {
      //     ca: './path/to/server.pem',
      //     pfx: './path/to/server.pfx',
      //     key: './path/to/server.key',
      //     cert: './path/to/server.crt',
      //     passphrase: 'webpack-dev-server',
      //     requestCert: true,
      // },
      // 开启热模块替换
      hot: true,
      // 配置代理
      proxy: {
          "/bili": { // 以 /bili 开头的请求,会转发到下面的 target 配置
              target: "https://api.bilibili.com", // 目标服务器
              pathRewrite: {"^/bili" : ""}, // 重写路径
              secure: false, // https接口,需要配置这个参数
          },
          '/api': {
              target: 'http://82.25.101.11:8000',
              changeOrigin: true, // 将请求头中的host 配置为 target
          },
      }
  }}

3. 在 package.json 中增加启动命令

{
  "scripts": {
    "start": "webpack serve"
  }
}

完结撒花,你又进步了一点点。

ᕦ( •̀∀•́)ᕤ

你可能感兴趣的:(webpack,前端)