slightlyfaulty / stylus-native-loader

✒️ A super fast Stylus loader for Webpack that leverages the built-in power of Stylus.
MIT License
15 stars 1 forks source link

Styles duplication #4

Closed mytecor closed 3 years ago

mytecor commented 3 years ago

Reproduction: https://github.com/midnightcoder-pro/stylus-duplication-demo Unfortunately stylus-loder works same way

slightlyfaulty commented 3 years ago

This is the expected behaviour. By importing 2 separate styl files from index.js, you're invoking 2 separate instances of the loader that know nothing about each other. After compiling, the 2 separate outputs are concatenated by extract-css-chunks-webpack-plugin. This works the same with any other loader.

To deduplicate your CSS output you should use optimize-css-assets-webpack-plugin. extract-css-chunks-webpack-plugin has a section that explains how to configure this properly.

mytecor commented 3 years ago

This does not solve the problem with imports At the output, I get pieces of the form:

.column,.flex{display:flex}
.center,.flex,.modal{display:flex}
slightlyfaulty commented 3 years ago

If CSS deduplication isn't working well enough in your project, then you need to change how you import your styl files. This is unfortunately a fundamental "issue" with the way Webpack works, and there isn't a way around it at the loader level.

slightlyfaulty commented 3 years ago

It's worth mentioning that if you're importing a common styl file from multiple other styl files, you should use @require instead of @import to make sure it's not imported twice.

mytecor commented 3 years ago

Yes, as you can see in my repo, I used @require, but it also duplicates extended classes

slightlyfaulty commented 3 years ago

In your demo repo you are using @import. But it makes no difference in this case since you're only importing it once, as far as Stylus is aware of.

https://github.com/midnightcoder-pro/stylus-duplication-demo/blob/6a91db3785cb014af49577569386f9378bf1d31e/src/child.styl#L2

mytecor commented 3 years ago

Oops. I fixed the demo

mytecor commented 3 years ago

Now it produces:

.box{border-width:2px;border-style:solid;padding:0 20px;margin:0 6px;max-width:400px}
.child{border-style:dotted;border-color:green}
.box,.child{border-width:2px;border-style:solid;padding:0 20px;margin:0 6px;max-width:400px}
.child{border-color:red}

The optimize-css-assets-webpack-plugin doesn't help

slightlyfaulty commented 3 years ago

You didn't set up optimize-css-assets-webpack-plugin properly. Please read the docs that I linked. It should be added to optimization.minimizer, not to plugins.

terser-webpack-plugin also needs to be added explicitly otherwise your JS won't be minimized.

const TerserJSPlugin = require('terser-webpack-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')

module.exports = {
  ...
  optimization: {
    minimizer: [
      new TerserJSPlugin(),
      new OptimizeCSSAssetsPlugin(),
    ],
  },
  ...
}
mytecor commented 3 years ago

Nothing changed, I updated the demo

slightlyfaulty commented 3 years ago

I'm not sure what else you're expecting, but with the way you're importing and extending selectors, that as deduplicated as it can possibly be. There isn't a single selector that's duplicated in your output.

mytecor commented 3 years ago

I need the result to be something like this: https://github.com/midnightcoder-pro/stylus-duplication-demo/blob/single-entry/dist/bundle.css

slightlyfaulty commented 3 years ago

Well then don't import your styl files separately. Use an index.styl file.

But even then Stylus isn't going to magically combine your .child selectors for you.

mytecor commented 3 years ago

Okay, it's crutches, but there's probably no other way out Of course, I would like it to work as composing in css-loader, otherwise, the meaning of modules is lost

slightlyfaulty commented 3 years ago

It works exactly like plain CSS with css-loader. Each styl files imported from index.js is compiled to CSS and then passed to css-loader. However, styl files imported from other styl files are not handled by Webpack, they are handled by the Stylus compiler. So these imports are not modules like files imported from js files.

Maybe since the latest updates you can get stylus-loader to do what you want since it uses Webpack to resolve imports as modules in styl files, but I don't know if it will work or how you would do it.

mytecor commented 3 years ago

I'll try, in any case, thank you

slightlyfaulty commented 3 years ago

No problem. Best of luck!