-
-
Notifications
You must be signed in to change notification settings - Fork 32.7k
Description
Reproduction
Summary
After upgrading from MUI v6 to v7, invoking createTheme(themeOptions) in my company's design system package causes Webpack 5 builds to spike heap usage to ~2.2 GB and intermittently OOM in CI (Chromatic). Removing the createTheme call and exporting the raw themeOptions(empty object) keeps memory usage normal.
Environment
- Package type: private design-system library in a monorepo
- Tooling:
- Webpack ^5.72.0, webpack-cli ^4.9.2
- ts-loader ^9.3.0, TypeScript ^4.6.4
- devtool: "source-map", webpack-node-externals ^3.0.0
- UI stack:
- @mui/material ^7.3.2, @mui/utils ^7.3.2, @mui/system ^7.3.2
- Emotion @emotion/react 11.14.0, @emotion/styled ^11.8.1
- React 19.0.0, React DOM 19.0.0
- Storybook/CI:
- Storybook 9.1.2
- Chromatic ^6.7.0
- Package flags:
- "sideEffects": false
- ESM + CJS outputs via exports map
CI symptom: Chromatic Storybook deploy fails with FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
What changed
Only the MUI upgrade (6 → 7) and the presence of createTheme(...) correlate with the memory spike. The codebase, loaders, and Webpack config are otherwise stable.
Minimal code to reproduce
// src/theme.ts
import { deepmerge } from "@mui/utils";
import { createTheme, ThemeOptions } from "@mui/material";
export const themeOptions: ThemeOptions = {
// representative content only
components: {
MuiCssBaseline: deepmerge(/* baselineA */, /* baselineB */),
},
};
// ❌ Triggers memory spike in v7
const theme = createTheme(themeOptions);
// ✅ Workaround
const theme = {};
export default theme;
- baseline A also uses deepmerge in its styleOverrides property
Webpack excerpt with memory logging
class MemoryLoggerPlugin {
log(label) {
const m = process.memoryUsage();
const mb = x => (x / 1024 / 1024).toFixed(1);
console.log(`[mem] ${label} rss=${mb(m.rss)}MB heapUsed=${mb(m.heapUsed)}MB`);
}
apply(compiler) {
compiler.hooks.beforeRun.tap("MemLog", () => this.log("beforeRun"));
compiler.hooks.compile.tap("MemLog", () => this.log("compile"));
compiler.hooks.afterCompile.tap("MemLog", () => this.log("afterCompile"));
compiler.hooks.emit.tap("MemLog", () => this.log("emit"));
compiler.hooks.done.tap("MemLog", () => this.log("done"));
}
}
module.exports = {
mode: "production",
devtool: "source-map",
module: { rules: [{ test: /\.tsx?$/, loader: "ts-loader", exclude: /node_modules/, options: { configFile: "tsconfig.build.json" } }] },
externals: [require("webpack-node-externals")({ modulesFromFile: true })],
plugins: [new MemoryLoggerPlugin()],
};
Observed memory
With createTheme(themeOptions)
[mem] beforeRun rss=90.3MB heapUsed=28.3MB
[mem] compile rss=90.6MB heapUsed=28.6MB
[mem] afterCompile rss=2331.0MB heapUsed=2195.9MB
[mem] emit rss=2331.0MB heapUsed=2195.9MB
[mem] done rss=2334.1MB heapUsed=2198.6MB
With {}(empty object)
[mem] beforeRun rss=90.3MB heapUsed=28.5MB
[mem] compile rss=90.6MB heapUsed=28.6MB
[mem] afterCompile rss=550.2MB heapUsed=457.4MB
[mem] emit rss=550.2MB heapUsed=457.4MB
[mem] done rss=550.9MB heapUsed=460.3MB
Expected
Using createTheme
during a library build should not increase heap usage by ~4× or trigger OOM with default Node heap limits.
Actual
Heap jumps at afterCompile
to ~2.2 GB only when createTheme is present. CI often fails with:
FATAL ERROR: Ineffective mark-compacts near heap limit
Allocation failed - JavaScript heap out of memory
Requests
- What is the root cause of the large heap increase when calling createTheme in v7 builds?
- How can this be fixed or avoided in library builds, other than increasing CI memory limits?
- Any guidance for memory-efficient theme composition patterns in libraries on v7?
Search keywords: