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

Implement CSS Cascade Layers support #51

Merged
merged 12 commits into from
Sep 16, 2023

Conversation

AlexandrHoroshih
Copy link
Contributor

@AlexandrHoroshih AlexandrHoroshih commented Sep 15, 2023

Closes #50

What is implemented

@layer rules got special processing, similiar to @media rules

Layer order definitions (@layer a, b, c;) are treated similiar to other "unprocessed" at-rules and are included at the top and as-is.

Actual layered styles (@layer a { ... }) are treated the same way @media is handled now - only actually used styles are included into critical css.

AST types are refactored to make a clear distinction between processed at-rules and unprocessed at-rules

During implementation it became obvious, that at-rules are splitted into two groups:

  • processed at-rules, like @media and @layer, that are properly handled
  • unknown at-rules, which are "unmatchable" and thus are included into critical styles as-is

AST types and related code was updated to reflect that:

  • atRules at the SingleStyleAst type became unknownAtRules
  • media: string[] at the StyleSelector is changed into atrules: { kind: "layer" | "media", value: string }[], this way it is possible to add more nestable at-rules like @supports

What is not implemented

There is a possible edge-case:
It is possible to have the same layers order definition at multiple files, something like this

/* index.css */
@layer a, b, c;

// ...styles

/* chunk.css */
@layer a, b, c;

// ...styles

I think, it is possible in the situation, where layers are added automatically by bundlers, based on some heuristics or rules, since this way layers order is guaranteed and is not dependent on loading order 🤔

In that case used-styles probably should deduplicate these definitions.

But since i do not have any actual real-life use-cases, which would require something like this, it is not added in this PR

If this problem will actually happend one day - then cross-file deduplication of layer definitions can be solved by introducing something like "shared context" for the AST parser:

const astFromFiles = (fileDate: StyleFiles): StyleAst => {
  const sharedContext = {
   layerDefinitions: new Set()
  }

  return Object.keys(fileDate).reduce((acc, file) => {
    acc[file] = buildAst(fileDate[file], file, sharedContext);

    return acc;
  }, {} as StyleAst);
};

const buildAst = (cssString, file, context) => {
  // ...
 if (context.layerDefinitions.has(`@layer ${rule.params}`) {
  return;
 }
}

@AlexandrHoroshih
Copy link
Contributor Author

Hello @theKashey !

Could you take a look? 🙏

@theKashey theKashey self-requested a review September 16, 2023 09:28
@theKashey
Copy link
Owner

What I could say @AlexandrHoroshih - it's AMAZING!
The changes in the code are minimal, no tests bothered for no reason and the one created are focused on what they should test and according to the results.... it's just working as it should!

@theKashey theKashey merged commit cc1861f into theKashey:master Sep 16, 2023
@theKashey
Copy link
Owner

Released as [email protected]

@AlexandrHoroshih AlexandrHoroshih deleted the css-cascade-layers branch September 16, 2023 12:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

CSS Cascade Layers support
2 participants