Vue 项目之 Webpack 中 DevServer 的配置(3)

1,280 阅读6分钟

「这是我参与11月更文挑战的第26天,活动详情查看:2021最后一次更文挑战

1. webpack-dev-server 的基本使用

上一小节我们讲了 webpackwatch 模式,你可能会觉得“哇~这个的话好舒服”,其实,我们还有更舒服的方式😁,即使用 webpack-dev-server 的方式,这也是我们开发中最常用的方式(其实,在 webpack3 及之前的版本中,我们会从这个 webpack-dev-server 开始启动 webpack,而现在有了 webpack-cli,我们就可以不从 webpack-dev-server 开始启动了。但都需要单独安装 webpack-dev-server)。

watch 模式确实可以监听文件的变化,但它并没有自动帮助我们刷新浏览器的功能,目前自动刷新浏览器页面是 VS Code 中的扩展 Live Server 帮助我们实现的功能,而不是使用的 webpack 自带的功能。如果我们希望在不使用 Live Server 这一扩展的情况下,实现 **live reloading(实时重新加载)**的功能(就是自动刷新浏览器页面),就可以通过 webpackwebpack-dev-server 实现。webpack-dev-server 可以给我们提供对应的开发时服务器,我们可以利用这个服务器开启一个本地服务,这样一来,我们就可以不使用 Live Server 了。下面,我们先来安装它(因为这个东西还是只在开发时使用的,所以我们使用 -D 标志):

npm install webpack-dev-server -D

安装完成后,我们

在真实的 Vue 或者 React 项目开发中,我们一般会有两个脚本:

  • npm run build:对当前项目中的代码进行打包;
  • npm run serve 或者 npm run dev:用来开启一个本地服务,让我们进行本地的开发;

当前,在我们的项目中,package.json 文件中只设置了 npm run build 脚本,用来直接对当前的项目做打包。现在,我们再来添加一个脚本:

image-20211126212932050

然后,我们运行 npm run serve 命令,就相当于执行了 npx webpack serve 命令,它会找到 devServer,来帮助我们启动一个本地服务器:

image-20211126213633385

这里,webpack-cli 提示我们不需要将 serve 命令和 { watch: true } 配置一起使用,这没有意义。那么我们用了 webpack-dev-server 之后,就不需要再配置 watch: true 了,因为 serve 命令内部会帮我们监听文件的变化,当文件发生变化时,就会重新对当前项目的源代码进行编译。所以我们把 webpack.config.js 中的 watch 配置注释掉:

image-20211126214312796

再来运行 npm run serve 命令:

image-20211126214522784

这次,就没有刚才的提示了,而且,你会发现 webpack-dev-server 有打印出有关信息,告诉我们项目已经运行在了 http://localhost:8080/ 这个地址上,也就是说,webpack-dev-server 已经帮我们开启了本地服务。之后,编译源代码也成功了,成功之后就意味着我们现在可以访问这个 http://localhost:8080/ 地址了,我们可以直接在命令行终端中按住 Ctrl 键的同时点击这个地址在浏览器中打开它:

image-20211126215538266

可以看到,我们现在访问的是 localhost:8080,这个东西就不是 Live Server 帮助我们开启的,而是当前 devServer 自动给我们搭建的一个本地服务器(它其实是基于 Node.jsexpress 框架搭建的本地服务器,我们现在访问 localhost:8080 这个地址时就会来到这个服务器中,找到我们刚才打包的那些静态资源,然后返回给浏览器,浏览器就能对这些静态资源做一个展示了)。

以上,就是 webpack-dev-server 最基本的使用方式。

下面要讲的是关于 webpack-dev-server 的一些细节:

  1. 当前,我们没有对 webpack-dev-server 做任何配置,只是在脚本中添加了 serve 命令,到时候 webpack-dev-server 就会自动启动。那为什么它会自动启动呢?其实,webpack serve 这一脚本在执行时还是会通过 webpack-cli 进行解析,然后发现有 serve 这一参数时,就会利用 webpack-dev-server 来帮助我们启动一个本地服务了。

  2. 如果我们启用了 webpack-dev-server,那么它是不会对 src 目录下的源代码进行打包之后生成目标代码文件的(这里即不会生成 build 文件夹,或者原来存在的 build 文件夹会被清空内容)。你可能会有疑问:没有输出打包之后的文件的话,我们待会访问的静态资源从哪来啊?其实,webpack-dev-server 也是有对源代码进行编译和打包的,只不过它没有对编译打包后的代码做文件的输出(没有将代码写入文件),而是直接将编译打包后的代码放到了内存中,之后再通过 express 服务器去访问这些放到了内存中的代码(静态资源)。这时如果浏览器需要访问,就是直接从内存中读取对应的静态资源,然后再返回到浏览器中的。那它为什么不进行输出呢?做一个输出不是更干脆吗?因为是这样的,假如我们现在打包完之后先把代码输出到文件中,那么如果这时用户来访问了,就得先等 express 服务器从文件中把对应的资源读取到内存中,再从内存中读取到浏览器中(即先从文件系统中读取到内存中,再从内存中读取后转化成对应的数据流返回给浏览器)。因此,webpack-dev-server 为了提高我们的开发效率,它会直接把打包之后的静态资源放到了内存里面,这样就少了一个从文件读取到内存的过程,这样提供服务的服务器的效率会更高一点,浏览器在访问时访问得也会更快一点。

    事实上,webpack-dev-server 使用了一个叫 memfs 的库(相当于是一个内存的文件系统),通过它把打包之后的静态资源直接放到了内存(内存的文件系统)中。

    image-20211126224752999

    memfsgithub 地址:github.com/streamich/m…

    而在早期,webpack 使用的不是这个 memfs 库,而是自己的一个库:memory-fs,当然,现在这个库已经很久没更新了,并且已经被弃用了:

    image-20211126225142588

    总结一下就是:webpack-dev-server 在编译之后不会写入到任何输出文件中,而是将打包后的文件保留在内存中(通过使用 memfs 库实现的)。