也许你接触过CommonsChunkPlugin,通过它来打公共模块,并做long cache,可能会是这样的代码

// webpack.config.js
var config = {
    entry: {
        'commons': [
            'react', 'react-dom'
        ],
        'index': [
            './example/index'
        ]
    },
    output: {
        path: path.join(__dirname, 'build'),
        filename: '[name].[chunkhash:8].bundle.js',
        chunkFilename: '[id].[chunkhash:8].bundle.js',
        publicPath: '/static/build/'
    },
    plugins: [
        new webpack.NoErrorsPlugin(),
        new CommonsChunkPlugin({
            name: 'commons',
            filename: 'js/[name].[hash:8].bundle.js'
        })
    ]
};

兴高采烈打包出来是js/commons.7279fdf6.bundle.js
改下入口文件./example/index.js的代码,如添加console.log('gmfe'),再次打包出来文件是js/commons.fceb5fbe.bundle.js

问题来了,公共文件并没有修改,怎么hash变了呢?

对比两次commons.xxx.js的文件可以发现,只有一次区别,且区别是index.[hash:8].bundle.js中的hash值。
也就是说index.js文件变了,index的hash肯定变,而index的hash在commons中。所以commons变了,hash也变。

为啥commons会有index的hash值呢?
细心的同学会发现文件开头有这么一行注释// webpackBootstrap,webpackBootstrap中包含了各个模块的的加载信息,打包的脚本一般会存在webpackBootstrap,用来做初始化。而CommonsChunkPlugin就打在了commons中。

为了解决commons的hash问题,搞了一个插件。只对commons依赖的源代码算hash,这样就可以保证commons的hash不变了。

插件和example在 commons-version-webpack-plugin

----分割线----

后来看了这篇文章,其方案会更好。
我之前也尝试过这个方案。这样 webpackBootstrap 会放在manifest文件中。

// output配置
output: {
    path: path.join(__dirname, 'build'),
    filename: '[name].[chunkhash:8].bundle.js',
    chunkFilename: 'js/[id].[chunkhash:8].bundle.js',
    publicPath: siteConfig.publicPath
}

// CommonsChunkPlugin配置
new CommonsChunkPlugin({
    names: ['commons', 'manifest']
})

同时有几个注意的地方:

  • 是names,不是name。虽然webpack同样会工作,但是打出来commons.hash1.js manifest.hash2.js hash1 === hash2。 如果用了 names,则hash1 !== hash2。

  • CommonsChunkPlugin如果不提供filename,则用output的filename。而用webpack-dev-server会提示错误(不能使用chunkhash)。 但是 webpack 就没有问题。


麦芽糖
1.4k 声望39 粉丝

enjoy segmentfault