webpack-contrib / mini-css-extract-plugin

Lightweight CSS extraction plugin
MIT License
4.67k stars 388 forks source link

Filtering multiple entries chunks #974

Closed zalishchuk closed 7 months ago

zalishchuk commented 2 years ago

Feature Proposal

The feature I am trying to implement is filtering entry chunks from which CSS will be extracted. Any chance it can be done using filename function syntax and pathData argument in it?

Feature Use Case

Two same entry points, with different names, but one of them does not have externals in it. Done with the help of webpack5 layers feature. So as a result, we have like 2 identical .css files exported with different names, but want to have only one. HtmlWebpackPlugin has this feature and it is very useful.

// webpack.config.js

entry: {
  bundle: {
    import: './src/index.js',
    layer: 'bundle',
  },
  'bundle-externals': {
    import: './src/index.js',
    layer: 'bundle-externals',
  },
},
externals: {
  byLayer: {
    'bundle-externals': {
      'my-lib': 'myLib',
    },
  },
},
plugins: [
  new MiniCssExtractPlugin({
    chunks: ['bundle'], // proposed feature
    filename: '[name].css'
  }),
  new HtmlWebpackPlugin({
    chunks: ['bundle'],
    template: './src/index.html',
  }),
]

Please paste the results of npx webpack-cli info here, and mention other relevant information

System:
  OS: macOS 11.6.5
  CPU: (8) x64 Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz
  Memory: 151.33 MB / 16.00 GB
Binaries:
  Node: 16.15.0 - ~/.nvm/versions/node/v16.15.0/bin/node
  Yarn: 1.22.19 - ~/.yarn/bin/yarn
  npm: 8.5.5 - ~/.nvm/versions/node/v16.15.0/bin/npm
Browsers:
  Chrome: 105.0.5195.125
  Safari: 15.4
Packages:
  css-loader: ^6.7.1 => 6.7.1
  css-minimizer-webpack-plugin: ^4.1.0 => 4.1.0
  html-webpack-plugin: ^5.5.0 => 5.5.0
  postcss-loader: ^7.0.1 => 7.0.1
  resolve-url-loader: ^5.0.0 => 5.0.0
  sass-loader: ^13.0.2 => 13.0.2
  style-loader: ^3.3.1 => 3.3.1
  webpack: ^5.74.0 => 5.74.0
  webpack-cli: ^4.10.0 => 4.10.0
  webpack-dev-server: ^4.11.0 => 4.11.0
alexander-akait commented 2 years ago

Why do not use layer? https://github.com/webpack-contrib/mini-css-extract-plugin/blob/master/src/loader.js#L304

zalishchuk commented 2 years ago

@alexander-akait the reason is that layers are not included into plugin options validation schema, and even if I remove the validation manually it doesn't work as expected.

ValidationError: Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema.
 - options has an unknown property 'layer'. These properties are valid:
   object { filename?, chunkFilename?, experimentalUseImportModule?, ignoreOrder?, insert?, attributes?, linkType?, runtime? }

The solution I found for myself is:

function _wrapExternalsLayer(rawExternals) {
  const externals = rawExternals.byLayer;

  return (ctx, callback) => {
    const issuerLayer = ctx.contextInfo?.issuerLayer;
    if (issuerLayer) {
      const moduleName = ctx.request.split('/')[0];
      const externalResult = externals[issuerLayer]?.[moduleName];
      if (externalResult) return callback(null, externalResult);
    }

    callback();
  };
}

// webpack.config.js
externals: _wrapExternalsLayer({
  byLayer: {
    'bundle-externals': {
      'my-lib': 'myLib',
    },
  },
}),
zalishchuk commented 2 years ago

Ah, didn't notice this layer option is for the loader, not the plugin, but still doesn't solve the problem I mentioned above.

alexander-akait commented 2 years ago

Yeah, you need to pass this to loader https://github.com/webpack-contrib/mini-css-extract-plugin/blob/master/src/loader-options.json#L28

alexander-akait commented 2 years ago

The feature I am trying to implement is filtering entry chunks from which CSS will be extracted.

Can you clarify?

Because in this case you will have the first chunk extracted and the second chunk with CSS inside JS, do you expect it?

alexander-akait commented 2 years ago

To be honest, I don't think you're going in the right direction. You can use multi compiler mode for it. Maybe I missing something, so can you create a small repo/example and show you what you expected?

alexander-akait commented 7 months ago

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