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

Port babel-plugin-styled-components to SWC #30802

Closed
8 tasks done
timneutkens opened this issue Nov 2, 2021 · 70 comments · Fixed by #58517
Closed
8 tasks done

Port babel-plugin-styled-components to SWC #30802

timneutkens opened this issue Nov 2, 2021 · 70 comments · Fixed by #58517
Labels
locked SWC Related to minification/transpilation in Next.js.

Comments

@timneutkens
Copy link
Member

timneutkens commented Nov 2, 2021

This Babel plugin is the most used customization of .babelrc.

The plugin is split up in multiple separate transforms:

https://github.com/styled-components/babel-plugin-styled-components/blob/a26774e599c82c72e8793989f60310d29c181fac/src/index.js

The defaults are here: https://github.com/styled-components/babel-plugin-styled-components/blob/950692b92855f17609e4281d5081e3d2acbf4b6b/src/utils/options.js

The critical one which makes styled-components not have hydration issues with Next.js is displayNameAndId. All the other ones seem to be optimizations. Because of this I'd start by porting the displayNameAndId transform and then check what else can be ported.

Looking at the defaults the only transform that is disabled by default is the pure annotations one.

List of transforms:

  • ssr -- enabled when styledComponents: true
  • displayName -- enabled when styledComponents: true, disabled in production to reduce file size
  • css prop
  • fileName
  • minify
  • transpileTemplateLiterals
  • pure
  • namespace
@timneutkens timneutkens added kind: story SWC Related to minification/transpilation in Next.js. labels Nov 2, 2021
@timneutkens timneutkens changed the title Port babel-plugin-styled-components Port babel-plugin-styled-components to SWC Nov 2, 2021
@switz
Copy link

switz commented Nov 2, 2021

swc-project/swc#2506

Unclear if this is relevant, but it looks like SWC fixed the compiler to not break with styled-components. Still probably not enough to close this issue for customization/optionality, but maybe if updated, swc can compile SC at a base level now?

@timneutkens
Copy link
Member Author

swc-project/swc#2506

Unclear if this is relevant, but it looks like SWC fixed the compiler to not break with styled-components. Still probably not enough to close this issue for customization/optionality, but maybe if updated, swc can compile SC at a base level now?

The linked issue is unrelated as that one is about the minifier. This issue is about implementing the transforms that are critical for running styled-components correctly when doing SSR.

kodiakhq bot pushed a commit that referenced this issue Nov 9, 2021
## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have helpful link attached, see `contributing.md`

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `yarn lint`




Related to: #30802
@timneutkens
Copy link
Member Author

Posted an update on the feedback thread: #30174 (comment). It's available to try now.

@timneutkens timneutkens assigned losfair and unassigned kdy1 Nov 19, 2021
@cahbb
Copy link

cahbb commented Nov 22, 2021

Awesome ⭐

I'm a bit confused on how to actually implement. Not sure if this is on a "normal" next@12 version or if I still have to install next@canary. #30174 (comment)

I'm running version 12.0.2. Do I still need to use the experimental key in next.config.js?

This actually works, but am getting no displayNames (component names) on the components.

{
  styledComponent: true
}

This works as expected. Do you guys have an estimate on when this is not experimental any more?

{
  experimental: {
    styledComponent: true
  }
}

@romulovalez
Copy link

Right now is available only on next@canary and inside experimental.

Thanks to @kdy1 and @timneutkens for this contribution!

I'll wait for css prop to be ready and I will adopt in a blink of an eye!

@matwii
Copy link

matwii commented Nov 23, 2021

Ahh this explains why css prop failed.. I thought it was supported. Is it planned later?

@janro1
Copy link

janro1 commented Nov 24, 2021

Hi @kdy1, are you planning to publish the styled-components swc plugin to npm as well? Would be cool if it could also be used with the swc-loader

@samuelhnrq
Copy link

I'll wait for css prop to be ready and I will adopt in a blink of an eye!

Wait you mean like Emotion's css prop? I've been using it on next 12 already. You can change the JSX pragma trough jsconfig.json

@nwesthoff
Copy link

Thank you @timneutkens, we're all very excited about the work you all have been doing with SWC.

