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

How use with Vite.js, especially displayName for debugging. #350

Open
valerii15298 opened this issue Aug 22, 2021 · 30 comments
Open

How use with Vite.js, especially displayName for debugging. #350

valerii15298 opened this issue Aug 22, 2021 · 30 comments

Comments

@valerii15298
Copy link

When using with CRA, its possible to see name of component inside css classes, but I cannot figure out how to make a nice developing/debugging experience when using with Vite.js. Is there any advices how to show in classes names of components when using with Vite.js?

@rockwotj
Copy link
Contributor

I suggest using https://www.npmjs.com/package/vite-plugin-babel-macros and importing from styled-components/macro. We have this working nicely in our vite setup (although that's with a custom plugin that should do the same as the package I pointed you too).

@ronaldruzicka
Copy link

ronaldruzicka commented Sep 23, 2021

Hi @rockwotj, please could you share your code how you set it up?
Or could you please tell me what am I doing wrong?

I have this config

// vite.config.ts
import { defineConfig } from 'vite';
import reactRefresh from '@vitejs/plugin-react-refresh';
import macrosPlugin from "vite-plugin-babel-macros"

export default defineConfig({
  plugins: [
    reactRefresh(),
    macrosPlugin(),
  ],
});

And then I just import from styled-components/macros

// App.tsx

import styled from 'styled-components/macros';

But I get a Typescript error and error from Vite.
I have the latest version of Styled Components: "styled-components": "^5.3.1"

// Typescript
Cannot find module 'styled-components/macros' or its corresponding type declarations.

// Vite
error when starting dev server:
Error: The following dependencies are imported but could not be resolved:
  styled-components/macros (imported by /Users/ronaldruzicka/Projects/vite-project/src/App.tsx)

Thanks!

@rockwotj
Copy link
Contributor

Hi @rockwotj, please could you share your code how you set it up?
Or could you please tell me what am I doing wrong?

Looks like it's not installed. Did you run npm install?

@ronaldruzicka
Copy link

Oh my bad, I was using plural /macros instead of singular /macro 🤦‍♂️
Now it's working properly, thanks a lot!

@IvanBernatovic
Copy link

@ronaldruzicka I added the macros plugin and started importing styled like this:
import styled from 'styled-components/macro

But I still don't get proper class names, they are still randomized/minified. Is there anything else I should do?

@rockwotj
Copy link
Contributor

@IvanBernatovic you need to have a config file to get display names, see the docs for more: https://styled-components.com/docs/tooling#experimental-config

@ronaldruzicka
Copy link

@IvanBernatovic I didn't use any other config. I just included that macrosPlugin in the vite.config.ts and then used import styled from 'styled-components/macro'; in the component and it worked.

I have these versions:

"styled-components": "^5.3.0"
"vite-plugin-babel-macros": "^1.0.5",

But maybe try that experimental config as well.

@IvanBernatovic
Copy link

@rockwotj @ronaldruzicka Thank you for your responses! I tried to add config as per styled-components docs but it still didn't work. I tried many things but in the end, solution was even simpler than this approach. This is what worked for me in vite.config.js:

// vite.config.js

export default defineConfig({
  plugins: [
    react({
      babel: {
        plugins: [
          [
            'babel-plugin-styled-components',
            {
              displayName: true,
              fileName: false
            }
          ]
        ]
      }
    })
  ]
})

No need to install any other plugin for babel macros (nor vite nor babel macros plugin) and no need to change exports to import styled from 'styled-components/macro'.

@velsa
Copy link

velsa commented Dec 26, 2021

@IvanBernatovic
I'm new to Vite. What additional config should I have to run the same plugin in a Typescript project?
If I just add it as in your example, I get lots of errors from vite. It seems that it tries to parse all TS typecasts as react components :)
E.g. it thinks that <ISomeInterface> is a component and complains.

@IvanBernatovic
Copy link

@IvanBernatovic I'm new to Vite. What additional config should I have to run the same plugin in a Typescript project? If I just add it as in your example, I get lots of errors from vite. It seems that it tries to parse all TS typecasts as react components :) E.g. it thinks that <ISomeInterface> is a component and complains.

Unfortunately, I can't help you with that as I don't have this setup (vite+typescript+styled-components) so I can't tinker around with config. Maybe if you had a reproducible example (a repo or codesandbox project) I could take a look.

Did you try other approaches from previous comments?

@agriffis
Copy link
Contributor

agriffis commented Jan 6, 2022

E.g. it thinks that <ISomeInterface> is a component and complains.

@velsa That's a known peculiarity of tsx. For generics you can use <T extends unknown> (you don't need this if there are two or more params, only one). For casting you can use as. See microsoft/TypeScript#6897 and lots more if you google tsx generic cast

@agriffis
Copy link
Contributor

agriffis commented Jan 6, 2022

@IvanBernatovic

But I still don't get proper class names, they are still randomized/minified. Is there anything else I should do?

Just connecting some dots, this was almost certainly because of styled-components/styled-components#3635

@velsa
Copy link

velsa commented Feb 20, 2022

Btw, for anyone interested, I eventually did the following:

  plugins: [
    // For all styled components:
    // create classnames from fileName and displayName in development
    react({
      babel: {
        presets: ['@babel/preset-typescript'],
        plugins: [
          '@babel/plugin-transform-typescript',
          [
            'babel-plugin-styled-components',
            {
              ssr: false,
              pure: true,
              displayName: true,
              fileName: false,
            },
          ],
        ],
      },
    }),
  ];

I added vite react plugin which accepts babel configuration and I am also doing TS transform ('@babel/plugin-transform-typescript) before using babel-plugin-styled-components.

This approach seems to play nicely with vite )

@valerii15298 valerii15298 changed the title How use with Vite.js, especialy displayNmae for debugging. How use with Vite.js, especially displayName for debugging. Feb 20, 2022
@pawelczerepak
Copy link

pawelczerepak commented Apr 14, 2022

displayName worked fine with the babel macros described above but I had some issues with the css prop. In the end what worked for me is

import { defineConfig } from 'vite';
import reactPlugin from '@vitejs/plugin-react';
import macrosPlugin from "vite-plugin-babel-macros"

export default defineConfig({
  plugins: [
    macrosPlugin(),
    reactPlugin(),
  ],
});

and then import using import styled from "styled-components/macro";

Note that macros plugin is added before react plugin. babel-plugin-styled-components relies on JSX nodes in AST for the css prop to work. So this transform needs to happen before JSX gets transformed away. You also need to have the macro import in the same module where your css prop is used. Below the styled import is unused but without it the prop wouldn't work.

import React from "react";
import styled from "styled-components/macro";
import { someStyle } from "./styled";

export default function Component() {
    return <div css={someStyle} />;
}

Hope this helps someone.

@oribenez
Copy link

@rockwotj @ronaldruzicka Thank you for your responses! I tried to add config as per styled-components docs but it still didn't work. I tried many things but in the end, solution was even simpler than this approach. This is what worked for me in vite.config.js:

// vite.config.js

export default defineConfig({
  plugins: [
    react({
      babel: {
        plugins: [
          [
            'babel-plugin-styled-components',
            {
              displayName: true,
              fileName: false
            }
          ]
        ]
      }
    })
  ]
})

No need to install any other plugin for babel macros (nor vite nor babel macros plugin) and no need to change exports to import styled from 'styled-components/macro'.

not working on production.
Did someone managed to make it work on production mode?

@jurosh
Copy link

jurosh commented Nov 15, 2022

@rockwotj @ronaldruzicka Thank you for your responses! I tried to add config as per styled-components docs but it still didn't work. I tried many things but in the end, solution was even simpler than this approach. This is what worked for me in vite.config.js:

// vite.config.js

export default defineConfig({
  plugins: [
    react({
      babel: {
        plugins: [
          [
            'babel-plugin-styled-components',
            {
              displayName: true,
              fileName: false
            }
          ]
        ]
      }
    })
  ]
})

No need to install any other plugin for babel macros (nor vite nor babel macros plugin) and no need to change exports to import styled from 'styled-components/macro'.

This works for me too, but needed to also add ssr: false. ⚠️ Without this hot-reload of styles was not reliable at all - changing properties works, but removing would just keep last value always persisted (until next reload).

