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

Missing styles in production (CRA + Emotion 11) #2209

Closed
green-arrow opened this issue Jan 11, 2021 · 15 comments
Closed

Missing styles in production (CRA + Emotion 11) #2209

green-arrow opened this issue Jan 11, 2021 · 15 comments

Comments

@green-arrow
Copy link

Current behavior:

Successfully updated codebase to emotion 11 (from 9) and using the css prop in conjunction with craco to override the webpack config and use the @emotion/babel-preset-css-prop preset. When running locally in development, all styles are applied properly and everything looks good. When building for production however, it seems like there are styles missing throughout the app.

To reproduce:

I don't have a repro case as this is in app, I'm hoping I've just missed a step or something else obvious.

Environment information:

  • react version: 17.0.1
  • @emotion/react version: 11.1.4
@green-arrow
Copy link
Author

green-arrow commented Jan 11, 2021

To give an example, this image shows elements with generated CSS class names, but nothing showing up in the debugger and the style tags for emotion in the head are empty. Although there are some styles throughout that seem to get applied and appear and the debugger, and those point to the empty style tags in the head.

image

I sincerely appreciate any assistance :)

@tyom
Copy link

tyom commented Jan 13, 2021

Are you using CacheProvider from @emotion/react? In my case, the use of CacheProvider (for custom AMP implementation in Next.js) disabled the automatic SSR injection of Emotion style blocks. Removing CacheProvider wrapper for WWW renders fixed the issue.

@green-arrow
Copy link
Author

@tyom - no, I’m not currently using CacheProvider. Just css from @emotion/react, with a single usage from vanilla @emotion/css for a special use case.

@Andarist
Copy link
Member

It looks like if you would load more than one instance of Emotion - the other one touching style elements if the first ine and thjs them losing injected styles. From what I remember those elements dont lose styles in FireFox - if this works for u in FF it would validate my diagnosis. Could u check this?

@green-arrow
Copy link
Author

green-arrow commented Jan 13, 2021

@Andarist - unfortunately I get the same issue in firefox.

Something I noticed though is that the styles for our header seem to be applied initially for about a second, and then everything goes missing. We do use code-splitting, and this could be correlated but not the cause, but it seems like when bundle for the first page loads in (after the shell loads in), that's when the styles seem to break / get removed. Not sure if it would be possible for the "multiple instances of emotion" to get loaded in that way.

@green-arrow
Copy link
Author

@Andarist - it looks like you are right with the multiple versions. I can't believe I didn't try this before, but I removed the one use of import { css as vanillaCss } from '@emotion/css'; from the codebase (which is on that initial page that gets loaded I mentioned), and it's back to working.

I guess my question now becomes, is there any easy way to safely use @emotion/css alongside @emotion/react?

@Andarist
Copy link
Member

I guess my question now becomes, is there any easy way to safely use @emotion/css alongside @emotion/react?

Yes. The exact thing I was suspecting is multiple instances of the @emotion/cache module - @emotion/css & @emotion/react shares that dependency. It's hard to tell what exactly has been wrong without inspecting a repro case. If the version of that @emotion/cache will be the same then there shouldn't be any problem.

@green-arrow
Copy link
Author

Checking out my yarn.lock file, it seems that both @emotion/css and @emotion/react both have version 11.1.3 as their @emotion/cache dependency. There is another instance of @emotion/cache that is used by storybook, but I don't think that should interfere here.

@Andarist
Copy link
Member

It kinda depends on your node_modules layout but I would expect issues to arise when using Storybook and not in your production code.

Either way - can't pinpoint it to the very exact problem if I can't investigate the repro case

@johncburnette
Copy link

johncburnette commented Jan 16, 2021

Seeing this when upgrading from 10.x.x to 11 as well in my production code, but we're using preact and the standalone(?) version of emotion (emotion -> @emotion/core when we upgraded to 11). I'm working to get together an example of this currently but my scenario is that my company provides a javascript bundle that behaves as a widget. If our javascript file is loaded twice sometimes some of the css classes do not get added to the DOM as a style element. It only appears to be one class for me and my emotion style looks like the following:

import { cx, css } from '@emotion/css';

const widgetItemWrapperStyle = (width, columns, gutter) => css`
  width: ${Math.floor((width / columns)) - gutter)}px;
`;

