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

Issues using emotion/styled with ES Modules #2730

Closed
maddijoyce opened this issue Apr 19, 2022 · 16 comments · Fixed by #2819 or #3029
Closed

Issues using emotion/styled with ES Modules #2730

maddijoyce opened this issue Apr 19, 2022 · 16 comments · Fixed by #2819 or #3029

Comments

@maddijoyce
Copy link

Current behavior:

When using import styled from "@emotion/styled", in a package setup to use esm, styled has a single key default

To reproduce:

  1. Clone https://github.com/maddijoyce/emotion-esm-issue
  2. Run npm test

Expected behavior:

As in the above example, using import styled from "@emotion/styled", styled should have styled.h1, styled.h2, etc

Environment information:

  • node version: 16.13.2
  • @emotion/styled version: 11.8.1

Some additional background:

Issue first discovered here - jestjs/jest#12571

@ocavue
Copy link

ocavue commented Jun 19, 2022

The exports filed in emotion's package.json is invalid for Node.js. Explanation: https://github.com/sheremet-va/dual-packaging

@ocavue
Copy link

ocavue commented Jul 31, 2022

@Andarist This issue is not resolved after #2819 (@emotion/[email protected]) and it should not be closed.

$ node --version
v18.6.0
$ npm --version
8.13.2
$ git clone https://github.com/maddijoyce/emotion-esm-issue
$ cd emotion-esm-issue
$ rm package-lock.json  # remove lock file so that npm can install the latest version
$ npm install 
$ npm list
[email protected] /private/tmp/emotion-esm-issue
└── @emotion/[email protected]
$ npm run test 
npm run test

> [email protected] test
> node index.js

[ 'default' ]
This should not be the case, this should be h1, h2, etc
So that we can do `styled.h1...`
Right now we would need to do `styled.default.h1...`

By adding some console.log under node_modules/@emotion/styled/dist/emotion-styled.esm.js and node_modules/@emotion/styled/dist/emotion-styled.cjs.js, you can see clearly that Node.js is still importing the CJS version of emotion. CommonJS doesn't include real default export, that's why we are seeing this error.

$ echo 'console.log("node_modules/@emotion/styled/dist/emotion-styled.cjs.js")' >> node_modules/@emotion/styled/dist/emotion-styled.cjs.js
$ echo 'console.log("node_modules/@emotion/styled/dist/emotion-styled.esm.js")' >> node_modules/@emotion/styled/dist/emotion-styled.esm.js
$ npm run test

> [email protected] test
> node index.js

node_modules/@emotion/styled/dist/emotion-styled.cjs.js
[ 'default' ]
This should not be the case, this should be h1, h2, etc
So that we can do `styled.h1...`
Right now we would need to do `styled.default.h1...`

As someone already mentioned, we need to use .mjs for esm build.

@Andarist Andarist reopened this Jul 31, 2022
@Andarist
Copy link
Member

Yes, you are right - my bad. This issue here won't be fixed soon though. The only viable strategy for us that would "fix" this would be switching to named exports.

@ocavue
Copy link

ocavue commented Jul 31, 2022

Switching (adding) named exports should be a practicable solution for now.

Eventually, I think it's better to fix this on the preconstruct side, by bundling .mjs files for ESM build. Maybe this would require a new major version of preconstruct, but it will resolve this issue for not only emotion but also other projects using preconstruct.

@wight554
Copy link

Switching (adding) named exports should be a practicable solution for now.

Eventually, I think it's better to fix this on the preconstruct side, by bundling .mjs files for ESM build. Maybe this would require a new major version of preconstruct, but it will resolve this issue for not only emotion but also other projects using preconstruct.

You're right, see #2819 (comment)

@Andarist
Copy link
Member

Andarist commented Aug 1, 2022

Switching (adding) named exports should be a practicable solution for now.

We'd be open to accepting a PR that would add a named export "alias" for all our default exports.

Eventually, I think it's better to fix this on the preconstruct side, by bundling .mjs files for ESM build. Maybe this would require a new major version of preconstruct, but it will resolve this issue for not only emotion but also other projects using preconstruct.

The problem is not on the preconstruct side here but instead in each project using it. Changing to .mjs or adding an import condition is not something that can be easily done within a minor version of a package. Even if releasing a major version would be an option - you still have to consider the compatibility with the rest of the ecosystem.

@mithodin
Copy link

mithodin commented Aug 4, 2022

I'm having the same issue with emotion/cache. Is there a workaround in the meantime?

@Andarist
Copy link
Member

Andarist commented Aug 4, 2022

The workaround is to do this:

import _createCache from '@emotion/cache'
const createCache = _createCache.default

@buzz
Copy link

buzz commented Sep 13, 2022

I'm having the same issue with emotion/cache. Is there a workaround in the meantime?

Another solution is to patch the package locally. See example for @reduxjs/toolkit.

Btw. pnpm has built-in support for patching packages.

@joaquinbentancor
Copy link

Hi, how could I fix the problem with .cjs file?

SyntaxError: The requested module '@emotion/react/jsx-runtime' is expected to be of type CommonJS, which does not support named exports. CommonJS modules can be imported by importing the default export. For example: import pkg from '@emotion/react/jsx-runtime'; const { jsx: _jsx } = pkg;

I'm having this issue.

@vtereshyn
Copy link

For those who are not using babel and don't want to wait for the full support of ESM there is a workaround that I tested in my codebase:

I use Typescript, so this is important for me that everything works properly and there are no type errors

import _styled from '@emotion/styled';
const styled = _styled.default || _styled;

@timofei-iatsenko
Copy link

timofei-iatsenko commented Dec 7, 2022

For those who came here trying to make work emotion-js + vite (which using ESM by default) here is solution:

import react from '@vitejs/plugin-react';
import { UserConfig } from 'vite';
import { cjsInterop } from 'vite-plugin-cjs-interop';


const config: UserConfig = {
  plugins: [
    cjsInterop({
      dependencies: [
        '@emotion/styled/base',
        '@emotion/*',
      ],
    }),
    react({
        jsxRuntime: 'automatic',
        jsxImportSource: '@emotion/react',
        babel: {
          plugins: [
            'babel-plugin-graphql-tag',
            'babel-plugin-macros',
            ['@emotion/babel-plugin', {}],
          ],
        },
      },
    ),
  ],
};

export default config;

The cjsInterop plugin is a crucial part, this plugin actually do what @vtereshyn wrote in the comment above

@bobaaaaa
Copy link

@thekip that helped me. thank you ❤️

@gauravbordoloi
Copy link

@thekip it helped me a lot. Thanks :)

@ssbarbee
Copy link

ssbarbee commented Nov 1, 2023

this is still not fully working even with latest emotion packages. What is the update here?

@Kikich47
Copy link

Hello
I had the same issue this week and I found a solution that work for me.
My context is a bit different. I'm building an custom library that put @emotion/style as a peerDependencies and I have a web site that will use this library. in runtime no problem, but with jest I got Type Error: emStyled is not a function

to manage it and force vite to use emStyled.default and not just emStyled I found interop in rollupOptions

I used it like that
interop: (id) => { if (id === '@emotion/styled') { return 'esModule'; } return 'default'; }

this work fine in this case

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