react({
  babel: {
    plugins: [
      ['babel-plugin-styled-components', { ssr: false, pure: true, displayName: true, fileName: true }]
]}})

On the other hand I am not confident if this is proper solution or some kind of ugly thing we all hate from CRA (Rewire/Craco). Would be nice if Vite would be able to support such basic styled-components functionality out of the box or at least have documented how to do it correctly.

@JulSeb42
Copy link

JulSeb42 commented Jan 27, 2023

Hey, I'm trying to use vite-plugin-babel-macros inside my project. It works, but I'd like not to have the fileName displayed inside the generated class. I tried like this, but I still have the fileName inside the class:

export default defineConfig({
    plugins: [
        react({
            babel: {
                plugins: [
                    [
                        "babel-plugin-styled-components",
                        {
                            fileName: false,
                            displayName: true,
                            meaninglessFileNames: ["index", "styles"],
                        },
                    ],
                ],
            },
        }),
        macrosPlugin(),
    ],
})

How can I fix it? Thanks!

@mlewando-cp
Copy link

mlewando-cp commented Feb 1, 2023

Hi guys
I managed to have this config working in at least couple of ways (only displayName, namespace, fileName...) but the result is that elements has now classes with prefixes done accordingly to the configuration plus additional not prefixed class that is actually used in generate CSS. This is not what I expected, I hoped to have CSS styles assigned to prefixed classes. Is there a way to add some prefixes to classes that are actually used?

image

In the example above I need to have styles assigned to StyledDiv-gzSrWC and not hnYDyV as they are now (ideally class hnYDyV should not exist in the element at all)

This is the code that generated this example:

const StyledDiv = styled.div`
  color: red;
  padding: 10px;
  background-color: blue;
`;

const App = () => <StyledDiv>hello react</StyledDiv>;

and this is the config in vite.config.js:

    plugins: [
      react({
        babel: {
          plugins: [
            [
              "babel-plugin-styled-components",
              {
                ssr: false,
                pure: true,
                displayName: true,
                fileName: false,
              },
            ],
          ],
        },
      }),

@basic-steve
Copy link

@MeLlamoPablo works for me, thanks.
For anyone who needs to customize the config a bit more, here all the available params: https://styled-components.com/docs/tooling

@pradeepkumar24rk
Copy link

@rockwotj @ronaldruzicka Thank you for your responses! I tried to add config as per styled-components docs but it still didn't work. I tried many things but in the end, solution was even simpler than this approach. This is what worked for me in vite.config.js:

// vite.config.js

export default defineConfig({
  plugins: [
    react({
      babel: {
        plugins: [
          [
            'babel-plugin-styled-components',
            {
              displayName: true,
              fileName: false
            }
          ]
        ]
      }
    })
  ]
})

No need to install any other plugin for babel macros (nor vite nor babel macros plugin) and no need to change exports to import styled from 'styled-components/macro'.

I also got the same issue my vite-config doesn't change anything it remains the same when I install vite.

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
})

I try a lot of things to solve this issue but till now I can't able to solve this issue in my system.

 "dependencies": {

    "eslint-plugin-styled": "^0.1.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "styled-components": "^6.0.3",
    "vite-plugin-babel-macros": "^1.0.6"
  },
  "devDependencies": {
    "@types/react": "^18.2.14",
    "@types/react-dom": "^18.2.6",
    "@vitejs/plugin-react": "^4.0.1",
    "babel-plugin-styled-components": "^2.1.4",
    "eslint": "^8.44.0",
    "eslint-plugin-react": "^7.32.2",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.4.1",
    "vite": "^4.4.0"
  }

I also installed the babel macros but the issue is not solved

code app.js :

import styled from 'styled-components/macros';
function App() {


  return (
   <Container>
      hello
   </Container>
  )
}

export default App

const Container=styled.button`
  color: red;
`

issue :

