Webpack中publicPath詳解

最近本身在搭建一個基於webpack的react項目,遇到關於output.publicPath和webpack-dev-server中publicPath的問題,而官方文檔對它們的描述也不是很清楚,因此本身研究了下並寫下本文記錄。javascript

output

output選項指定webpack輸出的位置,其中比較重要的也是常常用到的有pathpublicPathcss

output.path

  • 默認值:process.cwd()

output.path只是指示輸出的目錄,對應一個絕對路徑,例如在項目中一般會作以下配置:html

output: {
	path: path.resolve(__dirname, '../dist'),
}
複製代碼

output.publicPath

  • 默認值:空字符串

官方文檔中對publicPath的解釋java

webpack 提供一個很是有用的配置,該配置能幫助你爲項目中的全部資源指定一個基礎路徑,它被稱爲公共路徑(publicPath)。node

而關於如何應用該路徑並無說清楚...react

其實這裏說的全部資源的基礎路徑是指項目中引用css,js,img等資源時候的一個基礎路徑,這個基礎路徑要配合具體資源中指定的路徑使用,因此其實打包後資源的訪問路徑能夠用以下公式表示:webpack

靜態資源最終訪問路徑 = output.publicPath + 資源loader或插件等配置路徑
複製代碼

例如git

output.publicPath = '/dist/'

// image
options: {
 	name: 'img/[name].[ext]?[hash]'
}

// 最終圖片的訪問路徑爲
output.publicPath + 'img/[name].[ext]?[hash]' = '/dist/img/[name].[ext]?[hash]'

// js output.filename
output: {
	filename: '[name].js'
}
// 最終js的訪問路徑爲
output.publicPath + '[name].js' = '/dist/[name].js'

// extract-text-webpack-plugin css
new ExtractTextPlugin({
	filename: 'style.[chunkhash].css'
})
// 最終css的訪問路徑爲
output.publicPath + 'style.[chunkhash].css' = '/dist/style.[chunkhash].css'
複製代碼

這個最終靜態資源訪問路徑在使用html-webpack-plugin打包後獲得的html中能夠看到。因此publicPath設置成相對路徑後,相對路徑是相對於build以後的index.html的,例如,若是設置publicPath: './dist/',則打包後js的引用路徑爲./dist/main.js,可是這裏有一個問題,相對路徑在訪問本地時能夠,可是若是將靜態資源託管到CDN上則訪問路徑顯然不能使用相對路徑,可是若是將publicPath設置成/,則打包後訪問路徑爲localhost:8080/dist/main.js,本地沒法訪問github

因此這裏須要在上線時候手動更改publicPath,感受不是很方便,可是不知道該如何解決...web

通常狀況下publicPath應該以'/'結尾,而其餘loader或插件的配置不要以'/'開頭

webpack-dev-server中的publicPath

點擊查看官方文檔中關於devServer.publicPath的介紹

在開發階段,咱們借用devServer啓動一個開發服務器進行開發,這裏也會配置一個publicPath,這裏的publicPath路徑下的打包文件能夠在瀏覽器中訪問。而靜態資源仍然使用output.publicPath

webpack-dev-server打包的內容是放在內存中的,這些打包後的資源對外的的根目錄就是publicPath,換句話說,這裏咱們設置的是打包後資源存放的位置

例如:

// 假設devServer的publicPath爲
const publicPath = '/dist/'
// 則啓動devServer後index.html的位置爲
const htmlPath = `${pablicPath}index.html`
// 包的位置
cosnt mainJsPath = `${pablicPath}main.js`
複製代碼

以上能夠直接經過http://lcoalhost:8080/dist/main.js訪問到。

經過訪問 http://localhost:8080/webpack-dev-server 能夠獲得devServer啓動後的資源訪問路徑,如圖所示,點擊靜態資源能夠看到靜態資源的訪問路徑爲 http://localhost:8080${publicPath}index.html

圖1-1

html-webpack-plugin

這個插件用於將css和js添加到html模版中,其中templatefilename會受到路徑的影響,從源碼中能夠看出

template

做用:用於定義模版文件的路徑

源碼:

this.options.template = this.getFullTemplatePath(this.options.template, compiler.context);
複製代碼

所以template只有定義在webpack的context下才會被識別,webpack context的默認值爲process.cwd(),既運行 node 命令時所在的文件夾的絕對路徑

filename

做用:輸出的HTML文件名,默認爲index.html,能夠直接配置帶有子目錄

源碼:

this.options.filename = path.relative(compiler.options.output.path, filename);
複製代碼

因此filename的路徑是相對於output.path的,而在webpack-dev-server中,則是相對於webpack-dev-server配置的publicPath

若是webpack-dev-server的publicPathoutput.publicPath不一致,在使用html-webpack-plugin可能會致使引用靜態資源失敗,由於在devServer中仍然以output.publicPath引用靜態資源,和webpack-dev-server的提供的資源訪問路徑不一致,從而沒法正常訪問。

有一種狀況除外,就是output.publicPath是相對路徑,這時候能夠訪問本地資源

因此通常狀況下都要保證devServer中的publicPathoutput.publicPath保持一致。

最後

關於webpack中的path就總結這麼多,在研究關於webpack路徑的過程當中看查到的一些關於路徑的零碎的知識以下:

斜槓/的含義

配置中/表明url根路徑,例如http://localhost:8080/dist/js/test.js中的http://localhost:8080/

devServer.publicPath & devServer.contentBase

  • devServer.contentBase 告訴服務器從哪裏提供內容。只有在你想要提供靜態文件時才須要。
  • devServer.publicPath 將用於肯定應該從哪裏提供 bundle,而且此選項優先。

node中的路徑

  • __dirname: 老是返回被執行的 js 所在文件夾的絕對路徑
  • __filename: 老是返回被執行的 js 的絕對路徑
  • process.cwd(): 老是返回運行 node 命令時所在的文件夾的絕對路徑

參考

相關文章
相關標籤/搜索