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

294 阅读4分钟

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

1. 图解 contentBase

下面我们再来画图理解一下 devServer.contentBase

图解 devServer.contentBase 1_没有配置 contentBase 时.png
图解 devServer.contentBase 1_没有配置 contentBase 时
图解 devServer.contentBase 2_配置了 contentBase 后.png
图解 devServer.contentBase 2_配置了 contentBase 后
图解 devServer.contentBase 3_使用了 CopyWebpackPlugin 时.png
图解 devServer.contentBase 3_使用了 CopyWebpackPlugin 时
图解 devServer.contentBase 4_将使用 CopyWebpackPlugin 替换为使用 contentBase.png
图解 devServer.contentBase 4_将使用 CopyWebpackPlugin 替换为使用 contentBase

比如我们现在有一些源代码,如果直接运行在浏览器上,其中有些内容可能是浏览器识别不了的(比如说 .vue 文件)。所以我们的源代码需要进行打包,那么我们是通过 devServer 来打包,打包之后,devServer 会将所有的静态资源放到内存中(memfs),之后会开启一个 express 服务器,然后,浏览器就可以通过默认的 localhost:8080 地址去访问这个服务器,将对应的资源下载下来。而事实上,在从服务器上下载资源时,第一次只会下载下来一个文件,即 index.html 文件。我们知道,在 index.html 中会引入很多其它的资源(比如通过 <link> 引入 CSS 资源,通过 <img src="..."> 引入图片资源,通过 <script> 引入的 JS 资源(这些 JS 资源里面可能又引入了其它的资源)等等),那么这些资源都会在解析 index.html 文件时从 express 服务器中加载下来。那么我们再来看我们之前举的例子,我们在 index.html 中有一个 <script> 标签,它引用了 ./abc.js 这个资源,那么,浏览器到时候就会向服务器请求这个资源,但是服务器发现在刚才打包之后的资源中没有 abc.js,所以浏览器请求不到这个资源,这种情况下,浏览器可能会报一个错误或者就是不加载这个资源了。但是,我们还是希望浏览器最终能加载到这个 abc.js 资源,这个时候,我们就可以通过配置 devServer.contentBase 来实现了。这个 contentBase 对应的通常是一个文件夹,当浏览器从 express 服务器中打包之后的资源里面请求不到某个资源时,就会让 express 服务器从这个文件夹中尝试读取这个想请求的资源,读取到服务器的 memfs 中,然后再让服务器把这一资源返回给浏览器。所以,之前我们浏览器控制台中成功打印出了 abc.js 中的内容(abc呀~),说明成功加载到了 abc.js 资源,但其实它不是从打包之后的资源中加载到的,而是从我们配置的 contentBase 对应的目录(./abc)下加载到的。

此外,在对 favicon.ico 图标文件进行加载时,原来的方式是通过配置 CopyWebpackPlugin 插件将 favicon.ico 文件复制到了打包之后的资源中,所以之后浏览器中是可以正常加载这个 favicon.ico 文件的。后来,我们去掉了 CopyWebpackPlugin 的配置,也就意味着后续打包不会有将 favicon.ico 文件复制到打包之后的资源中的操作了,所以打包之后的资源中就没有这个文件了,之后浏览器中再进行请求就请求不到这个文件了。这时,我们就可以把 contentBase 设置为 ./pulbic,这意味着,当从 express 服务器中请求不到相应的资源时,就会来到这个 public 文件夹中进行请求,而因为 public 文件夹中有我们要请求的 favicon.ico 资源,所以请求成功,浏览器最终就能成功加载这个 favicon.ico 文件。

你可能会问,所以开发中就不再需要使用 CopyWebpackPlugin 了吗?其实,如果是在开发阶段,我们可以不使用 CopyWebpackPlugin,因为每次在打包时,CopyWebpackPlugin 都会对文件做拷贝操作,这可能会对 webpack 编译的过程造成一定的性能问题(比如有很多的音视频资源时,资源大小可能就比较大),但如果不使用 CopyWebpackPlugin,原本想要加载的某些资源就加载不到了,那么这时就可以配置 devServer.contentBase 了。但在部署阶段,我们是要把(npm run build)打包之后的资源部署到服务器上的,那么,打包之后的资源中应该是要包含所需的所有资源的,这时,我们就需要使用 CopyWebpackPlugin 帮助我们把有关资源(一般是 public 文件夹中的内容)拷贝到这个打包之后的静态资源文件夹中了。

所以,我们一般会这样做:开发阶段用 devServer.contentBase,生产阶段(真正打包部署时)用 CopyWebpackPlugin

以上,就是对 contentBase 的图解过程,其实就是资源的加载过程(到底从哪里去寻找对应的资源)。