Our main blocker right now is 'referring to other components' feature of styled-components. I'm not exactly sure what transform this is using, but I wanted to flag it in case it's not on your roadmap already.

@timneutkens
Copy link
Member Author

Our main blocker right now is 'referring to other components' feature of styled-components. I'm not exactly sure what transform this is using, but I wanted to flag it in case it's not on your roadmap already.

That feature doesn't seem to rely on any compilation, it's just leveraging tagged template literals. Are you running into an issue with that feature or just checking if it's supported?

@agriffis
Copy link

Do you expect to support topLevelImportPaths? We need this for xstyled or any other lib that wraps styled-components. More info:

https://xstyled.dev/docs/migrate-from-styled-components/#babel-plugin
styled-components/babel-plugin-styled-components#288

@kdy1
Copy link
Member

kdy1 commented Nov 30, 2021

@janro1

Hi @kdy1, are you planning to publish the styled-components swc plugin to npm as well? Would be cool if it could also be used with the swc-loader

Sorry for the late response. I finally managed to handle issue emails and saw this.
Of course, although not polished/documented yet but @swc/core now supports rust plugins under experimental flags.

But it will require some more work because currently only displayNameAndId is ported to rust.

@janro1
Copy link

janro1 commented Nov 30, 2021

@janro1

Hi @kdy1, are you planning to publish the styled-components swc plugin to npm as well? Would be cool if it could also be used with the swc-loader

Sorry for the late response. I finally managed to handle issue emails and saw this. Of course, although not polished/documented yet but @swc/core now supports rust plugins under experimental flags.

But it will require some more work because currently only displayNameAndId is ported to rust.

Nice, thank you @kdy1! From what I see, displayNameAndId is all we need currently.

@KimPaow
Copy link

KimPaow commented Dec 1, 2021

When opting in to use SWC I noticed that media-queries like below have a new behaviour. Before, the query would take precedence but now the margin: 23px auto overwrites margin: auto auto 120px even when the condition is true.

const P = styled(BaseP)`
  margin-bottom: 60px;

  ${mq.breakpoint('sm')} {
    margin: auto auto 120px;
  }
`;

const CenterP = styled(P)`
  text-align: center;
  margin: 23px auto;
`;

@roxeteer
Copy link

roxeteer commented Dec 1, 2021

@KimPaow That has happened randomly in our applications even with babel. Styled-components FAQ has a solution: https://styled-components.com/docs/faqs#how-can-i-override-styles-with-higher-specificity

@KimPaow
Copy link

KimPaow commented Dec 1, 2021

@roxeteer That seems to be working, thanks for the tip!

@agriffis
Copy link

agriffis commented Dec 1, 2021

@roxeteer It's not random. Media queries don't increase specificity. The wrapping styled-component overrides the wrapped one because the rules come later.

@KimPaow The behavior you describe happens with Babel too, it's not related to SWC. https://codesandbox.io/s/stupefied-grass-e0cox?file=/src/App.js

@kdy1
Copy link
Member

kdy1 commented Dec 1, 2021

@agriffis I think it's related to the fact only displayNameAndId is ported. There were some babel transforms which can modify css, but those are not ported.

@roxeteer
Copy link

roxeteer commented Dec 1, 2021

@agriffis It's random in the sense that it depends on the order that styled-components outputs the rules, and it doesn't seem to be constant.

@agriffis
Copy link

agriffis commented Dec 1, 2021

@roxeteer Hmm, that really shouldn't happen... 😦 I understand you might not have a reproducer handy, but if you do, I would love to see it and an issue at https://github.com/styled-components/styled-components/issues. The specificity hack in the s-c doc shouldn't be necessary in this case. (Asking as a contributor to styled-components.)

@kdy1 Are you referring to transpilation of tagged template literals? In theory that's only an optimization and shouldn't change behavior. Or do you mean something else?

@ekaterina4952
Copy link

I have still same issue on the nextjs 13.4.1 even though I configured such as document of nextjs.
compiler: { styledComponents: { ssr: true} }

Prop "className" did not match. Server: "mui-style-1ggikmx" Client: "css-1ggikmx"

@thexpand
Copy link

I know this is probably not very relevant to the issue at hand, but I'll give you my 2 cents. It's been a very long time since this issue was opened. At some point, I just decided not to use SWC on the project that used the styled-components package. Later on, I started using CSS Modules with sass support and got completely hooked up. It's so much lighter on the final bundle and pages load definitely faster. For conditional switching of CSS classes, I use the classnames npm package. For me, CSS-in-JS puts too much pressure on the bundle and bloats it unnecessarily. Since I ditched it, I never looked back.

@bsmith-self
Copy link

We did the same thing. The issue in this ticket wasn't the motivator for switching, exactly, but switching means it became mostly a legacy issue

@utikati
Copy link

utikati commented Aug 7, 2023

I know this is probably not very relevant to the issue at hand, but I'll give you my 2 cents. It's been a very long time since this issue was opened. At some point, I just decided not to use SWC on the project that used the styled-components package. Later on, I started using CSS Modules with sass support and got completely hooked up. It's so much lighter on the final bundle and pages load definitely faster. For conditional switching of CSS classes, I use the classnames npm package. For me, CSS-in-JS puts too much pressure on the bundle and bloats it unnecessarily. Since I ditched it, I never looked back.

@thexpand Can you just tell me if in dev you can trace the file where your style is?
Im using SASS and in dev in browser i try to debug but all I see is "layout.css" with all the styles, did you had the same problem?

@2Pacalypse-
Copy link

Hey guys, I'm using the newest Next.js with the SWC compiler and styled-components work fine, but I don't see the more useful class names in the developer tools, which is supposed to be controlled with the displayNames config property. Nothing I do seem to fix this, and even more weirdly this used to work fine with the pages router, but doesn't work now with the app router. Does anyone know what might be wrong, or what's the best way to debug this in case it's a bug in Next.js's code?

@machineghost
Copy link

Honestly, the fact that this ticket has been open for almost two years should tell you everything you need to know: the Next.js team just doesn't care about supporting Styled Components.

Similarly, don't expect the Styled Components devs to help out in any way: when I asked the guy who answered basically said that he was the only developer left, and he could barely keep the library maintained on his own, so he doesn't have time to help out other projects.

Sadly, in 2023, if you want to use Next.js, you either have to abandon Styled Components (as I did), or live with a flawed integration.

@Lwdthe1
Copy link

Lwdthe1 commented Aug 27, 2023

I'm using Next.js 13.0.3 beta, and I've added to next.config.js:

compiler: {
  styledComponents: true,
},

However, when my own client-side JavaScript adds classes to elements, I'm getting the warning "Prop "className" did not match. Server: "<myclass, etc.>"
How do I prevent this warning? I do want to use ssr and rust, and I need to add classes to elements in the client, classes that are not present on the component expressed in the server-side JSX. Adding styledComponents: true is not fixing it.

I fixed the warning "Prop "className" did not match. Server: "<myclass, etc.>" by setting next.config.js like this:

// @ts-check
const { i18n } = require('./next-i18next.config.js');

/**
 * @type {import('next').NextConfig}
 */
const nextConfig = {
  reactStrictMode: true,
  compiler: { styledComponents: { ssr: true } },  // ✅
  i18n,
  trailingSlash: true,
};

module.exports = nextConfig;
  • Nextjs@12 +
  • styled-components

🔎 Trouble Shooting:

  1. Only set compiler: { styledComponents: true } is not enough ❌
  2. If used nextjs@12+,no need to import babel plugin babel-plugin-styled-components

This got me to a solution for getting the css prop working again after upgrading from NextJs 10, but mine is slightly different. I'm using:

  • "next": "^13.1.6",
  • "react": "^18.2.0",,
  • "styled-components": "^6.0.7", ,
  • "babel-plugin-styled-components": "^1.13.3",
  • "webpack": "^5.88.2"

The following are my next.config.js and .babelrc setups:

// next.config.js
module.exports = {
  return {
    env,
    useFileSystemPublicRoutes: false,
    typescript: {
	// TODO: Remove once project is fully typed
	ignoreBuildErrors: true,
    },
    compiler: {
	styledComponents: true,
    },
  }
}
// .babelrc
"plugins": [
		// ... other plugins
		[
			"babel-plugin-styled-components",
			{
				"ssr": true,
				"displayName": true,
				"preprocess": false
			}
		]
	]

