Skip to content

Different import order leads to multiple vendor bundles #135

@wyntau

Description

@wyntau

Condition

Suppose I have a project have two entry file foo-entry.js and bar-entry.js, both of them import es6-promise and normalize.css. Additionally foo-entry may also import other modules, e.g. object-assign.

Now I want to split both shared node_modules es6-promise and normalize.css to shared-vendor.js and shared-vendor.css(use mini-css-extract-plugin to extract out from shared-vendor.js), and split object-assign to foo-vendor.js.

So on foo page, I add shared-vendor.js, foo-vendor.js, foo-entry.js to script tag in html
And on bar page, I add shared-vendor.js and bar-entry.js to script tag in html.

Reproduce

To do this, I pass a config array to webpack. the config like below. The only difference is two entry name

var webpack = require('webpack');
var MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = [{
  mode: 'development',
  entry: {
    'foo-entry': './src/foo-entry.js',
  },
  output: {
    filename: '[name].pack.[chunkhash:12].js',
    chunkFilename: 'foo-chunk.[chunkhash:12].js'
  },
  optimization: {
    splitChunks: {
      cacheGroups: {
        vendor: {
          test: /\/node_modules\/(es6-promise|normalize\.css)\//,
          name: 'shared-vendor',
          filename: 'share-vendor.pack.[chunkhash:12].js',
          chunks: 'initial'
        },
        // here may have other groups with lower priority to split rest modules
      }
    }
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].pack.[chunkhash:12].css'
    })
  ],
  module: {
    rules: [
      {
        test: /\.css/,
        // loader: ['style-loader', 'css-loader'],
        loader: [MiniCssExtractPlugin.loader, 'css-loader']
      }
    ]
  }
}, {
  mode: 'development',
  entry: {
    'bar-entry': './src/bar-entry.js',
  },
  output: {
    filename: '[name].pack.[chunkhash:12].js',
    chunkFilename: 'bar-chunk.[chunkhash:12].js'
  },
  optimization: {
    splitChunks: {
      cacheGroups: {
        vendor: {
          test: /\/node_modules\/(es6-promise|normalize\.css)\//,
          name: 'shared-vendor',
          filename: 'share-vendor.pack.[chunkhash:12].js',
          chunks: 'initial'
        }
        // here may have other groups with lower priority to split rest modules
      }
    }
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].pack.[chunkhash:12].css'
    })
  ],
  module: {
    rules: [
      {
        test: /\.css/,
        // loader: ['style-loader', 'css-loader'],
        loader: [MiniCssExtractPlugin.loader, 'css-loader']
      }
    ]
  }
}]
// src/foo-entry.js
import 'normalize.css';
import 'es6-promise/auto';
// src/bar-entry.js, the import order is different from foo-entry.js
import 'es6-promise/auto';
import 'normalize.css'

Expected result

Generate four files.

  • foo-entry.pack.[chunkhash].js
  • bar-entry.pack.[chunkhash].js
  • shared-vendor.pack.[chunkhash].js, include es6-promise
  • shared-vendor.pack.[chunkhash].css, include normalize.css

Actual result

Generate six files. Two shared-vendor.js and two shared-vendor.css with the very same content

  • foo-entry.pack.[chunkhash].js
  • bar-entry.pack.[chunkhash].js
  • shared-vendor.pack.[chunkhash-1].js, include es6-promise
  • shared-vendor.pack.[chunkhash-1].css, include normalize.css
  • shared-vendor.pack.[chunkhash-2].js, include es6-promise
  • shared-vendor.pack.[chunkhash-2].css, include normalize.css

Search and find

  • If I do not use mini-css-extract-plugin, replace it with style-loader(the commented line on above webpack config), only one shared-vendor.pack.[chunkhash].js and shared-vendor.pack.[chunkhash].css will be generated.
  • If I change import order in bar-entry.js, firstly import normalize.css and then import es6-promise like foo-entry, it will also generate only one shared-vendor.pack.[chunkhash].js and shared-vendor.pack.[chunkhash].css.

Problem

  • Does mini-css-extract-plugin change the chunkhash compute algorithm?
  • Why same content have different chunkhash?
  • Why different import order will generate different chunkhash but same content ?
  • Does my this usage have problem? How can I do to split both shared modules to shared-vendor, and the rest modules to [name]-vendor?

Reproduce project

reproduce.zip
To mininal reproduce, I removed all other modules. So foo-entry and bar-entry will only import two modules es6-promise and normalize.css and have no any other code

Environment

  • Node v8.11.1
  • webpack 4.8.1
  • mini-css-extract-plugin 0.4.0
  • OS Mac 10.12.6

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions