經(jīng)過(guò)一番測(cè)試,終于猜出了這幾個(gè)字段合乎我測(cè)試結(jié)果的意義,暫時(shí)解決了它們給我?guī)?lái)的困惑,我打算先從 devServer.publicPath 這個(gè)字段說(shuō)起,這樣我覺得比較好講明白一點(diǎn)兒,然后再說(shuō) output.publicPath 這個(gè)牽扯部分稍微多一點(diǎn)的字段,最后以最簡(jiǎn)單的 output.path 收尾。
devServer.publicPath
我們知道 devServer 這個(gè)字段只在 development 環(huán)境下有效,所以涉及到此字段的都是在 development 模式下。根據(jù)官方文檔,這個(gè)字段的值是一個(gè)字符串,默認(rèn)值為 '/',它表示 devServer 這個(gè)服務(wù)器在以 contentBase 為根路徑的基礎(chǔ)上在 publicPath 這個(gè)路徑上對(duì)外提供開發(fā)過(guò)程中 webpack 構(gòu)建的文件,比如有一個(gè)文件名字是 vendor.dll.js,假定此時(shí) devServer 跑在 http://localhost:8080 上,若我們不設(shè)置 devServer.publicPath 字段,同時(shí)也不要設(shè)置 output.path 字段的值(至于為什么,稍后會(huì)說(shuō)到),那么我們?cè)L問(wèn) http://localhost:8080/vendor.dll.js 就可以訪問(wèn)到這個(gè) js 文件,如圖:

如果設(shè)置 devServer.publicPath 字段的值為 '/lalala/' 那么我們?cè)L問(wèn) http://localhost:8080/lalala/vendor.dll.js 就可以訪問(wèn)到該文件:

所以,這個(gè)字段的意義應(yīng)該明晰了,即決定外部能夠以什么樣的路徑訪問(wèn)到構(gòu)建的文件。
值得一提的是,devServer 構(gòu)建的文件是在內(nèi)存里的,而非你電腦的磁盤上,但是如果內(nèi)存中找不到想要的文件時(shí),devServer 會(huì)根據(jù)文件的路徑嘗試去電腦的磁盤上找,如果這樣還找不到才會(huì) 404。所以如果我們把 devServer.contentBase 設(shè)置成 production 環(huán)境的 build 的目錄時(shí),那么如果這個(gè)目錄上存在文件,這個(gè)文件就可以在 devServer 開啟時(shí)通過(guò)對(duì)應(yīng)的路徑去訪問(wèn)。比如我現(xiàn)在 build/static/media 下存在 timg.fbfdb0cd.1.jpeg 這樣一個(gè)文件,那么在我們把 devServer.contentBase 設(shè)置為 build 后,通過(guò) devServer 訪問(wèn) http://localhost:8080/static/media/timg.fbfdb0cd.1.jpeg 就可以得到該圖片:

是一只柴犬。當(dāng)然,通過(guò)一個(gè)服務(wù)器按照對(duì)應(yīng)路徑找到這只柴犬是必然的事情,這里突出的重點(diǎn)是,如果開發(fā)時(shí)在內(nèi)存和
contentBase 下真實(shí)的磁盤路徑中存在著同樣文件名的文件,那么 devServer 返回的是內(nèi)存的那個(gè)。
output.publicPath
這里也是一個(gè) publicPath,那么肯定會(huì)想,這與上面的 devServer.publicPath 有關(guān)系嗎?答案是:有。就像上面說(shuō)的 devServer 把 contentBase 下真實(shí)的磁盤里的文件當(dāng)做內(nèi)存中文件的備胎一樣,devServer 也把 output.publicPath 當(dāng)做 devServer.publicPath 的備胎。就是說(shuō),如果后者,沒有顯式設(shè)定值,那么 devServer 就會(huì)嘗試去讀取前者的值,如果前者顯式設(shè)定了值,那么就用前者的值,否則就用 devServer.publicPath 的 default 值,也就是 '/';這就是我上面說(shuō)的那會(huì)兒提到的在測(cè)試devServer.public的作用時(shí)不要給 output.publicPath 設(shè)值。那我們現(xiàn)在可以來(lái)看看只給 output.publicPath 設(shè)值而不給 devServer.publicPath 設(shè)值會(huì)發(fā)生什么,比如設(shè)定 output.publicPath: /kakaka/:

再看看同時(shí)給二者設(shè)定值會(huì)發(fā)生什么,比如設(shè)定
devServer.publicPath: /lalala/,output.publicPath: /kakaka/:
但是,這兩個(gè)值設(shè)置成不一樣會(huì)導(dǎo)致其他的問(wèn)題,如圖:

地址欄訪問(wèn)到的是 http://localhost:8080/lalala/index.html 但是這個(gè) html 里的 script 標(biāo)簽以及一些其他的資源的前綴都是 'kakaka',也就是說(shuō)是以 output.publicPath 為準(zhǔn)的,這就不得不提到 output.publicPath 的其他功能了:其實(shí)它不止是 devServer.publicPath 的備胎,更是其他的眾多 loader 和 plugin 的備胎或者參考標(biāo)準(zhǔn),比如 html-webpack-plugin 應(yīng)該就是倚仗 output.publicPath 為構(gòu)建的文件決定的滿足特定需求的前綴來(lái)生成最終的文件訪問(wèn)路徑給 inject 到對(duì)應(yīng)的 html 模板中的。至于 webpack 對(duì)這個(gè)前綴要求的規(guī)則,webpack 官網(wǎng)教程里「配置」那一欄的 output.publicPath 就列的比較詳細(xì)了。另外,這個(gè)字段的 default 值是一個(gè)空字符串 '',如果沒有特殊需求就設(shè)置 output.publicPath: '/' 好了。而且,如果可以的話,其他要用到這個(gè)字段的「東西」,最好不要把這個(gè)字段當(dāng)初備胎,而把他當(dāng)成唯一,這樣應(yīng)該會(huì)避免類似上面那樣把兩個(gè) publicPath 字段的值設(shè)置成不一致而導(dǎo)致的問(wèn)題。
總結(jié)
哎?是不是忘了什么?嗯,output.path 這個(gè)字段其實(shí)沒什么好說(shuō)的,它的意義應(yīng)該不用再贅述了,實(shí)際上它只在 production 配置下有效,如果你去試一下的話,你會(huì)發(fā)現(xiàn)在 development 配置下,無(wú)論你給把它配置成什么值(前提必須是一個(gè)合規(guī)的絕對(duì)地址),它都不會(huì)對(duì)你訪問(wèn)開發(fā)時(shí)構(gòu)建在內(nèi)存中的文件產(chǎn)生影響,所以 development 配置下,直接忽略就好了。另外,它的 default 值是 path.resolve(__dirname, './dist')。
總而言之, devServer.publicPath 的意義就是決定外部能以怎樣的路徑通過(guò) devServer來(lái)訪問(wèn)構(gòu)建在內(nèi)存中的文件,這個(gè)字段未顯式設(shè)定時(shí),則會(huì)去沿用 output.publicPath 字段的顯式值(如果有的話,否則就用自己的 default 值)。output.publicPath 的意義是用來(lái)為構(gòu)建的文件生成滿足特定需求的前綴,并將這個(gè)前綴提供給需要的 resolver、plugin 或者其他的配置字段。
上面就是關(guān)于這兩個(gè)讓人光看 webpack 官網(wǎng)教程不一定能搞清楚其意義和用法的字段的總結(jié),需要注意的是,這個(gè)總結(jié)不一定靠譜,因?yàn)樗⒉皇浅鲎苑喸创a(想翻過(guò),太多了,不知道從何看起)之后的理論證實(shí),只是在控制變量之后的再組合變量的多次測(cè)試猜想規(guī)律歸納而得。不過(guò),至少他目前能解決我自己的困惑,所以,希望也能幫到有類似困惑的你。