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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

[@unocss/webpack] Generated CSS is not processed by PostCSS #386

Closed
chrissantamaria opened this issue Jan 3, 2022 · 9 comments
Closed
Labels
help wanted Extra attention is needed stale webpack

Comments

@chrissantamaria
Copy link

Hi 馃憢 this is a bit of a broad thread and not something I expect to necessarily be addressed - just opening to start a conversation and see if there's a better way I should be approaching things.

All of this is my interpretation of UnoCSS and similar projects after some brief digging - please correct me if something in my thought process seems incorrect 馃槄

Problem

I'm attempting to use @unocss/webpack in conjuction with postcss-loader to have all CSS (including generated unocss classes) processed by my PostCSS pipeline. Here's a slimmed example Webpack config:

{
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['css-loader', 'postcss-loader'],
      },
    ],
  },
  plugins: [
    new UnoCSS({
        presets: [presetUno()],
      }),
  ],
}

As a consumer of @unocss/webpack, I would expect the uno.css import to be treated the same as any other CSS modules. However, from my testing this doesn't appear to be the case - generated CSS is injected later in the Webpack build after loaders have been run.

Exploration

After some digging into the plugin's internals, this seems to be expected behavior. Generated CSS is injected into built assets in the optimizeAssets stage, meaning Webpack won't reprocess the created RawSources through any configured loaders.

I looked into similar plugins and noticed Windi CSS takes a slightly different approach, using a glob parser to scan all valid source files (not just those in the build's dependency graph) and generate CSS classes earlier in the build. This ensures the virtual module is populated before loaders are run, resulting in all CSS (including windi.css) being parsed through loaders such as PostCSS. This does have the notable downside of including potentially unused classes, though these can in theory be purged later in the build.

Solution

I've spent quite a bit of time investigating this problem with Webpack and haven't found a clean solution. Seems like a bit of a chicken and egg problem - we'd like to use Webpack's dependency graph to only parse relevant modules for classes, but the CSS needs to be ready before loaders (and therefore dependency graph creation) even start. One idea I've had is using a child compiler to do an initial build pass just for generating CSS, though I haven't found a way to implement this that isn't wasteful (seems to generally perform an entire build).

Again, opening this thread more to start conversation than to request any concrete changes - I don't think unocss' approach is strictly wrong given Webpack's constraints but I'd love if we could come up with a best of both worlds approach. Thanks!

@antfu
Copy link
Member

antfu commented Jan 4, 2022

Yes, exactly as you described. I wrote both approaches of Windi's and UnoCSS, and indeed they are basically trade-offs. I personally don't use PostCSS so I don't have this concern. If that's something you really need, I am happy to receive a PR to introduce the pre-scanning approach under an optional flag for user to judge the trade-offs that fit for their use cases.

@chrissantamaria
Copy link
Author

Right now I don't have an urgent need - glad I'm on the right track here, happy to maintain my own fork if I end up building something custom for my use case. Feel free to close this issue unless you'd like it open to keep thinking through ideas. Thanks!

@productdevbook
Copy link

./node_modules/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[3].oneOf[8].use[1]!./node_modules/next/dist/build/webpack/loaders/postcss-loader/src/index.js??ruleSet[1].rules[3].oneOf[8].use[2]!./node_modules/unplugin/dist/webpack/loaders/load.js??ruleSet[1].rules[6].use[0]!./_virtual_\__uno.css
Error: Malformed PostCSS Configuration
    at Array.forEach (<anonymous>)

@sabereen
Copy link
Contributor

sabereen commented Jul 13, 2022

Hello, pitching loaders is one of the features of webpack (another link).

Can we use a loader instead of a plugin? or use both of them (like MiniCssExtractPlugin).

We can scan all files in pitching phase and generate CSS rules in evaluating phase! Now all of other loaders can process the generated CSS.

@chrissantamaria
Copy link
Author

Hello, pitching loaders is one of the features of webpack (another link).

Can we use a loader instead of a plugin? or use both of them (like MiniCssExtractPlugin).

We can scan all files in pitching phase and generate CSS rules in evaluating phase! Now all of other loaders can process the generated CSS.

This could probably work! Not entirely sure how to most effectively read module contents based on remainingRequest (looks like the string also contains loader metadata) but in theory should be possible.

It is worth noting that loaders (including pitching ones) won't run on each build if persistent caching is enabled, resulting in issues like #419. It would be great if we could find a solution that addresses both of these issues at once (though I'm not sure if there's any great alternatives).

afaik unplugin also doesn't support the pitch option, so we'd likely have to write our own loader module rather than using the transform or load helpers.

@stale
Copy link

stale bot commented Sep 14, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Sep 14, 2022
@stale stale bot closed this as completed Sep 21, 2022
@hustcer
Copy link

hustcer commented Sep 27, 2022

@Stale Please reopen

@sudongyuer sudongyuer reopened this Sep 27, 2022
@stale stale bot removed the stale label Sep 27, 2022
@stale
Copy link

stale bot commented Nov 26, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Nov 26, 2022
@stale stale bot closed this as completed Dec 3, 2022
@GrapevineLin
Copy link

/reopen

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed stale webpack
Projects
None yet
Development

No branches or pull requests

7 participants