Skip to content

Webpack 4 chunkhash/contenthash can vary between builds #7179

@mikeyoon

Description

@mikeyoon

Do you want to request a feature or report a bug?
Bug

What is the current behavior?
I'm finding that the chunkhash varies between builds in v4. Using the diff utility between the the different files shows no differences. Attempting to narrow the codebase down reduces the frequency of different hashes.

If the current behavior is a bug, please provide the steps to reproduce.
I've been unsuccessful in creating a small test case as it's just too inconsistent and would take such an enormous amount of time for me to figure out by slicing and dicing our codebase.

I'm happy to help as much as I can to find a repro, but I'd need some information about diagnostics I can turn on to figure out what's happening.

What is the expected behavior?
The chunkhash should be consistent, as does in version 3.

If this is a feature request, what is motivation or use case for changing the behavior?

Please mention other relevant information such as the browser version, Node.js version, webpack version, and Operating System.

Webpack 4.6.0, Node 8.9.4, OS X 10.13.4

Here's our webpack.config.js

const path = require('path');
const webpack = require('webpack');
const ProgressBarPlugin = require('progress-bar-webpack-plugin');
const childProcess = require('child_process');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const AssetsPlugin = require('assets-webpack-plugin')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const WebpackBuildNotifierPlugin = require('webpack-build-notifier');

const root = path.resolve(__dirname, './src');
const webappPath = path.resolve(__dirname, '..');
const deployPath = path.resolve(webappPath, './public/assets');

const dev = !process.env.NODE_ENV;
const ci = process.env.NODE_ENV === 'ci';
const prod = process.env.NODE_ENV === 'production';

if (prod) {
  console.log('PRODUCTION MODE ENABLED');
}

// don't hash the filename unless we're building for prod or staging. Hashed filenames interfere with karma tests.
const outputFilename = dev || ci ? '[name].bundle.js' : '[name].[chunkhash].bundle.js';
const excludedMapSources = dev ? [/vendor.*bundle.js/, /manifest.*bundle.js/] : [/manifest.*bundle.js/];

function getPlugins() {
  let plugins = [
    new CleanWebpackPlugin(['public/assets/*'], {
      allowExternal: true,
      root: webappPath
    }),

    new webpack.SourceMapDevToolPlugin({
      filename: "[file].map",
      exclude: excludedMapSources
    }),

    new AssetsPlugin({
      includeManifest: true,
      path: deployPath,
      prettyPrint: true
    })
  ];

  plugins.push(new webpack.NamedModulesPlugin());
  plugins.push(new webpack.optimize.ModuleConcatenationPlugin());

  return plugins;
}

module.exports = {
  context: root,

  mode: prod ? 'production' : 'development',
  devtool: false, // rely on SourceMapDevToolPlugin
  cache: dev,

  stats: {
    chunks: false,
    chunkModules: false,
    entrypoints: false,
    modules: false,
    version: false,
    hash: false,
    timings: false,
  },

  entry: {
    app: './core-app/bootstrap.ts',
    embed: './core-embed/bootstrap.ts'
  },

  watchOptions: {
    aggregateTimeout: 300,
    ignored: /node_modules/
  },

  resolve: {
    extensions: ['.ts', '.tsx', '.js', '.jsx'],
    alias: {
      handsontable: 'handsontable/dist/handsontable.full.js'
    }
  },

  output: {
    filename: outputFilename,
    path: path.resolve(__dirname, '../public/assets'),
  },

  optimization: {
    runtimeChunk: {
      name: "manifest",
    },
    splitChunks: {
      cacheGroups: {
        // default: false,
        commons: {
          test: /[\\/]node_modules[\\/]/,
          name: "vendor",
          chunks: "initial",
          enforce: true
        }
      },
    },
  },

  externals: {
    nvd3: 'window.nv',
    highcharts: "window.Highcharts",
    angular: 'window.angular',
    jquery: 'window.jQuery',
    lodash: 'window._',
    moment: 'window.moment',
    ace: 'window.ace',
    d3: 'window.d3',
    chiliPiper: 'window.ChiliPiper',
  },

  plugins: getPlugins(),

  module: {
    rules: [
      {
        test: /\.ts(x?)$/,
        exclude: [/\.(spec|e2e)\.ts$/],
        use: [{
          loader: 'ts-loader',
          options: {
            experimentalWatchApi: true // seems to work ok atm, but performance improvement varies
          }
        }]
      }, {
        test: /\.(html|css)$/,
        loader: 'raw-loader',
        exclude: /\.async\.(html|css)$/
      }, {
        test: /\.svg$/,
        loader: 'url-loader?' + JSON.stringify({
          name: '[name]_[hash]'
        })
      }
    ]
  }
};

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions