Making Emotion React work with Vite
According to Emotion docs, the standard way to use Emotion is with css
prop of jsx components. For first time users, it's easy to miss out on the required pragma header and just add the css prop directly. In that case, this is what you will get:
<div css="You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop).">
</div>
To fix that, remember to add a jsx pragma at the top of file /** @jsx jsx */
. But If your project is configured via Vite, you are to get the following error:
Turn out Emotion documentation does mention that:
If you are using a zero-config tool with automatic detection of which runtime (classic vs. automatic) should be used and you are already using a React version that has the new JSX runtimes (hence runtime: 'automatic' being configured automatically for you) such as Create React App 4 then /** @jsx jsx / pragma might not work and you should use /* @jsxImportSource @emotion/react */ instead.
Use jsxImportSource Pragma
But following the instruction and replace @jsx
with @jsxImportSource
results in another error thrown by Vite:
According to this typescript document, jsxImportSource
pragma specifies which factory method should be used to compile jsx string into plain old javascript objects. Look like Vite needs to know that it can automatically determine which jsx transform method to use on a per file basis. In order for the css
prop mentioned above to function properly, Vite should use Emotion provided jsx
transform function instead of React's default (i.e React.createElement
)
Update Vite.config.js
A little digging around the web, it's possible to configure jsxImportSource
via the vite.config.js
file instead. Add the bellow lines to the Vite config file:
plugins: [react({
jsxImportSource: "@emotion/react",
babel: {
plugins: ["@emotion/babel-plugin"],
},
})
]
That let Vite knows definitely that it should use jsx
transform function from Emotion for the whole project. It has the added benefit of not having to add pragma comment at the top of every source file.
And be sure to install the Emotion Babel plugin
npm install -D @emotion/babel-plugin
Now that the configuration is updated, Emotion based JSX components are transformed properly in a Vite project.