Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Different import order leads to multiple vendor bundles #135

Closed
wyntau opened this issue May 9, 2018 · 11 comments
Closed

Different import order leads to multiple vendor bundles #135

wyntau opened this issue May 9, 2018 · 11 comments

Comments

@wyntau
Copy link

wyntau commented May 9, 2018

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
@alexander-akait
Copy link
Member

@wyntau Thanks for issue, we known this problem and already fixed this problem, just wait improve documentation webpack/webpack.js.org#2096. Thanks! Feel free to feedback!

@alexander-akait
Copy link
Member

@wyntau I will leave open because looks like you have other issue around code splitting, right?

@wyntau
Copy link
Author

wyntau commented May 9, 2018

Does it mean I can now replace all [chunkhash] with [contenthash] safely in webpack 4.8.1?

@alexander-akait
Copy link
Member

@wyntau yes, [chunkhash] for backward compatibility, use always [contenthash], in webpack@5 it is right way to create long term caching

@wyntau
Copy link
Author

wyntau commented May 9, 2018

@evilebottnawi
I canged all [chunkhash] to [contenthash], and only one shared-vendor.pack.[contenthash].css will generated, But still two shared-vendor.pack.[contenthash].js with same content.

image

  1. When I use mini-css-extract-plugin, the bar-entry's import modules order will still affect the [contenthash] like above described
  2. If I use style-loader, only one shared-vendor.pack.[contenthash].js(included es6-promise and normalize.css) will generated.

@alexander-akait
Copy link
Member

alexander-akait commented May 9, 2018

@wyntau looks like problem with splitChunks, can you create minimum reproducible test repo? sorry, found in original post. It is hard to solve based only on configuration

@wyntau
Copy link
Author

wyntau commented May 9, 2018

@evilebottnawi
reproduce.zip

this is the newest zip

npm install
npx webpack

@wyntau
Copy link
Author

wyntau commented May 19, 2018

hi @evilebottnawi , do you have any idea why will two vendor files with the same content be generated?

@michael-ciniawsky michael-ciniawsky added this to the 0.4.3 milestone Aug 24, 2018
@michael-ciniawsky michael-ciniawsky changed the title when use mini-css-extract-plugin different import order will lead to different chunkhash Different import order leads to multiple vendor bundles Aug 24, 2018
@michael-ciniawsky
Copy link
Member

The [chunkhash] change is to be expected, use [contenthash] instead. Did you resolve the issue about multiple vendor bundles being generated ?

@wyntau
Copy link
Author

wyntau commented Aug 26, 2018

@michael-ciniawsky not yet

@alexander-akait
Copy link
Member

Closing due to inactivity. Please test with latest version and feel free to reopen if still regressions. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants