question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

auto-labelling styled() with css() class: classname differs between browser and server

See original GitHub issue

Current behavior:

I’m experiencing a difference between the generated classnames server-side (cjs) and client-side (esm.js) using Emotion v11, @emotion/react, @emotion/styled, @emotion/babel-plugin with sourceMap set to always (or dev-only) and webpack.

broadly speaking this is what triggers it:

// file.js

import React from 'react';
import styled from "@emotion/styled";
/** @jsx jsx */
import { jsx, css } from "@emotion/react";
 
const someColor = 'red';

const typ = css`
 font-size: 20px;
 color: ${someColor};
 line-height: 1;
`

const Text =  styled.p`
 margin: 5px;
`

export default () => (<Text css={[typ]}>hello</Text>)

… which renders a <Text> with a classname of ...-Text-typ-typ ... on the client and ...-Text-typ ... on the server, and then it complains about a className mismatch.

when i examine the arguments to the style serializer, i can see that the css() argument has been split in four parts, for interpolation:

  • font-size: 20px; color:
  • red
  • ;line-height: 1;label:typ;/*...
  • ;label:typ;/*# sourceMappingURL=data:

If I interpolate more times however, the -typ- part is not included more times, just the ;-s in the style string generated increase in number. if I disable auto labelling, the problem goes away. if I remove the interpolation part, it comes up with the correct class name. It fails in both Chrome and Safari. Works on the server (Node16). The source maps setting doesn’t change anything.

I tried recreating this in the v10 sandbox and was unable to. I have checked that serializeStyles is only called once.

I’m sorry i couldn’t provide a more reproducible example. 😐

Expected behavior:

In the generated className with a label, to see typ only once, not twice.

Environment information:

  • react: 16.14.0
  • @emotion/react: 11.7.1
  • @emotion/styled: 11.6.0
  • @emotion/babel-plugin: 11.7.2

Any pointers welcome, including where i can place breakpoints or logging in the dist/ modules to check things and navigate further?

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:1
  • Comments:10 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
gmarinovcommented, Jan 25, 2022

hi. thanks for the effort, @srmagura .

I think mylabel-typ-mylabel-typ is unexpected there and that you’re seeing it doubled but not mismatched points me in the direction of sourcemaps. edit: it’s specified twice in your example, so it’s expected, but I’m seeing it 4 times unless I switch sourceMaps off.

SSR is a custom set up - Node 16 + webpack + extractCritical, render into an HTML view (Handlebars). That is then sent to the client to hydrate.

I tested in Safari and Chrome - both exhibited the problem.

The versions I use are the latest around Webpack 4 (including latest Webpack):

@babel/core: 7.16.12 @babel/cli: 7.16.8

Strangely, not every class is duplicated like that - I definitely end up with at least one that is duplicated, but as I change my React tree, which one exactly ends up being different.

I’ll keep bashing it a little longer, before I try to put together a minimal repro. (🤞)

below is my .babelrc

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "browsers": [
            ">0.5%"
          ]
        },
        "debug": false,
        "modules": false,
        "corejs": 3.6,
        "useBuiltIns": "usage"
      }
    ],
    "@babel/preset-react"
  ],
  "plugins": [
    ["@emotion/babel-plugin", {
      "autoLabel": "always",
      "labelFormat": "[local]",
      "sourceMap": false
    }],
    "@babel/plugin-proposal-object-rest-spread",
    "@babel/plugin-syntax-dynamic-import"
  ],
  "env": {
    "test": {
      "presets": [
        [
          "@babel/preset-env",
          {
            "modules": "commonjs"
          }
        ]
      ]
    }
  }
}
0reactions
gmarinovcommented, Jan 30, 2022

eventually I solved my issue by removing Emotion and moving to css-loader modules

Read more comments on GitHub >

github_iconTop Results From Across the Web

auto-labelling with class components differs between browser ...
Expected behavior: In the generated className with a label css-sz5maj-bulletInnerCss-visibleInnerCss-SectionBullets on server and client.
Read more >
Advanced Usage - styled-components
This function will receive the parent theme, that is from another <ThemeProvider> higher up the tree. This way themes themselves can be made...
Read more >
Warning: Prop `className` did not match. when using styled ...
That error is showing you the class that is being created by your styled-components library on the server and how it is different...
Read more >
Styled-components vs. Emotion for handling CSS
Explore the benefits, drawbacks, and differences between two CSS-in-JS libraries: styled-components and Emotion-JS.
Read more >
Demystifying styled-components - Josh W Comeau
We come up with a unique class name by hashing styles into a seemingly-random ... Can we really generate new CSS classes from...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found