在研究webpack打包的时候,一直对于publicPath有比较大的迷惑。今天就来记录一下我解惑的过程。
首先,webpack-dev-server也可以打包,它用于在开发环境中打包文件,并将打包后的文件运行在本地服务器上(localhost.xx.com:8080),在生产环境下打包时,用webpack打包,打包之后的文件运行在线上服务器上(test.xx.com)。
webpack-dev-server里面的publicPath就是指定本地服务器下的某一个路径,而output中的publicPath是指定线上服务器下的某一个路径。这是它们本质的区别。
接下来,我们来仔细讨论一下:
1)output里面的publicPath作用是什么?
output: {
filename: "bundle.[hash].js",
path: path.resolve(__dirname, "dist")
publicPath: "/assets/",
},
复制代码
output中的publicPath一般情况下我们是用不到的,只有在生产环境中需要用到,在上线的时候需要给项目中的静态资源统一配置资源前缀,代表客户端访问的上线资源地址。
publicPath意思就是公共路径,它是为整个项目的静态资源提供一个基础的路径,静态资源包括:js css img等,打包之后静态资源的保存路径不再是根路径,而是在根目录下新建一个assets文件夹,用于存放我们项目下的打包资源。
打开html可以看到source下:
我们可以看到,script中引入的js文件有assets前缀,当浏览器在找到html文件的时候,会去加载html文件中的其他静态资源文件(js img css),会按照设置的文件路径去寻找。
2)devServer中的publicPath作用是什么?
修改webpack.config.js如下:
devServer: {
// 根目录下dist为基本目录
contentBase: path.join(__dirname, "dist"),
// 自动压缩代码
compress: true,
// 服务端口为1208
port: 1208,
// 自动打开浏览器
open: true,
host: "dev.jd.com",
publicPath: "/assets/",
},
复制代码
重新打包并npm start,这个时候我们看到dev.jd.com:1208/
页面是空白的,没有任何内容,当我们加入后缀访问dev.jd.com:1208/assets/
时,就可以看到页面的内容了。这表明server将打包后的文件存放在assets文件夹下了。
这个在source中也可以看到,如下图:
3)为什么官网生命这两个publicPath最好保持一致?
我们先将它们两个改成不一样的看会发生啥?
output: {
filename: "bundle.[hash].js",
path: path.resolve(__dirname, "dist"),
publicPath: "/test/",
},
devServer: {
// 根目录下dist为基本目录
contentBase: path.join(__dirname, "dist"),
// 自动压缩代码
compress: true,
// 服务端口为1208
port: 1208,
// 自动打开浏览器
open: true,
host: "dev.jd.com",
publicPath: "/assets/",
},
复制代码
重新打包并运行:
观察上图,访问dev.jd.com:1208/assets/
时,可以找到该html文件,但是html文件中js文件404报错,这其实就可以说明问题,devserver是本地存放打包代码的地方,它想模拟访问线上的资源地址,但是静态资源存放的地址和它存放的地址不一致,所以就会出现资源访问不到的情况。
摘抄一段话,很简洁的说明了这句话:
如果webpack-dev-server的publicPath和output.publicPath不一致,在使用html-webpack-plugin可能会导致引用静态资源失败,因为在devServer中仍然以output.publicPath引用静态资源,和webpack-dev-server的提供的资源访问路径不一致,从而无法正常访问。
所以,官网才会让我们将两者保持一致。