Migrate to css cascade layers#3229
Conversation
✅ Deploy Preview for babel-v9 ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for babel-v8 ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
| "babel.custom": (filePath: string) => | ||
| filePath.includes("/src/css") || filePath.includes("/static/css"), |
There was a problem hiding this comment.
@slorber It would be great if there is a single customCSS(filePath: string): boolean option which defines a docusaurus.custom layer overriding the other predefined layers. Of course users can turn to the layers option for more advanced usage such as resetting before infima, or defining multiple layers.
There was a problem hiding this comment.
I'm not sure I understand, wouldn't it be better to just add @layer babel.custom in your CSS files directly?
As you can see in the default config, I hesitated including a @layer docusaurus.website to all website CSS. I decided it was not a good idea by default because it may be confusing for users not familiar with that feature. In particular, !important works quite differently when using layers.
For that reason I think it's better to keep custom CSS unlayered and let users apply a layer themselves in their CSS file.
In the future, we'll likely hardcode a layer in our CSS packages, instead of having a PostCSS plugin apply it on top of unlayered CSS. We only built the plugin so that we could provide an opt-in future flag. So I think it's reasonable to just use regular @layer directives in your CSS files, because this is what we'll likely all use in the future.
There was a problem hiding this comment.
I'm not sure I understand, wouldn't it be better to just add @layer babel.custom in your CSS files directly?
This is a very good point. Yesterday I tried adding @layer when debugging on this PR but it didn't work. Now I have investigated and here is what I found:
To avoid the ambiguous defaults target interpreted by different tools, I have temporarily set the target to chrome 141, since any version later than chrome 142 will throw "Error: No browserslist config found to handle the 'browserslist' target.", which is probably an rspack issue as it misinterprets the browser version unknown error thrown from the browserslist-rs crate due to the outdated brwoserslist-data crate. I believe it will be somehow fixed in rspack 2 once they update the crate dependencies.
Here is the screenshot of the landing page in development mode.
It should have been:
So the specificity does not apply. And the reason is that the @layer babel.custom is not transpiled, but somehow @layer docusaurus.*, added by the postcss plugin, are transpiled, even though chrome 141 should support the cascade layer very well. The transpiled output always win over the native @layer.
I have pushed the experimental change to #3230.
There was a problem hiding this comment.
Update: The production build of #3230 does looks good: https://deploy-preview-3230--babel-v8.netlify.app/, so it is an issue only reproducible on a development server.
There was a problem hiding this comment.
oh weird I don't know what is happening, if you can send a repro I'll take a look.
But we'll release v4.0 with Rspack v2 soon so it may not be worth it if your prod build works? I guess it remains a problem for local DX?
There was a problem hiding this comment.
oh weird I don't know what is happening, if you can send a repro I'll take a look.
I guess the imported CSS and the builtin CSS are handled by different tools (probably one is from JS and the other is from Rust?) You can check out the branch of #3230 and run yarn && yarn start.
But we'll release v4.0 with Rspack v2 soon so it may not be worth it if your prod build works? I guess it remains a problem for local DX?
Well, local DX is important, imo any visual difference between development & production should be avoided. For the time being I will keep the current approach, I will definitely give it a new try once the v4.0 with rspack 2 is released. Are there any alpha version that we can test? I have checked the npm tag and it seems there isn't an v4 alpha publicly available.
There was a problem hiding this comment.
No alpha for now and our canary process broken due to migrating to pnpm recently, I need to fix it 😅
| [ | ||
| "@docusaurus/plugin-css-cascade-layers", | ||
| { | ||
| layers: { |
There was a problem hiding this comment.
FYI you may want to add other layers here
If that helps, here's our default layers when you use the future flag:
// Not ideal to compute layers using "filePath.includes()"
// But this is mostly temporary until we add first-class layers everywhere
function layerFor(...params: string[]) {
return (filePath: string) => {
const posixFilePath = posixPath(filePath);
return params.some((p) => posixFilePath.includes(p));
};
}
// Object order matters, it defines the layer order
export const DEFAULT_LAYERS: PluginOptions['layers'] = {
'docusaurus.infima': layerFor('node_modules/infima/dist'),
'docusaurus.theme-common': layerFor(
'packages/docusaurus-theme-common/lib',
'node_modules/@docusaurus/theme-common/lib',
),
'docusaurus.theme-classic': layerFor(
'packages/docusaurus-theme-classic/lib',
'node_modules/@docusaurus/theme-classic/lib',
),
'docusaurus.core': layerFor(
'packages/docusaurus/lib',
'node_modules/@docusaurus/core/lib',
),
'docusaurus.plugin-debug': layerFor(
'packages/docusaurus-plugin-debug/lib',
'node_modules/@docusaurus/plugin-debug/lib',
),
'docusaurus.theme-mermaid': layerFor(
'packages/docusaurus-theme-mermaid/lib',
'node_modules/@docusaurus/theme-mermaid/lib',
),
'docusaurus.theme-live-codeblock': layerFor(
'packages/docusaurus-theme-live-codeblock/lib',
'node_modules/@docusaurus/theme-live-codeblock/lib',
),
'docusaurus.theme-search-algolia.docsearch': layerFor(
'node_modules/@docsearch/css/dist',
),
'docusaurus.theme-search-algolia': layerFor(
'packages/docusaurus-theme-search-algolia/lib',
'node_modules/@docusaurus/theme-search-algolia/lib',
),
// docusaurus.website layer ? (declare it, even if empty?)
};There was a problem hiding this comment.
Thank you. I end up importing DEFAULT_LAYERS from @docusaurus/plugin-css-cascade-layers/lib/options. Would you consider exporting DEFAULT_LAYERS from the index.ts? It might benefit other users as well if they want to override layers but do not want to manipulate the default internal layers.
| "babel.custom": (filePath: string) => | ||
| filePath.includes("/src/css") || filePath.includes("/static/css"), |
There was a problem hiding this comment.
I'm not sure I understand, wouldn't it be better to just add @layer babel.custom in your CSS files directly?
As you can see in the default config, I hesitated including a @layer docusaurus.website to all website CSS. I decided it was not a good idea by default because it may be confusing for users not familiar with that feature. In particular, !important works quite differently when using layers.
For that reason I think it's better to keep custom CSS unlayered and let users apply a layer themselves in their CSS file.
In the future, we'll likely hardcode a layer in our CSS packages, instead of having a PostCSS plugin apply it on top of unlayered CSS. We only built the plugin so that we could provide an opt-in future flag. So I think it's reasonable to just use regular @layer directives in your CSS files, because this is what we'll likely all use in the future.
|
Note, for this kind of website upgrades, you might find this visual regression workflow useful: https://docusaurus.io/blog/upgrading-frontend-dependencies-with-confidence-using-visual-regression-testing |
Thank you very much for the tip. I will explore if we can add an argos workflow. |
In this PR we enable the
@docusaurus/plugin-css-cascade-layersplugin and apply a custom layer to all the stylesheets withinsrc/cssandstatic/css.Note: although
caniuse-liteis bumped, the build target of the current website is not changed because we use rspack, which uses browserslist-rs, which depends on the browserslist-data crate, the last release of which is already 6 months ago. Becausebrowserslist-datais bundled in the rspack distributed binary, thedefaultsquery has not been updated for some time longer than 6 months. So the currentdefaultsdoes not support CSS cascade layers.Anyway, adding a custom layer fixes all the specificity issues.