wbepack中output.filename和output.chunkFilename

对于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字段提供的文件相同。

参考

  1. 输出(output)
  2. manifest

版权声明:本文为letterTiger原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。