14

Is anyone using Vite to bundle their MUI app? I was surprised at how big my vendor chunk (1.1MB) was from Vite/Rollup. I've come up with the below config which separates MUI packages into it's own chunk:

import { defineConfig } from "vite";
import reactRefresh from "@vitejs/plugin-react-refresh";
import { dependencies } from "./package.json";

// whenever you get the error: (!) Some chunks are larger than 500kb after minification
// find the biggest lib in your vendors chunk and add it to bigLibs
const bigLibs = [
  { regExp: /^@material-ui*/, chunkName: "@material-ui" },
  { regExp: /^@aws-amplify*/, chunkName: "@aws-amplify" },
];

function getManualChunks(deps: Record<string, string>) {
  return Object.keys(deps).reduce(
    (prev, cur) => {
      let isBigLib = false;
      for (const l of bigLibs) {
        if (l.regExp.test(cur)) {
          isBigLib = true;
          if (prev[l.chunkName]) {
            prev[l.chunkName].push(cur);
          } else {
            prev[l.chunkName] = [cur];
          }
          break;
        }
      }
      if (!isBigLib) prev.vendors.push(cur);
      return prev;
    },
    { vendors: [] } as Record<string, string[]>
  );
}

// https://vitejs.dev/config/
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks: getManualChunks(dependencies),
      },
    },
  },
  plugins: [reactRefresh()],
  resolve: {
    alias: [
      {
        find: "./runtimeConfig",
        replacement: "./runtimeConfig.browser",
      },
    ],
  },
});

but... I get an error in the browser:

@material-ui.1d552186.js:1 Uncaught TypeError: Cannot read property 'exports' of undefined
    at @material-ui.1d552186.js:1

Does anyone know what's going on? I have a suspicion that I'm not correctly tree shaking.

Ben Stickley
  • 1,551
  • 1
  • 16
  • 22

2 Answers2

22

If u set a function for "manualChunks" the first argument will be a "string"

https://www.rollupjs.org/guide/en/#outputmanualchunks

try this:

manualChunks: (id) => {
if (id.includes("node_modules")) {
    if (id.includes("@aws-amplify")) {
        return "vendor_aws";
    } else if (id.includes("@material-ui")) {
        return "vendor_mui";
    }

    return "vendor"; // all other package goes here
}
},
Tamás Katona
  • 683
  • 7
  • 13
  • 1
    I ended up still having very large chunks but this is because those libs are so big. This is the correct answer to fix the error. Thank you! – Ben Stickley Jan 05 '22 at 01:08
3

If you wanna spare all modules try this

...
manualChunks: (id) => {
    if (id.includes('node_modules')) return id.toString().split('node_modules/')[1].split('/')[0].toString();
}
...

Regards