15 | window.$RefreshSig$ = RefreshRuntime.createSignatureFunctionForTransform;
16 | }
17 | import styled from "styled-components/macros";
| ^
18 | function App() {
19 | return /* @PURE */ jsxDEV(Container, { children: "hello" }, void 0, false, {

@zibra
Copy link

zibra commented Sep 18, 2023

Disabling ssr helped in my case (Nx, Vite, latest versions of SC and babel plugin)

@vostersc
Copy link

vostersc commented Nov 1, 2023

Just leaving this for anyone stuck like I was. I needed an older version of styled-components in order to get the /macro folder working with my Vite/React/Styled-components project. The version I settled on was 5.3.0. I believe the folder was removed in v6.1 because of low usage. After getting the correct version, a compilation of the advice above worked for me.

@bambery
Copy link

bambery commented Jan 23, 2024

So In 2024, what is the way to get this working? I have spent about two hours messing around with this and I still simply get an error every time I try to spin up my app. Debugging is terrible. Why is this a separate package and not a config for the base library? Who doesn't need readable class names when debugging?

@Sheraff
Copy link

Sheraff commented Jan 23, 2024

So In 2024, what is the way to get this working? I have spent about two hours messing around with this and I still simply get an error every time I try to spin up my app. Debugging is terrible. Why is this a separate package and not a config for the base library? Who doesn't need readable class names when debugging?

I'm using the @vitejs/plugin-react-swc plugin, which itself accepts an array of plugins. This is the config I'm using

[
      '@swc/plugin-styled-components',
      {
        displayName: true,
        fileName: true,
        ssr: false,
      },
    ]

So basically no babel plugin, but if you can make the switch, this works perfectly fine.

@aesy
Copy link

aesy commented Jan 23, 2024

@Sheraff Thanks for the pointer. For me, unfortunately, it gives me a deadlock when trying to build, no idea why. Would love to hear if it happens to anyone else and if they could resolve it.

@wojtekmaj
Copy link

@aesy You're not alone, @vitejs/plugin-react-swc doesn't seem to do the trick for me. During development, index.html loads, but after that, Vite just crashes silently.

@hkrobotics
Copy link

hkrobotics commented Jan 24, 2024

I am getting this error [vite] Pre-transform error: failed to handle: assertion failed: !result.is_null() (x2)

This is the config i am using

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
import { nodePolyfills } from 'vite-plugin-node-polyfills'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react({
    plugins: [[
      "@swc/plugin-styled-components",
      {
        displayName: true,
        ssr: true
      }
    ]]
  }), nodePolyfills()]
})

This error only comes up when i add @swc/plugin-styled-components plugin

@unyo
Copy link

unyo commented Jan 25, 2024

For those having trouble with @swc/plugin-styled-components, I found luck with downgrading to @swc/plugin-styled-components@1.5.111: vitejs/vite-plugin-react-swc#190 (comment). With @swc/plugin-styled-components@1.5.115, vite was just crashing upon visiting http://localhost:5173/ in the browser, with this error:

zsh: bus error  

