emotion-js/emotion

Load order of @emotion/styled and @emotion/react matters

BreakBB opened this issue · 1 comments

Current behavior:

When using manual chunks in the rollup config, to reduce the individual chunk size, the order in which the chunks are build matters.

We add manual chunking to improve load times. Usually we simply do so by placing every dependency in it's own chunk (check details below).
The issue is broken down with the chunking settings below. When changing the order of both entries, everything works just fine.

Broken:

        manualChunks: {
          emotionStyled: ["@emotion/styled"],
          emotionReact: ["@emotion/react"],
        }

Works:

        manualChunks: {
          emotionReact: ["@emotion/react"],
          emotionStyled: ["@emotion/styled"],
        }

In Firefox the error message is:

Uncaught TypeError: undefined has no properties

image

The built chunks differ in their size, when switching the order:

@emotion/styled first:
image

@emotion/react first:
image

To reproduce:

  1. Checkout https://github.com/BreakBB/mui-bundle-error (This is a fresh vite project with @emotion/styled and @emotion/react installed).
  2. npm ci
  3. npm run build
  4. npx service -s dist
  5. Open localhost:3000 and check the console output to see the error

The vite.config.ts file was adjusted, to contain the manual chunking described above.

Expected behavior:

It should not matter in which order the chunks are loaded.

Additional information:

I noticed this behavior when updating @mui/material to v6.1.0, but the curl print seems to be @emotion (details are in this mui issue).

Instead of configuring "manual chunking" as above, usually it is preferred to do something like this:

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

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  build: {
    minify: false, // to be readable
    rollupOptions: {
      output: {
        manualChunks(id) {
          if (id.includes("node_modules")) {
            return id.toString().split("node_modules/")[1].split("/")[0].toString();
          }
        },
      },
    },
  },
})

This splits all dependencies found in the node_modules directory based by name. Depending on the project this might cause problems though as the order might change.

Environment information:

  • react version: 18.3.1
  • @emotion/react version: 11.13.3