Current behavior:
Development build produces styled components like expected, while the production build doesn't style anything at all, although there are class names added.
I tried both using the css-prop transform preset and the plugin & preset combo like https://emotion.sh/docs/css-prop##babel-preset suggested, but both produce nothing.
The dev build on the other hand is okay with just the preset.
The only Emotion things that I can see in the final build are a
<style data-emotion="css" data-s=""></style>
tag and the css classes, also there are a lot of emotions in the source files, so something did build, its just that that something is probably not appending the style tags into the header ?
To reproduce:
git clone https://github.com/Twiggeh/emotion-no-prod-stylescd emotion-no-prod-styles/client/ && yarn install && yarn run buildcd ../server && yarn install && node ./src/app.jsExpected behavior:
To get styles outputted for when I use the development build.
Environment information:
react version: 17.0.1@emotion/react version: 11.1.5Please prepare a simpler repro - this can't even be executed as is right now:
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/react-emotion-2282/server/keys/keys.js' imported from /react-emotion-2282/scripts/setup.js
Please prepare a simpler repro - this can't even be executed as is right now:
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/react-emotion-2282/server/keys/keys.js' imported from /react-emotion-2282/scripts/setup.js
you need to run yarn install and yarn run build inside client. If you run it in the project root it will start the server, which would need keys. You do not need the server to reproduce the issue hence why I wrote that you need to run it in client (and serve the client/dist/index.html with any file server, e.g. live server extension from vscode) :D
I have updated the repo to include a simple server & copy / paste instructions. Sorry that I did not include copy pastables in the first place.
You can fix this by removing @emotion/styled from your vendors:
https://github.com/Twiggeh/emotion-no-prod-styles/blob/9e5c6e2cc7f7708ec0a968cd6ae7de26fbe8df89/client/config/webpack.prod.js#L25
I'm not a webpack expert (although I know a pretty decent amount of things about it) so I'm not 100% sure why this happens - I would kinda still expect your module graph to be split correctly~. Especially when I've tried to add @emotion/react to your vendors as well but that didn't work.
In the webpack docs for entry u might find a golden rule though:
Simple rule: one entry point per HTML page. SPA: one entry point, MPA: multiple entry points.
You break that rule because you expect 2 entry bundles to be injected into a single HTML file (and this breaks stuff). On the other hand - this rule is pretty quickly contradicted in the same doc page when describing what should be done for exactly what you are trying to do: creating a vendors bundle. It describes how you should use dependOn:
https://webpack.js.org/configuration/entry-context/#dependencies
You can try this patch to see the issue being fixed:
diff --git a/client/config/webpack.prod.js b/client/config/webpack.prod.js
index df87db8..ac811ba 100644
--- a/client/config/webpack.prod.js
+++ b/client/config/webpack.prod.js
@@ -16,13 +16,17 @@ console.log(mode);
module.exports = {
entry: {
- main: path.resolve(__dirname, '../src/index.js'),
+ main: {
+ import: path.resolve(__dirname, '../src/index.js'),
+ dependOn: ['vendor']
+ },
vendor: [
'react',
'react-dom',
'scheduler',
'object-assign',
'@emotion/styled',
+ '@emotion/react',
'prop-types',
],
},
Thank you for pointing me to to the right direction - the problem with the current config is the order in which the scripts get loaded !

The vendor script must be the first to be loaded for emotionjs to be able to work (because its runtime is extracted right?), when the browser loads the other stuff it tries to use a runtime that doesn't exist, but it doesn't throw an error ?
Anywho, the solution with dependOn works much better (total bundle size is 90kb vs 140kb for the reordered import order of scripts!) and I am now thoroughly confused, because the runtime remains in vendor? Maybe it now adds a dynamic import that awaits for vendor to load ?
Anyways thank you a lot, I can build my stuff now :)
Without dependOn you end up with 2 Emotion runtimes being loaded - there is still an issue there, it just might not manifest itself that easily. I encourage you to use the dependOn solution as it seems the proper one and more future-proof.
Most helpful comment
You can fix this by removing
@emotion/styledfrom your vendors:https://github.com/Twiggeh/emotion-no-prod-styles/blob/9e5c6e2cc7f7708ec0a968cd6ae7de26fbe8df89/client/config/webpack.prod.js#L25
I'm not a webpack expert (although I know a pretty decent amount of things about it) so I'm not 100% sure why this happens - I would kinda still expect your module graph to be split correctly~. Especially when I've tried to add
@emotion/reactto your vendors as well but that didn't work.In the webpack docs for
entryu might find a golden rule though:You break that rule because you expect 2 entry bundles to be injected into a single HTML file (and this breaks stuff). On the other hand - this rule is pretty quickly contradicted in the same doc page when describing what should be done for exactly what you are trying to do: creating a vendors bundle. It describes how you should use
dependOn:https://webpack.js.org/configuration/entry-context/#dependencies
You can try this patch to see the issue being fixed: