next.js: Next.js 13: SWC Emotion Transform Plugin Breaks with root layout Server Component in `app/`
Verify canary release
- I verified that the issue exists in the latest Next.js canary release
Provide environment information
Operating System:
Platform: linux
Arch: x64
Version: Ubuntu 20.04.0 LTS Thu Oct 27 2022 20:19:36 GMT+0200 (Central European Summer Time)
Binaries:
Node: 16.14.2
npm: 7.17.0
Yarn: 1.22.19
pnpm: 7.13.6
Relevant packages:
next: 13.0.1-canary.0
eslint-config-next: N/A
react: 18.2.0
react-dom: 18.2.0
What browser are you using? (if relevant)
No response
How are you deploying your application? (if relevant)
No response
Describe the Bug
Using the compiler: { emotion: true }
option is throwing an error about React.createContext
not being a function:
event - compiled client and server successfully in 59 ms (403 modules)
error - (sc_server)/node_modules/@emotion/react/dist/emotion-element-b63ca7c6.cjs.dev.js (20:47) @ eval
error - TypeError: React.createContext is not a function
at eval (webpack-internal:///(sc_server)/./node_modules/@emotion/react/dist/emotion-element-b63ca7c6.cjs.dev.js:19:49)
at (sc_server)/./node_modules/@emotion/react/dist/emotion-element-b63ca7c6.cjs.dev.js (/home/projects/vercel-next-js-mxnxa7/.next/server/app/page.js:501:1)
at __webpack_require__ (/home/projects/vercel-next-js-mxnxa7/.next/server/webpack-runtime.js:33:43)
at eval (webpack-internal:///(sc_server)/./node_modules/@emotion/react/jsx-dev-runtime/dist/emotion-react-jsx-dev-runtime.cjs.dev.js:7:22)
at (sc_server)/./node_modules/@emotion/react/jsx-dev-runtime/dist/emotion-react-jsx-dev-runtime.cjs.dev.js (/home/projects/vercel-next-js-mxnxa7/.next/server/app/page.js:512:1)
at __webpack_require__ (/home/projects/vercel-next-js-mxnxa7/.next/server/webpack-runtime.js:33:43)
at eval (webpack-internal:///(sc_server)/./app/layout.tsx:5:88)
at (sc_server)/./app/layout.tsx (/home/projects/vercel-next-js-mxnxa7/.next/server/app/page.js:403:1)
at __webpack_require__ (/home/projects/vercel-next-js-mxnxa7/.next/server/webpack-runtime.js:33:43)
at Object.layout (webpack-internal:///(sc_server)/./node_modules/next/dist/build/webpack/loaders/next-app-loader.js?name=app%2Fpage&appPaths=%2Fpage&pagePath=private-next-app-dir%2Fpage.tsx&appDir=%2Fhome%2Fprojects%2Fvercel-next-js-mxnxa7%2Fapp&pageExtensions=tsx&pageExtensions=ts&pageExtensions=jsx&pageExtensions=js&rootDir=%2Fhome%2Fprojects%2Fvercel-next-js-mxnxa7&isDev=true&tsconfigPath=tsconfig.json!:22:99) {
type: 'TypeError',
page: '/'
}
null
Making the root layout component into a client component does work, but this would be unfortunate:
Workaround:
Disable the SWC Emotion transform plugin and use the /** @jsxImportSource @emotion/react */
directive instead:
Expected Behavior
It works to use the SWC Emotion transform plugin via compiler: { emotion: true }
with a server component as the root layout
Link to reproduction
To Reproduce
- Install
next@13.0.1-canary.0
,@emotion/cache@11.10.5
,@emotion/react@11.10.5
- Enable the
app/
dir and the SWC Emotion Transform plugin usingcompiler: { emotion: true }, experimental: { appDir: true }
innext.config.js
- Add the files as mentioned in @mitchellhamilton’s post here: https://github.com/emotion-js/emotion/issues/2928#issuecomment-1293012737
- Remove the
/** @jsxImportSource @emotion/react */
directive to rely on the SWC Emotion transform plugin to addcss
prop support - Start the server and observe the error
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 63
- Comments: 39 (6 by maintainers)
In the same way, I experience the same problem with @mui, which uses emotion under the hood.
Yep I’m stuck too. I can`t fully migrate to v13 and adopt it because the project depends on MUI
Issues with different libraries workaround
Workaround
My workaround was creating my own custom wrapper for the providers with “use client” like this:
Custom Wrapper
Wrapper.tsx
Then wrapping the children in
layout.tsx
like this:Not sure if this is optimal, but it works for now.
if anyone is using some sort of wrapper make sure to define “use client” in frist line of script of wrapper. anything that has useSomthing in it must be in script that start with “use client”
I have the same problem with React-redux. When trying to wrap
{children}
with astore
Provider:TypeError: (0 , _react.createContext) is not a function
Call Stack
Ditto. mui5, which depends on emotion breaks with
TypeError: React.createContext is not a function
when attempting to wrap app layout with theme context provider.Add
/** @jsxImportSource react */
to your layouts, and"use client"
to your pages and components.Adding
/** @jsxImportSource react */
to the top of the root layout makes{ compiler: { emotion: true } }
work.Seems to be working for me with MUI:
Repo: https://github.com/mwskwong/resume/commit/f4092af87989e6c56b4bd20e9ad518d482a060ec Live build: https://resume-82bwpwy6q-mwskwong.vercel.app
Thanks for the fix in #54284 @huozhi 🙌
Once this is released in the next canary version, can someone from this thread who uses Emotion check the new version and provide some proof that it’s working in your app? Make sure to install
next@13.4.20-canary.0
(once this version is released).cc @Zagorodnyi @dzcpy @dan-turner @Systemcluster @magnuen2k if you could test as mentioned above, that would be great!
@magnuen2k I believe we should finally avoid
'use client'
since we shouldn’t need a client module in this case.As far as I recall, the doc mentioned at this moment Emotion doesn’t work with
app/
at all, isn’t it?I’ve tried everything. This is so cursed
guys. @karlhorky tried to explain multiple times - this issue is about the compiler option in
next.config.js
AFTER you work around the basic emotion or MUI setup using"use client"
directives forCacheProvider
and all the components that will use emotion. If you comment out theemotion: true
line innext.config.js
in his StackBlitz (https://stackblitz.com/edit/vercel-next-js-nlknru?file=next.config.js), the app doesn’t throw, but also it doesn’t work (the rendered text isn’t green). You currently need another workaround because of this, as shown in the second @karlhorky’s StackBlitz (https://stackblitz.com/edit/vercel-next-js-ajvkxp?file=app/page.tsx) - put/** @jsxImportSource @emotion/react */
on top ofpage.tsx
.Overall, is it valid to say that MUI does not work with Nextjs v13?
I am using a vanilla Next 13.0.0 config created using
npx create-next-app@latest --typescript
, and the only changes are 1) settingexperimental.appDir
totrue
, and 2) addition oflayout.tsx
with MUI v5 Box component added, plus a no-op page.tsx. Result in same exact error as op posted.edit: here are project deps – just noticed added some add’l modules in anticipation of using, but hit wall early with above issues (or different having same symptom), so extra modules unused).
Maybe the people replying about different libraries here can also mention whether your reproduction uses SWC with
compiler: { emotion: true }
innext.config.js
(or maybe also look if your library configures this internally for you). And then edit your posts to include this information.If you are not using this config option, then actually your comments are not related to the subject of this issue.
Just want to expand on this / highlight it a little since this lowers the overhead quite a bit for people who DON’T want to disable
compile: { emotion: true }
(and/or the equivalent intsconfig
since that seems to throw the same issue)The vast majority of my files are going to be components that use
styled
or@mui
, so having my jsx source beemotion
is pretty important.As some commenters in this thread and the “workaround” thread have mentioned, you can specify
jsxImportSource
on a file-by-file basis, though most people seem to be doing that to enable emotion specifically on their'use client'
files; by not specifying the emotion compiler innext.config.js
you’re falling back to regular react for jsx which does work with server components and avoids all the errors people are posting above.What @Systemcluster posted helped me realize that the opposite was true as well; I could leave my compiler settings intact so that my ~99% of files that are using MUI or some custom styled component only need
'use client'
(which was always going to be the case inapp
directory world, at least for now) since they’ll be using the emotion compiler by default, but if I have something I know could be a server component I can just specify/** @jsxImportSource react */
explicitly in that file, which will override the compile setting (they mentioned the root layout which is true, but afaict this should work anywhere in the tree).Following other advice here about weaving the client and server components together means that everything works the way I expected after just reading the next docs: I get root layouts that are server (with
metadata
support, which was actually what I cared about when I started looking into this) and my client children play nicely with them, with “minimum” file prefixing.@codyslex1a did you find any solution? I faced the same problem here…
@karlhorky are you saying there’s a correct way to make Next.JS v13 server components work with Emotion? Sorry new to this space
Edit: just noticed the workaround mentioned above. Will give it a try