对于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字段提供的文件相同。
参考
- 输出(output)
- manifest