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

[Bug]: story rendering order influences the order of the CSS styles in the head #23990

Open
martinkutter opened this issue Aug 29, 2023 · 7 comments

Comments

@martinkutter
Copy link

Describe the bug

As discovered some years ago in #13515 the name of the story defines in which order the imported styles from the component are added to the head. So if I change the name of a story, or delete the story, or force a rerender the look of a component could change.

To Reproduce

https://stackblitz.com/edit/github-64tjnp

image

AHeader imports header.module.scss so it is added first in the head.
ZHeader imports header.module.scss again, but it's already in the head.
As a result, the button turns green because button.modules.scss is added to the head after header.module.scss.
image

If I simply resize the window, the order changes and the button turns red.
Kapture 2023-08-29 at 15 53 09

System

No response

Additional context

No response

@dcop
Copy link

dcop commented Oct 25, 2023

This is happening to me also on 7.5.1, but the weird thing is that in dev mode everything works fine, while building and serving is breaking the CSS order. I'm also using CSS modules and my main (css) theme is loaded in the provider that I then use in the preview file with withThemeFromJSXProvider.

@lztetreault-dev
Copy link

Also having this issue on 7.5.2, this seems like it should be a high priority bug. It defeats the point of developing in isolation if your component doesn't look the same as it will in your application.

@hendrikheil
Copy link

We're on v8.0.0-rc.3 and are encountering the a very similar issue using vite builder. In dev mode the order of the styles is inserted as expected, preview.ts imported (vendor) styles are first, while component or story styles are imported later.

In built-mode, we get the opposite, where preview styles are always last. This causes specificity issues for us in Chromatic snapshots.

Even if we explicitly set cssCodeSplit: false the resulting file still has an order we don't expect. We also tried naming the components / stories alphabetically by prefixing them with Z (so they are after p of preview). Nothing worked so far.

I'm not sure if this is a problem in storybook or vite. But it is causing results we don't expect.

We could fix it by using CSS layers, however Layers don't have enough browser support for us yet, so this isn't a good solution for us.

@tmeasday
Copy link
Member

I'm not an expert on CSS modules, but in my experience, if you see different rendering behaviour when you access stories/components in a different order, you'll see the same issue in your actual code depending on the order you import those components in your source code. That import order is often driven by the order you visit routes in your app and can be super tricky to track down.

That seems to me to be a bug that you want to fix in your code and will be much easier to debug in SB 🤷

In the example repro posted (thank you!) I can't quite get the CRA app running in StackBlitz but I downloaded it and added this to the index.tsx to simulate the behaviour of a router that does dynamic imports (e.g like NextJS):

import React from 'react';
import ReactDOM from 'react-dom/client';

const ZHeader = React.lazy(async () => ({ default: (await import('./stories/zHeader')).ZHeader }));
const AHeader = React.lazy(async () => ({ default: (await import('./stories/aHeader')).AHeader }));
const Router = () => {
  if (document.location.search.indexOf('foo') !== -1) {
    return (
      <>
        <AHeader />
        <ZHeader />
      </>
    );
  }

  return <ZHeader />;
};

const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
  <React.StrictMode>
    <Router />
  </React.StrictMode>
);

You can quite clearly see the same behaviour where the ZHeader renders green at /?foo and red at /:

image
image

@hendrikheil
Copy link

So while we were working on an unrelated improvement for bundle size optimizations, we changed our upstream library to import each CSS module at the top of every ESM module we emit. This required quite a bit of tinkering with Vite, as it - by default - bundles all CSS and JS into two bundle files in Lib mode, which makes it a lot harder to tree-shake, but doesn't require processing by downstream bundlers.

By making that change, we now only rely on our global styles to provide certain reused design system tokens (as custom properties in :root), but that doesn't depend on any order in our stylesheets.

So for us, these changes made the regression go away, but I still believe storybook should behave the same way in dev and built mode - which it doesn't right now.

@tmeasday
Copy link
Member

So for us, these changes made the regression go away, but I still believe storybook should behave the same way in dev and built mode - which it doesn't right now.

Yes, this is a fair point. Do we have any idea of why it behaves differently? In the reproduction @martinkutter posted it broke in dev mode.

@hendrikheil
Copy link

Not sure really. I did see this issue upstream in vite: vitejs/vite#3924 which might be related. I'm not sure where the root cause is really. I think it'd be interesting to see if the webpack builder exhibits the same behavior as the vite one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants