對於webpack配置中filename和chunkFilename在使用中有些不懂的地方,研究之後記錄如下。
filename: string | function
此選項決定了每個輸出 bundle 的名稱。這些 bundle 將寫入到 output.path 選項指定的目錄下。
對於單個入口起點,filename 會是一個靜態名稱。
chunkFilename: string
此選項決定了非入口(non-entry) chunk文件的名稱。
上面就是關於filename和chunkFilename的官文解釋。
首先什麼是入口?
目前可以理解爲entry字段就是提供的應用的入口文件。(這個解釋並不全面)
開始做出如下嘗試:
目錄結構:
nodule_modules/
dist/
src/
--index.js
--a.js
webpack.config.js
文件webpack.config.js
var path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, '../dist'),
filename: '[name].[contenthash:6].js',
chunkFilename: '[name].[contenthash:4].js'
}
}
上面配置中,整個應用的入口就是文件/src/index.js。
文件src/index.js
import('./a.js')
console.log('index')
文件src/a.js
console.log('a')
打包後的結果可以看出來index.js對應的main.conenthash.js是6位的,a.js對應的1.contenthash.js是4位的。
這和我們預想的結果一樣,filename設置的是入口文件的文件名,chunkFilename設置的是非入口文件的文件名。動態加載的文件a.js並不是入口文件。
我們知道webpack打包的文件分爲三大模塊,一個是第三方庫,這部分比較穩定,可以打包到一起,利於緩存。一個是業務代碼,基本上每次發版都會修改。最後一個是webpack生成的runtime和manifest,每次打包都會改變。
現在我們的代碼中只涉及到了自己的業務代碼,並沒有第三方庫代碼,即使這樣我們也可以分離出webpack生成runtime和manifest。
修改配置如下:
var path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, '../dist'),
filename: '[name].[contenthash:6].js',
chunkFilename: '[name].[contenthash:4].js'
},
optimization: {
runtimeChunk: {
name: 'manifest'
}
}
}
可以看到entry對應生成的文件main.js文件的hash變成了4位,但是entry明明就是規定的是應用的入口文件,對應的文件名配置應該是filename,對應的hash位數應該是6位。
但現實它就是4位的。
並且還能看出來新分離出來的manifest.js的hash是6位的。
這其實也說明了webpack打包的應用本質上的入口並不是entry字段提供的文件,應用的入口是webpack自己生成的runtime。是通過runtime + manifest纔將我們的代碼和第三方庫組織起來並且正常運行的。
所以webpack打包的應用入口是自己生成的runtime + manifest。
沒有提取manifest的時候entry生成對應的main.js的hash位數是正確的。這其實只是一個巧合,因爲這個情況下整個引用的入口就是main.js,因爲manifest + runtime並沒有從main,js中分離出來。所以入口文件對應的就是main.js,然後filename的設置是正確應用在了main.js上。
從上面的分析中可以推倒出,如果我們把manifest + runtime內聯到HTML文件中,那麼將不會有6位hash的文件被生成,因爲並沒有入口的js文件被生成。修改配置文件如下:
var path = require('path')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin')
module.exports = {
mode: "development",
entry: './src/index.js',
output: {
path: path.resolve(__dirname, './dist'),
filename: '[name].[contenthash:6].js',
chunkFilename: '[name].[contenthash:4].js'
},
optimization: {
runtimeChunk: {
name: "manifest",
},
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new ScriptExtHtmlWebpackPlugin({
inline: /manifest..*.js$/
})
]
}
從上圖中可以看到確實沒有6位hash的文件被生成了。
總結:
output.filename規定的是應用入口文件的名稱,而output.entry提供的是webpack打包的入口。某種情況下這兩個入口是統一的。
通過webpack打包後的應用入口是webpack生成的manifest + runtime。當沒有分離manifest + runtime的時候,這部分生成的內容會和entry字段提供的文件相同。