(Edit: I think maybe I was getting an error because I forgot to install @swc/core perhaps? latest @swc/core isn't working with @swc/plugin-styled-components@1.5.111, it errors out on build with:)

[vite:react-swc] failed to handle: failed to invoke plugin: failed to invoke plugin on 'Some...

Background

I've been trying to find a good replacement for create-react-app, all the new ones (next.js, remix, expo) can't be hosted at a /unknown-at-build-time/subpath/ - BrowserRouter doesn't work with relative paths (<base href="." />), and there isn't a good way to swap out BrowserRouter with a HashRouter. And remix build apparently just builds server JS files instead of static files like next.js and gatsby and expo do. It has an unstable SPA mode that uses vite - so I'm checking it out since I can't use any browser history routers. I've used gatsby before, but I don't feel like graphql today, so I'm not sure if it would work for this case yet.

So since I have to use HashRouter, this limits me to vite, parcel, or create-react-app. And it seems parcel does not work with @swc/plugin-styled-components at the moment (it doesn't seem to parse .swrc), so vite is my best hope for a CRA replacement at the moment (as create-react-app is being depreciated)

Parcel works too, but that would require babel, which would probably have the same relative performance as CRA. I'm concerned about Vite hitting the 10 download concurrent limit for lots of files in a large project, but I'm willing to check out SWC's performance for a bit since I already know the capabilities of babel and parcel (though not babel + parcel yet)

I'm trying to retain usage of styled-components since it has the vendor prefixing that I'd like to have automatically - some of these other built-in CSS solutions for CRA alternatives don't seem to have that, and I have to support older hardware. I've used PostCSS in the past, but styled-component vendor prefixing automatically and the automatically generated displayName (vs emotion's manual labeling) make styled-components kind of unreplaceable at the moment.

(Note: For SSR frameworks, only next.js with page routing seems to do SSR styled-components well. Next.js w/ app routing requires 'use client'. Remix generate SSR CSS too, but requires some Error Boundary files (ie _boundary._index.js) that I would rather not have in the codebase for someone to break.)

Solutions

The solutions below all show displayName: true behavior.

SWC Config 👍

install

npm install --save styled-components
npm install --save-dev @vitejs/plugin-react-swc @swc/plugin-styled-components @swc/core @vitejs/plugin-legacy terser

vite.config.js:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
import legacy from '@vitejs/plugin-legacy'

export default defineConfig(({ mode }) => ({
  plugins: [
    react({ plugins: [["@swc/plugin-styled-components", {}]] }),
    legacy(),
  ],
  define: {
    'process.env.NODE_ENV': `'${mode || 'production'}'`, // browser throws an error about process not defined on determineTheme.ts
    'SC_DISABLE_SPEEDY': "true", // needed to enable vendor prefixing using 'vite build'
    // using process.env.SC_DISABLE_SPEEDY doesnt work due to the way styled-components checks for process.env 
    // https://github.com/styled-components/styled-components/blob/main/packages/styled-components/src/constants.ts#L17
    // I'm guessing process.env ternary worked in webpack but doesn't work with vite
    // you also need to wrap the app with <StyleSheetManager enableVendorPrefixes={true}>
  }
}))

package.json

  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "styled-components": "^6.1.8"
  },
  "devDependencies": {
    "@swc/core": "^1.3.106",
    "@swc/plugin-styled-components": "^1.5.115",
    "@vitejs/plugin-legacy": "^5.2.0",
    "@vitejs/plugin-react-swc": "^3.5.0",
    "terser": "^5.27.0",
    "vite": "^5.0.8"
  },

ref
ref

Babel Config 👍

install

npm install --save styled-components
npm install --save-dev @vitejs/plugin-react babel-plugin-styled-components

vite.config.js

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react({
    babel: {
      plugins: [['styled-components', { displayName: true }]]
    },
  })],
  define: {
    'SC_DISABLE_SPEEDY': "true", // needed to enable vendor prefixing using 'vite build'
  }
})

package.json

  "dependencies": {
    "babel-plugin-styled-components": "^2.1.4",
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@vitejs/plugin-react": "^4.2.1",
    "vite": "^5.0.8"
  }

ref

Babel Macros Config (depreciated, macros removed in styled-components 6) 🛑

install

npm install --save styled-components@5.3.0
npm install --save-dev vite-plugin-babel-macros @vitejs/plugin-react-swc

vite.config.js

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
import macrosPlugin from 'vite-plugin-babel-macros'

export default defineConfig({
  plugins: [
    macrosPlugin(),
    react()
  ],
  define: {
    'SC_DISABLE_SPEEDY': "true", // needed to enable vendor prefixing using 'vite build'
  }
})

package.json

  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "styled-components": "^5.3.0",
    "vite-plugin-babel-macros": "^1.0.6"
  },
  "devDependencies": {
    "@vitejs/plugin-react-swc": "^3.5.0",
    "vite": "^5.0.8"
  }

usage

import styled from 'styled-components/macro'

const Container = styled('div')`
  border: 4px solid green;
`

ref
ref

More options?

@bambery
Copy link

bambery commented Jan 25, 2024

Thank you all for your responses. I am hesitant to bind myself to old versions, and as I am beginning a new project, I think I will simply opt for a different way to manage styling inside of React rather than using styled components.

@unyo
Copy link

unyo commented Jan 25, 2024

@bambery after some investigation I was able to get it working with the latest @swc/plugin-styled-components

https://github.com/unyo/vite-swc-styled-components-legacy

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

No branches or pull requests