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

fix(core): correctly order CSS imports #5987

Closed
wants to merge 2 commits into from
Closed

Conversation

Josh-Cena
Copy link
Collaborator

@Josh-Cena Josh-Cena commented Nov 22, 2021

Motivation

Fix the problem patched in #6052. Fix #3678.

Have you read the Contributing Guidelines on pull requests?

Yes

Test Plan

TODO

@facebook-github-bot facebook-github-bot added the CLA Signed Signed Facebook CLA label Nov 22, 2021
@Josh-Cena Josh-Cena added pr: bug fix This PR fixes a bug in a past release. and removed CLA Signed Signed Facebook CLA labels Nov 22, 2021
@facebook-github-bot facebook-github-bot added the CLA Signed Signed Facebook CLA label Nov 22, 2021
@Josh-Cena
Copy link
Collaborator Author

@lex111 I don't know how to reproduce #3678 although I've also been annoyed by !important in the past. Could you test if this would fix that?

@netlify
Copy link

netlify bot commented Nov 22, 2021

✔️ [V2]

🔨 Explore the source changes: 2297f8d

🔍 Inspect the deploy log: https://app.netlify.com/sites/docusaurus-2/deploys/619b27f4af138c0008bf388c

😎 Browse the preview: https://deploy-preview-5987--docusaurus-2.netlify.app

@github-actions
Copy link

github-actions bot commented Nov 22, 2021

⚡️ Lighthouse report for the changes in this PR:

Category Score
🟠 Performance 70
🟢 Accessibility 98
🟢 Best practices 100
🟢 SEO 100
🟢 PWA 95

Lighthouse ran on https://deploy-preview-5987--docusaurus-2.netlify.app/

@github-actions
Copy link

github-actions bot commented Nov 22, 2021

Size Change: -65 B (0%)

Total Size: 892 kB

Filename Size Change
website/build/assets/css/styles.********.css 100 kB -64 B (0%)
ℹ️ View Unchanged
Filename Size Change
website/.docusaurus/globalData.json 38.3 kB 0 B
website/build/assets/js/main.********.js 477 kB 0 B
website/build/blog/2017/12/14/introducing-docusaurus/index.html 66.2 kB 0 B
website/build/blog/index.html 37.8 kB 0 B
website/build/docs/index.html 44 kB +1 B (0%)
website/build/docs/installation/index.html 51.7 kB -2 B (0%)
website/build/index.html 29.5 kB 0 B
website/build/tests/docs/index.html 25.2 kB 0 B
website/build/tests/docs/standalone/index.html 21.7 kB 0 B

compressed-size-action

@netlify

This comment has been minimized.

@Josh-Cena
Copy link
Collaborator Author

Josh-Cena commented Nov 22, 2021

After re-reading that thread it seems #3678 is not solved... That one was hoping to make custom CSS, currently loaded via client modules, override module CSS styles

import React from 'react';
// Load this at the very top!
// client modules have to be loaded before anything else...
import './client-lifecycles-dispatcher';
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually have no idea we import client-lifecycles-dispatcher instead of @generated/clientModules here. But side-effects are too hard to reason so I didn't refactor it

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you are right and we should do this change, it was probably historical.

But yeah, hard to reason about and see possible side-effects.

@slorber
Copy link
Collaborator

slorber commented Nov 22, 2021

I'd rather not do this kind of change now until we have defined properly what kind of order we want exactly, have better test on CSS ordering issues, and have a concrete plan to solve them once for all.

This kind of change can produce annoying breaking changes for users that may need to rewrite some of their site's CSS. We don't have a lot of custom site CSS on Docusaurus, and need to make sure such change is fine for sites like ReactNative.dev.

If we really need to do such a breaking change, I'd rather do only one instead of doing multiple attempts, each producing a breaking change.

IMHO the order should rather be:

  • client modules (ie infima)
  • css modules / imports (can override infima)
  • site CSS => I don't think this PR puts site CSS last => we probably need another system to handle that

@Josh-Cena
Copy link
Collaborator Author

Josh-Cena commented Nov 22, 2021

This kind of change can produce annoying breaking changes for users that may need to rewrite some of their site's CSS

This would not affect most sites because it's making us actually abide to the spec we made. We have to make sure that styles are applied in the order of clientModules => import styles. In #3104 we accidentally loaded the classic theme's global styles.css CSS before loading Infima by importing Layout in core, as explained in #5873 (comment)

  • client modules (ie infima)
  • css modules / imports (can override infima)

This is exactly the ordering we are supposed to keep. But if you look at the App.tsx, we are now importing ErrorBoundary before importing client-modules, so the layout gets loaded early, and its CSS imports are loaded early as well, even before client modules. Does that make sense?

  • site CSS => I don't think this PR puts site CSS last => we probably need another system to handle that

I'll soon make another PR to handle that. Do you think we should apply that here as well? Note that we are just restoring the pre-#3104 behavior. Had #3104 not been merged, it doesn't really matter how we arranged the imports because they didn't have side-effects. We should find a tool to mark import side-effects, not sure if it would be easy

@slorber
Copy link
Collaborator

slorber commented Nov 22, 2021

The RN site is using theme.customCss which under the hood uses client modules.

https://github.com/facebook/react-native-website/blob/main/website/docusaurus.config.js#L73

        theme: {
          customCss: [
            require.resolve('./src/css/customTheme.scss'),
            require.resolve('./src/css/index.scss'),
            require.resolve('./src/css/showcase.scss'),
            require.resolve('./src/css/versions.scss'),
          ],
        },

This would not affect most sites

Unless we have a test plan for it, this is just a random guess 🤪

Fixing this issue with a few lines of code is probably not the time-consuming part, it's actually having a test plan and executing it that is the time-consuming part. I'd like such a test to be automated so that we never regress again on CSS ordering issues.

I'll soon make another PR to handle that.

No, this has to be handled atomically in a single PR atomically, not split into multiple PRs.

We define an order once for all, test it automatically on our Docusaurus site, test it in a few third-party sites to ensure this order is correct, and then we stick to it forever.


I can't dedicate much time to all this atm as I'm still trying to focus on the category index feature.

If you want to work on this, be ready to invest much more time in it because it's unlikely I'll want to merge a PR like this one without a strong understanding of the possible annoying side effects for our user base. We need to limit the number of breaking changes.

If that helps, I can see how to produce a canary release for that branch and you can open PRs to some third party sites so that we can see what kind of impact it has

@Josh-Cena
Copy link
Collaborator Author

Sure, will see what we can do to test this PR 👍 I would figure out about making the siteConfig.customCss option.

@Josh-Cena Josh-Cena changed the title fix(core): load client modules before mounting React components fix(core): correctly order CSS imports Nov 22, 2021
@Josh-Cena Josh-Cena added the status: don't merge yet This PR is completed, but we are still waiting for other things to be ready. label Nov 22, 2021
@Josh-Cena
Copy link
Collaborator Author

Josh-Cena commented Nov 23, 2021

@slorber I understand your concern, but I still want to get the fix somewhat done correctly. What about this:

Instead of putting the import at the very top and risk reordering all CSS:

+ import './client-lifecycles-dispatcher';

import React from 'react';

import routes from '@generated/routes';
import renderRoutes from './exports/renderRoutes';
import {BrowserContextProvider} from './exports/browserContext';
import {DocusaurusContextProvider} from './exports/docusaurusContext';
import ErrorBoundary from '@docusaurus/ErrorBoundary';
import PendingNavigation from './PendingNavigation';
import BaseUrlIssueBanner from './baseUrlIssueBanner/BaseUrlIssueBanner';
import Root from '@theme/Root';
import Error from '@theme/Error';

- import './client-lifecycles-dispatcher';

We pretend that #3104 was actually done by putting all imports last:

import React from 'react';

import routes from '@generated/routes';
import renderRoutes from './exports/renderRoutes';
import {BrowserContextProvider} from './exports/browserContext';
import {DocusaurusContextProvider} from './exports/docusaurusContext';
import PendingNavigation from './PendingNavigation';
import BaseUrlIssueBanner from './baseUrlIssueBanner/BaseUrlIssueBanner';
import Root from '@theme/Root';

import './client-lifecycles-dispatcher';

