next.js
next.js copied to clipboard
Icomoon font will not be rendered with emotion enabled
Verify canary release
- [X] I verified that the issue exists in the latest Next.js canary release
Provide environment information
Operating System:
Platform: darwin
Arch: x64
Version: Darwin Kernel Version 21.6.0: Sat Jun 18 17:07:25 PDT 2022; root:xnu-8020.140.41~1/RELEASE_X86_64
Binaries:
Node: 14.15.0
npm: 7.11.1
Yarn: 1.22.18
pnpm: N/A
Relevant packages:
next: 12.3.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
Background
Since we switched to nextjs@12 we only got minified css classes on development for our @emotion styles.
The Problem
Now we tried to enable emotion with the compiler.emotion = true configuration. With that emotion works well except our icomoon font.
The icomoon font will be loaded and added to the styles... but not rendered. I'm not sure what the problem is exactly, for me all the things looks well.
Expected Behavior
Icons should be rendered as a font
Link to reproduction
https://github.com/dominikmatt/nextjs-emotion
To Reproduce
- Add emotion to your nextjs project
- Add a emotion component and define all the icons inside of it
- Enable emotion on next-configuration
const nextConfig = {
compiler: {
emotion: true, // Change to false to get the icon rendered
},
}
Taking a look at this.
It breaks because if compiler.emotion = true, the inline stylesheet in index.js is emitted with content: "\\e904" rather than content: "\e904". This is what it looks like in the original source in index.js. And no other escaping works in this template string.
So my guess is this is introduced at compile time by next-swc/crates/emotion, specifically here which is called to modify the template string after styles.tagname. I think a layer of string escaping is introduced here implicitly in type conversion, so I'm trying an explicit conversion.
Looking into it a little more, it seems that all those conversions in swc don't escape anything.
But after some investigation and looking at related issues (emotion-js/emotion#1755, emotion-js/emotion#2802) I found #38301 which is apparently the root of the problem.
Tagged template strings basically have two forms: the "cooked" one which translates escape sequences, and the "raw" one which leaves the string exactly as it appears in the source. (See here for more info.) So I think this is the line responsible: https://github.com/vercel/next.js/blob/8bc587aa30099bdf3ee379fe0b1a2fe3387801cf/packages/next-swc/crates/emotion/src/lib.rs#L340
q.raw here selects the raw form, and it seems the transformations which come later (in this function) never attempt to "cook" the string.
@kdy1 Are you still working on #38301? If not I'll try making a pr that should resolve both.
No I'm not working on it
@rubytree33 When can we expect a fix here? Looks like it is already fixed but not merged…
That's up to the maintainers, since I can't merge the PR myself.
https://github.com/swc-project/plugins/pull/260 should fix this issue
This closed issue has been automatically locked because it had no new activity for 2 weeks. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.