你真的知道publicPath的用處嗎?無論是官方文檔,還是水友的解釋都很難讓豁然開朗,比如:
對(duì)于按需加載(on-demand-load)或加載外部資源(external resources)(如圖片、文件等)來說,output.publicPath 是很重要的選項(xiàng)。如果指定了一個(gè)錯(cuò)誤的值,則在加載這些資源時(shí)會(huì)收到 404 錯(cuò)誤。
此選項(xiàng)指定在瀏覽器中所引用的「此輸出目錄對(duì)應(yīng)的公開 URL」。相對(duì) URL(relative URL) 會(huì)被相對(duì)于 HTML 頁面(或 <base> 標(biāo)簽)解析。相對(duì)于服務(wù)的 URL(Server-relative URL),相對(duì)于協(xié)議的 URL(protocol-relative URL) 或絕對(duì) URL(absolute URL) 也可是可能用到的,或者有時(shí)必須用到,例如:當(dāng)將資源托管到 CDN 時(shí)。
實(shí)驗(yàn)是檢驗(yàn)用法的最好途徑,于是設(shè)置目錄結(jié)構(gòu)如下:
src
|---index.html
|---index.js
|---asssets
????|----1.jpg
- index.html使用<script src="./dist/bundle.js"/>的方式引入打包后的腳本。
- index.js使用require('./assets/1.jpg')的方式引入了圖片
- webpack.config.js的配置如下:
entry:"./index.js",
output:{
filename:"bundle.js",
path:path.resolve(__dirname,"dist"),
},
devServer:{
},
目的是將腳本打包到一個(gè)統(tǒng)一的dist文件夾下。
使用webpack-dev-server重新打包并打開index.html時(shí),報(bào)錯(cuò)如下:
http://localhost:8080/dist/bundle.js net::ERR_ABORTED
為什么找不到呢?
- webpack-dev-server使用的是內(nèi)存中的打包文件,并不是webpack命令打包后的路徑。(上面我沒有使用webpack命令打包哦。)
- webpack-dev-server在不設(shè)置publicPath的情況下,將默認(rèn)輸出bundle.js到根目錄。不信,你輸入localhost:8080/bundle.js就能看到這個(gè)Js。
- 報(bào)錯(cuò)是因?yàn)?,輸出的bundle.js在根目錄,而html卻要去加載dist目錄下的,所以找不到(上文:index.html使用<script src="./dist/bundle.js"/>的方式引入打包后的腳本)。
這時(shí)你需要在devServer中添加publicPath屬性:
publicPath: "/dist/"
重新使用webpack-dev-server打包,并打開index.html你會(huì)發(fā)現(xiàn),找到了bundle.js。但是仍舊提示找不到圖片
http://localhost:8080/c3bbc15b8d6be7ec744c8a32670d7f6c.png 404 (Not Found)
所以,此時(shí)devServer.pulicPath屬性的含義可以這么理解:
- 將你的打包文件輸出到哪個(gè)路徑下,該路徑是在內(nèi)存里(你看不到但存在),相對(duì)于加載bundle.js的index.html頁面或web服務(wù)根目錄的哪個(gè)路徑下。(本示例就相對(duì)web服務(wù)根目錄,因?yàn)槭且?/"開頭)
- 此時(shí)webpack.config.js中,output.path是可以刪除的。因?yàn)檫@個(gè)路徑是輸出到硬盤上的物理路徑。與webpack-dev-server完全無關(guān)。
可為什么找不到圖片呢?先回味一下官方原文
對(duì)于按需加載(on-demand-load)或加載外部資源(external resources)(如圖片、文件等)來說,output.publicPath 是很重要的選項(xiàng)。如果指定了一個(gè)錯(cuò)誤的值,則在加載這些資源時(shí)會(huì)收到 404 錯(cuò)誤。
也就是說:如果你require了一些資源或直接引用了網(wǎng)絡(luò)上的資源,這些資源里包含uri屬性(如css中設(shè)置img:url('./1.jpg')),就要使用就這個(gè)屬性,否則會(huì)找不到文件。(如果沒有使用uri資源,那么這個(gè)屬性沒什么用)。
說人話---這個(gè)屬性就是讓webpack在打包時(shí)才能根據(jù)配置動(dòng)態(tài)修改uri中的相對(duì)值的;你不配置,webpack打包后的bundle.js中引用的url不對(duì)。
于是再去配置output下的publicPath,將其修改為
output:{
filename:"bundle.js",
path:path.resolve(__dirname,"dist"),
publicPath: "/dist/"
},
重新執(zhí)行webpack-dev-server,打開index.html發(fā)現(xiàn)一切正常!
后來嘗試,不配置webserver.publicPath,而只配置output中的publicPath且修改為:
publicPath: "/dist/"
重新執(zhí)行webpack-dev-server,打開index.html發(fā)現(xiàn)一切正常!
難道我對(duì)webserver.publicPath的理解有錯(cuò)?
比較了加與不加時(shí),控制臺(tái)打印出的日志才明白:
- 當(dāng)你不配置devServer下的publicPath時(shí),其會(huì)默認(rèn)將包打到output.publicPath的路徑下。
- 當(dāng)你配置了devServer下的publicPath時(shí),才其會(huì)將包打開你指定的路徑下。
個(gè)人理解:
- output.path:硬盤上的路徑,也就是你打算把文件打包到你的哪個(gè)目錄,也就是各個(gè)牛人說的絕對(duì)路徑!與發(fā)布時(shí)的路徑完全無關(guān)。
- output.publicPath:主要用來轉(zhuǎn)換url中的相對(duì)路徑的。如果你引用到包含url的資源,一定要配置output.publicPath。配置了此項(xiàng),webpack在打包時(shí)才能根據(jù)配置動(dòng)態(tài)修改uri中的相對(duì)值。
- devserver.publicPath:可以理解為服務(wù)或模塊的發(fā)布路徑!注意:該值后面都要有"/"!本示例的index.html用了dist目錄下的bundle.js,所以我們需要將模塊發(fā)布到dist目錄下就正確了。
4.output.path對(duì)應(yīng)的是硬盤上路徑,output.publicPath對(duì)應(yīng)的是你這打好的包將來放在web服務(wù)器上后,使用www.xxx.xx/xxx/xx形式訪問時(shí)對(duì)應(yīng)的url.本示例中因?yàn)槲乙玫氖怯蛎?dist目錄中的js。所以其對(duì)應(yīng)的publicPath就應(yīng)該為/dist/ - 如果你使用webstorm,千萬不要在webpack打包后,使用其自帶的端口為63342的默認(rèn)web服務(wù)器打開index.html。這個(gè)默認(rèn)的web服務(wù)器會(huì)以你的工程目錄為根目錄,而不像webpack-dev-server是以配置文件所在目錄為根目錄。