@kdy1
Copy link
Member

kdy1 commented Aug 27, 2023

@Lwdthe1 If you have .babelrc, compiler.styledComponents has no effect.

@Lwdthe1
Copy link

Lwdthe1 commented Aug 27, 2023

@Lwdthe1 If you have .babelrc, compiler.styledComponents has no effect.

That's what I heard elsewhere, but that's not true. If I remove compiler.styledComponents, my css props stop working completely.

However, it does appear the babel-plugin-styled-components has no effect if I keep it or remove it so long as I have compiler.styledComponents.

@2Pacalypse-
Copy link

Hey guys, I'm using the newest Next.js with the SWC compiler and styled-components work fine, but I don't see the more useful class names in the developer tools, which is supposed to be controlled with the displayNames config property. Nothing I do seem to fix this, and even more weirdly this used to work fine with the pages router, but doesn't work now with the app router. Does anyone know what might be wrong, or what's the best way to debug this in case it's a bug in Next.js's code?

In case someone else faces the same issue, I've fixed it by doing what this comment suggested: #46605 (comment)

Sounds ridiculous, but it works.

@S-YOU
Copy link

S-YOU commented Sep 16, 2023

pure, minify and transpileTemplateLiterals are not implemented yet

May I know why minify is not supporting at all? I am seeing standalone/.build folder js contents not getting minified.

@fnwbr
Copy link

fnwbr commented Oct 24, 2023

Hey @kdy1 👋
Thank you very much for your continued efforts on this. As I'm seeing some movement in the @swc/plugin-styled-components package, can you maybe enlighten the rest of us?

As referred to by @2Pacalypse- and @d-nakajima, how come that this is the case?

I faced same problem when I use import { styled } from 'styled-components'. I change to import styled from 'styled-components' and it is fixed. Please try this change If your code is like first one.

(I don't know why it is fixed. The code for export in 'styled-components' file is export { styled, styled as default } ...)

Is there any chance you can fix this behavior going forward, and allow us to also use the following style of importing as well?

import { styled } from 'styled-components';

(This is the recommended way as of https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-named-as-default.md)

@kdy1
Copy link
Member

kdy1 commented Oct 25, 2023

Okay. I think at least the recommended way should work out of the box. I'll work on it. Thank you for the notice. I didn't know that it's the recommended way.

I misread it. It's a third-party eslint rule

@kdy1
Copy link
Member

kdy1 commented Oct 25, 2023

Filed swc-project/plugins#224 anyway, but I have lots of tasks with higher priority

ciffelia added a commit to ciffelia/swc-plugins that referenced this issue Nov 23, 2023
This implements `minify` option in styled-components plugin. The
minification algorithm and unit tests are ported from
`babel-plugin-styled-components`.

Note that CSS code in helper functions (`keyframes`, `css`, etc.) are
currently not always processed. I think there is a bug in `is_helper`
function, so I'll fix it in another pull request later.

fixes swc-project#143
cf. vercel/next.js#30802
ciffelia added a commit to ciffelia/swc-plugins that referenced this issue Nov 25, 2023
…roject#237)

This implements `transpileTemplateLiterals` option in styled-components plugin.

cf. vercel/next.js#30802
ciffelia added a commit to ciffelia/swc-plugins that referenced this issue Nov 27, 2023
This implements `pure` option in styled-components plugin. 

cf. vercel/next.js#30802
AkifumiSato pushed a commit to AkifumiSato/next.js that referenced this issue Nov 27, 2023
### What?

Update swc crates.

Diff:
swc-project/swc@09b3003...c566b73

### Why?

To fix bugs, and improve minification.

### How?

turbopack counterpart: vercel/turbo#6472

- Closes PACK-1972

- Closes vercel#30802

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
@fnwbr
Copy link

fnwbr commented Dec 5, 2023

Can confirm that import { styled } from 'styled-components'; is now also working as expected. (Tested Next.js 14.0.4-canary.41)
Thank you @kdy1! 🙌

Copy link
Contributor

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.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Dec 20, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
locked SWC Related to minification/transpilation in Next.js.
Projects
None yet
Development

Successfully merging a pull request may close this issue.