webpack中path/publicPath/contentBase傻傻分不清楚

2022.10.01 更新: 时隔一年多在 webpack5 下的全新认知. 其实是忘得差不多重新学习了下 当然下面的知识并没有过时~
[[2022-09-30-study-webpack-day7#publicPath path contentBase in webpack5]]

path vs. publicPath vs. contentBase

output.path

绝对路径, 代表打包在本地磁盘上的物理位置.
比如:

1
2
3
4
5
output: {
filename: '[name].js',
path: path.resolve(__dirname, '../dist'),
publicPath: '/dev/'
}

这个配置项在生产环境下是必须的, 因为你总要指定打包生成的最终路径. 但是在开发模式下不是必须的, 因为webpackDevServer打包出来的文件都在内存中而没有打包到磁盘中.
path属性容易理解, 经常容易弄混的是publicPathcontentBase属性

output.publicPath

打包出来的资源的 URL 前缀(这里打包在生产模式和开发模式都很重要, 区别在于前者打包在硬盘, 后者打包在内存), 即在浏览器中访问的路径前缀,可以填写为相对路径和绝对路径:

  • 相对路径会被解析为相对 HTML 的路径
  • 绝对路径, 比如 CDN 路径

事实上在实际开发中会通过当前的环境设置publicPath为 CDN 路径还是普通绝对路径, 这个配置项会被加入每一个 runtime 或者 loader 产生的 URL 中, 所以这个配置项最好是以 / 结尾
示例图

devServer.publicPath

开启webpackDevServer时浏览器可以通过devServer.publicPath中设置的路径来访问bundled 被打包的文件, 通过访问http://localhost:8080/webpack-dev-server可以得到 devServer 启动后的打包资源访问路径, 点击资源可以看到打包资源的访问路径为http://localhost:8080${publicPath}main.js, 如图所示:

没有设置devServer.publicPath时, 默认值为output.publicPath, 和output.publicPath非常相似, 都是为浏览器指定访问路径的前缀, 一般来说开发环境下devServer.publicPath都需要和output.publicPath保持一致.举个反 🌰

  1. output.publicPath 设置了/mb/v5/
  2. devServer.publicPath 设置了/mb/v4
  3. 打包出来 js 文件为/mb/v5/js/vendor~12345678.js
  4. 实际上通过http://localhost:8080/webpack-dev-server查询访问的路径实际是/mb/v4/js/vendor~12345678.js
  5. 404 报错

总结来说, output.publicPath 指定路径(仅仅是对打包路径字符串进行修改), devServer.publicPath 则是对该路径设置了一个类似 express.static 的文件系统服务器, 服务器路径和设置路径对不上自然就无法访问了

devServer.contentBase

决定了 webpackDevServer 启动是服务器静态资源的根目录, 默认是项目根目录
这里的静态资源指图片, 字体等资源, 而不是指 bundled 被打包的资源, 在有静态资源的时候必填, contentBase不会影响pathpublicPath, 他唯一作用是指定服务器静态资源根目录来引用静态文件.
devServer.contentBasedevServer.publicPath的关系: contentBase是服务于静态资源文件的路径, publicPath是服务于打包出来的文件访问的路径, 两者互不影响。

htmlWebpackPlugin

htmlWebpackPlugin用于向 html 中插入打包好的 js 文件, 而这个路径是根据output.publicPath决定的.官网文档中有这么一句话:

If you’ve set a publicPath in your webpack config this will be reflected correctly in this assets hash.
It is recommended that devServer.publicPath is the same as output.publicPath.

所以就像他说的, 把output.publicPathdevServer.publicPath设置成一样吧。

参考资料


webpack中path/publicPath/contentBase傻傻分不清楚
https://mariana-yui.github.io/2021/06/25/2021-06-25-path-publicPath-contentBase/
作者
Mariana
发布于
2021年6月25日
许可协议