// context provider for holding data for widget
const widgetContext = useContext(context);
const { width, columns, gutter } = widgetContext;

<div className={cx(widgetItemWrapperStyle(width, columns, gutter), 'arbitrary class for friendly selection`)}>
  // markup for widget here
</div>

We're currently using emotion 10.0.27 and attempted to move to @emotion/core version 11.1.3

@Andarist
Copy link
Member

I believe that you have meant @emotion/css and not @emotion/core. Putting that aside - in such context you most definitely should use @emotion/css/create-instance. It still might not fix your whole problem though - I have some things in mind that I think could affect you but I'd really need to get a repro case of the problem to evaluate this further.

@shobhitsharma
Copy link

shobhitsharma commented Jan 28, 2021

UPDATE: Below code worked for me, after I fixed babel stuff with plugins for transformation.

I ran into same issue. I am able to resolve with custom code, but compiler of storybook instance is not parsing certain import statement correctly so it throws errors for some stories.

What I did?

$ cd .storybook
$ touch babel.config.js

babel.config.js

module.exports = {
  extends: '../../../babel.config.js',
  presets: [
    '@babel/preset-typescript',
    [
      '@babel/preset-react',
      {
        runtime: 'automatic',
        importSource: '@emotion/react',
      },
    ],
  ],
  plugins: [
    [
      '@emotion',
      {
        sourceMap: true,
        autoLabel: 'always',
        labelFormat: '[local]',
        cssPropOptimization: true,
      },
    ],
  ],
};

Then, in .storybook/main.ts

import { resolve } from 'path';
import webpack from 'webpack';

/**
 * Map Emotion 10 libraries to Emotion 11 libraries.
 * This function makes a shallow copy of an object, rejecting keys that match /emotion/
 *
 * Otherwise Storybook fails to compile with "Module not found: Error: Can't resolve '@emotion/styled/base'", etc.
 * It wasn't necessary to do this until we imported React component using "@emotion/styled".
 * This issue is probably caused because Storybook uses Emotion 10 while we have Emotion 11 used by the Next.js app.
 *
 * @see https://github.com/storybookjs/storybook/issues/13277#issuecomment-751747964
 * @see https://github.com/storybookjs/storybook/issues/12262#issuecomment-681953346
 * @see https://emotion.sh/docs/emotion-11#package-renaming
 */
function emotionless<T extends Record<string, unknown>>(object: T) {
  let result = {} as T;
  for (let key in object) {
    if (!/emotion/.test(key)) {
      result[key] = object[key];
    }
  }
  return result;
}

export default {
  stories: ['../src/**/*.story.@(tsx|mdx)'],
  addons: ['@storybook/addon-docs', '@storybook/addon-actions', '@storybook/addon-a11y'],
  babel: (config: any) => {
    config.plugins = config.plugins.map((plugin: any) => {
      if (/emotion/.test(plugin[0])) {
        return [
          require('@emotion/babel-plugin'),
          {
            sourceMap: true,
            autoLabel: 'always',
            labelFormat: '[local]',
            cssPropOptimization: true,
          },
        ];
      }
      return plugin;
    });
    return config;
  },
  webpackFinal: async (config: { [key: string]: any }) => {
    if (config.resolve.plugins) {
      config.resolve.plugins.push(...alias.plugins);
    } else {
      config.resolve.plugins = alias.plugins;
    }

    config.devtool = isProductionEnv ? false : 'cheap-module-source-map';

    return {
      ...config,
      resolve: {
        ...config.resolve,
        alias: {
          ...emotionless(config.resolve.alias),
        },
      },
    };
  },
};

This https://emotion.sh/docs/@emotion/babel-preset-css-prop plugin loads everything without error but some styles are missing. Storybook is mess right now, had also issues with webpack v4-v5 and still not resolve. If anyone get around with it, let me know. Otherwise just have to wait til storybook bump emotion to v11.

@NicholasBoll
Copy link

Does #2361 fix this issue?

@filipesmedeiros
Copy link

And if so, has it been released yet?

@Andarist
Copy link
Member

Andarist commented May 7, 2021

Does #2361 fix this issue?

Hopefully - yes. The repro case for this problem has not been given so I can't say for sure. I have to assume that this has been fixed - if not, please open a new issue with the repro case.

And if so, has it been released yet?

Yes, this has been released in the last 24h.

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