+ import ErrorBoundary from '@docusaurus/ErrorBoundary';
+ import Error from '@theme/Error';

We leave all the other imports untouched. This would still fix the issues, and had #3104 not landed, the behavior would be identical in every way to the current behavior. Does that look sensible as a better temporary fix than just removing the app-level error boundary? Now that we do know what's wrong, I feel we deserve a better fix.

I would send another PR and you can merge that one if you think the fix described above makes sense. We would keep this one to actually fix the issue from its root.

@lex111
Copy link
Contributor

lex111 commented Nov 23, 2021

I'm fine with the current change of imports order. After all, this will lead back to the previous of CSS ordering, where infima/admonitions styles came first, then custom CSS files, and finally built-in Docusaurus components styles (which currently cannot be simply overridden without using !important rule). So there shouldn't be any breaking change in my understanding.

To reproduce #3678, try overriding built-in docusaurus-mt-lg class in any custom CSS, without using !important this is currently not possible.

@Josh-Cena
Copy link
Collaborator Author

So there shouldn't be any breaking change in my understanding.

I understand Sebastien's concern. While he's probably being more speculative than we are, the moment we assert there's no breaking change with the addition of in my understanding / I believe it means we can't be sure yet, and that can be very problematic.

In practice, although we are probably moving ourselves towards the correct side, we never know what kinds of convoluted setups there are in the wild. Maybe they relied on some (terrible) hacks that only work with our previous import order and this change breaks their website.

Mandatory XKCD for the day though, for this kind of fear:

I do assert that either fix is safe, no matter where we put the client modules import, as long as it stays above the error boundary import, because these are the only two imports with side-effects.

Copy link
Collaborator

@slorber slorber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That change seems reasonable to me.

We already have a stylesheets API to easily override global CSS. I guess CSS is added after infima + CSS modules? https://docusaurus.io/docs/api/docusaurus-config#stylesheets

Also, should we keep theme.customCss, deprecate it, or change its behavior? with this change, customCss CSS will be loaded earlier than before (before theme CSS modules), which means that some unexpected CSS might become applied to user sites while it was not the case before 🤷‍♂️ . This may not impact us, but it may impact other highly customized websites like React-Native.

And yes, all this is Hyrum's law (https://www.hyrumslaw.com/) in practice: current users depend on our legacy wrong behavior. Some users may suffer from this change and we should aim to reduce their pain, by ensuring a well-defined order once for all with automated tests.

What I suggest:

PR 1:

  • Revert the error boundary in core to ensure we revert the CSS order issues to the former state (temporary)
  • Dogfood usage of stylesheets on our own website and theme.customCSS on our own website, eventually add things like "marker CSS classes" that we can easily monitor like .test-css-module {} or .test-stylesheets {} or .test-custom-css {}
  • Monitor CSS diff changes in our own website (inspired by refactor: replace dist in git by diff comment facebookincubator/infima#152?)
  • Eventually add an automated test to ensure marker CSS classes are in a correct order

PR 2:

  • Do this client modules import change
  • ensure that the monitored diff looks expected in terms of order, particularly that the marker CSS classes are in the correct order.
  • Publish canary from PR
  • Test on RN/Jest websites and see how painful it is for them to fix issues, create PRs that can help the community to migrate their CSS files

import React from 'react';
// Load this at the very top!
// client modules have to be loaded before anything else...
import './client-lifecycles-dispatcher';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you are right and we should do this change, it was probably historical.

But yeah, hard to reason about and see possible side-effects.

@Josh-Cena Josh-Cena marked this pull request as draft December 20, 2021 08:25
@Josh-Cena Josh-Cena removed the status: don't merge yet This PR is completed, but we are still waiting for other things to be ready. label Dec 20, 2021
@Josh-Cena
Copy link
Collaborator Author

Closing in favor of #6227

@Josh-Cena Josh-Cena closed this Dec 30, 2021
@Josh-Cena Josh-Cena deleted the jc/fix-client-modules branch March 6, 2022 10:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed Signed Facebook CLA pr: bug fix This PR fixes a bug in a past release.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Ensure proper and stable CSS insertion ordering
4 participants