Webpack 5 production builds have no styles

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:

  1. git clone https://github.com/Twiggeh/emotion-no-prod-styles
  2. run cd emotion-no-prod-styles/client/ && yarn install && yarn run build
  3. run cd ../server && yarn install && node ./src/app.js

Expected behavior:

To get styles outputted for when I use the development build.

Environment information:

  • react version: 17.0.1
  • @emotion/react version: 11.1.5

1 possible answer(s) on “Webpack 5 production builds have no styles

  1. 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',
                    ],
            },