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: Styled-components are unstyled using React Server Components (the component contains all the necessary props) #23126

Closed
Thisisjuke opened this issue Jan 16, 2022 · 4 comments
Labels
Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug

Comments

@Thisisjuke
Copy link

Thisisjuke commented Jan 16, 2022

Context

Its seems that React Server Components do not Support CSS-in-JS at the moment.

Related to an issue in the Hydrogen Framework by Shopify : Shopify/hydrogen#398

Describe the bug
Hello, it seems I have encountered a bug using styled-components from external library.

  • Inside the demo of React Server Components:

The basic setup from the React Server Components can't compile, because of the package extension (see spoiler with full log below). This error seems weird :

Instead rename taggedTemplateLiteral.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /home/[...]/hydrogen-styled-components-error/apps/react-server-components-app/node_modules/@babel/runtime/helpers/esm/package.json.
  • Inside the default repo of Hydrogen App (see more in original issue):

Once the component is loaded in front-end, it's not flagged as "component" in react dev tools (other Hydrogen elements are) and has no CSS applied.

To Reproduce

Reproduction Repository

  1. Create a styled component like this one :
export const TestButton = styled.button`
  background: red;
  ${props => props.primary && css`
    color: blue;
  `}
`
  1. Build it with ES / UMD (using viteJS or rollup). The compiled version looks like this:
const en=Qr.button.withConfig({displayName:"TestButton",componentId:"sc-levoo9-0"})((({variant:e="primary"})=>[{"--tw-bg-opacity":"1",backgroundColor:"rgba(239, 68, 68, var(--tw-bg-opacity))"},e==="primary"&&{"--tw-text-opacity":"1",color:"rgba(59, 130, 246, var(--tw-text-opacity))"}]));export{en as TestButton};
  1. Add it to your application using yarn : yarn workspace react-server-components-app add @test/ui
  2. Import the component in your App : <TestButton>Yo !</TestButton>
  3. Launch your application => Impossible to compile

Expected behaviour
The site should compile and the button should have CSS props and shoudn't be unstyled.

Logs

Inside React Server Components application with button : error starting with yarn start-rsc
internal/modules/cjs/loader.js:1102
    throw new ERR_REQUIRE_ESM(filename, parentPath, packageJsonPath);
    ^

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /home/[...]/hydrogen-styled-components-error/apps/react-server-components-app/node_modules/@babel/runtime/helpers/esm/taggedTemplateLiteral.js
require() of ES modules is not supported.
require() of /home/[...]/hydrogen-styled-components-error/apps/react-server-components-app/node_modules/@babel/runtime/helpers/esm/taggedTemplateLiteral.js from /home/[...]/hydrogen-styled-components-error/libs/ui/dist/ui.umd.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename taggedTemplateLiteral.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /home/[...]/hydrogen-styled-components-error/apps/react-server-components-app/node_modules/@babel/runtime/helpers/esm/package.json.

  at new NodeError (internal/errors.js:322:7)
  at Module._extensions..js (internal/modules/cjs/loader.js:1102:13)
  at Object.newLoader [as .js] (/home/[...]/hydrogen-styled-components-error/node_modules/pirates/lib/index.js:141:7)
  at Module.load (internal/modules/cjs/loader.js:950:32)
  at Function.Module._load (internal/modules/cjs/loader.js:790:12)
  at Module.require (internal/modules/cjs/loader.js:974:19)
  at require (internal/modules/cjs/helpers.js:93:18)
  at Object.<anonymous> (/home/[...]/hydrogen-styled-components-error/libs/ui/dist/ui.umd.js:5:54)
  at Module._compile (internal/modules/cjs/loader.js:1085:14)
  at Module._compile (/home/[...]/hydrogen-styled-components-error/node_modules/pirates/lib/index.js:136:24) {
code: 'ERR_REQUIRE_ESM'
}
Inside hydrogen app : console.log(TestButton.componentStyle.rules[0]({variant: 'primary'}))
[
{
  transform: 'var(--tw-transform)',
  paddingLeft: '2rem',
  paddingRight: '2rem',
  paddingTop: '0.5rem',
  paddingBottom: '0.5rem',
  borderRadius: '0.25rem',
  ':focus': { outline: '2px solid transparent', outlineOffset: '2px' },
  transitionDuration: '75ms'
},
{
  ':hover, :focus': {
    '--tw-scale-x': '1.05',
    '--tw-scale-y': '1.05',
    transform: 'var(--tw-transform)',
    '--tw-text-opacity': '1',
    color: 'rgba(251, 191, 36, var(--tw-text-opacity))'
  }
},
{
  '--tw-bg-opacity': '1',
  backgroundColor: 'rgba(0, 0, 0, var(--tw-bg-opacity))',
  '--tw-text-opacity': '1',
  color: 'rgba(255, 255, 255, var(--tw-text-opacity))',
  '--tw-border-opacity': '1',
  borderColor: 'rgba(0, 0, 0, var(--tw-border-opacity))'
},
false,
{ fontSize: '0.875rem', lineHeight: '1.25rem' },
[ '\n    color: ', '#fff', ';\n  ', isCss: true ]
]

Additional context
In the reproduction repo, the same component from same build is used in:

  • React Server Component app : application can't compile
  • Hydrogen App : component is unstyled
  • create-react-app : component is styled
  • react with viteJS as bundler : component is styled

Versions & System

  • Node version : v14.18.1
  • Device details :
    OS: Linux 5.4 Ubuntu 20.04.3 LTS (Focal Fossa)
    CPU: (12) x64 Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
    Memory: 393.64 MB / 15.32 GB
    Container: Yes
    Shell: 5.8 - /usr/bin/zsh

Thx for your time !

@Thisisjuke Thisisjuke added the Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug label Jan 16, 2022
@Thisisjuke
Copy link
Author

Thisisjuke commented Apr 11, 2022

Updated dependencies of the reproduction repo to React 18.

@gaearon
Copy link
Collaborator

gaearon commented Apr 11, 2022

I don't think there is a bug in React here. styled-components would need to add support for Server Components — I don't think it's expected to "just work" with the current approach. It would be good to file an issue in the styled-components repo for this discussion. I think the React 18 streaming guides like reactwg/react-18#110 and reactwg/react-18#108 might be good starting points, though I think Server Components will probably require something additional to that. I'll need to check with the team to answer this. Regardless, there is no bug in React related to this.

@gaearon gaearon closed this as completed Apr 11, 2022
@penx
Copy link

penx commented Nov 3, 2022

With regard to the react-server-components error (but unrelated to the Hydrogen one), this is due to an issue with the Babel config in the demo apps.

Inside react-server-components-app you have

const register = require('react-server-dom-webpack/node-register');
register();
const babelRegister = require('@babel/register');

babelRegister({
  ignore: [/[\\\/](build|server|node_modules)[\\\/]/],
  presets: [['react-app', {runtime: 'automatic'}]],
  plugins: ['@babel/transform-modules-commonjs'],
});

This is the same setup as @gaearon 's SSR demo at https://codesandbox.io/s/kind-sammet-j56ro and also the server-components-demo.

Unfortunately the babel config on both of these apps is pretty flakey:

e.g. if you open https://codesandbox.io/s/kind-sammet-j56ro and change App.js to have the following:

export default function App({ assets, test = ["a", "b"] }) {
  const [a, b] = test;
  console.log(a, b);

You will see:

https://github.com/browserslist/browserslist#browsers-data-updating
internal/modules/cjs/loader.js:1102
      throw new ERR_REQUIRE_ESM(filename, parentPath, packageJsonPath);
      ^
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /sandbox/node_modules/@babel/runtime/helpers/esm/slicedToArray.js

This means babel can't process const [thing, setThing] = useState() with this setup, which is pretty fundamental to React :)

I guess a different babel config is needed here, rather than just the react-app preset plus @babel/transform-modules-commonjs.

I can't find much else referencing this issue, I'll try remember to post back here if I find any solution.

@gaearon if you've made any demos since then that improves this setup, please let me know :)

@penx
Copy link

penx commented Nov 3, 2022

I was able to modify the babel config to load commonjs modules on the server, details in this PR:

reactjs/server-components-demo#61

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug
Projects
None yet
Development

No branches or pull requests

3 participants