Node.js/Vite SSR: ERR_UNSUPPORTED_DIR_IMPORT with @mui/material/utils during Inertia.js SSR

I’m encountering an ERR_UNSUPPORTED_DIR_IMPORT error during server-side rendering (SSR) with Vite, React, MUI (Material UI), and Inertia.js. The specific error message is:

Error [ERR_UNSUPPORTED_DIR_IMPORT]: Directory import '/var/www/html/myproject/node_modules/@mui/material/utils' is not supported resolving ES modules imported from /var/www/html/myproject/node_modules/@mui/icons-material/esm/utils/createSvgIcon.js
Did you mean to import "@mui/material/node/utils/index.js"?

This error only occurs during the SSR process (php artisan inertia:start-ssr). The client-side build works fine.

Problem Context:

I’m using the following technologies:

  • Laravel: 11.38.2
  • Inertia.js: 2.0.0
  • React: 19.0.0
  • MUI (Material UI): 6.4.0
  • Vite: 6.0.7
  • Node.js: 22.13.0
  • npm: 10.9.2

What I’ve Tried:

  1. Corrected config/inertia.php: I’ve ensured that the bundle path in my config/inertia.php file correctly points to the SSR bundle generated by Vite (which is now in bootstrap/ssr/ssr.js):

    'bundle' => base_path('bootstrap/ssr/ssr.js'),
    
  2. noExternal Configuration: I’ve added the relevant MUI packages, lexical packages, react packages and @inertiajs/server to the ssr.noExternal array in my vite.config.js:

    ssr: {
        noExternal: [
            '@inertiajs/server',
            '@mui/material',
            '@mui/utils',
            '@mui/system',
            '@mui/styled-engine',
            '@emotion/react',
            '@emotion/styled',
            '@lexical/code',
            '@lexical/react',
            'lexical',
            'react-dom/server',
            'react'
        ],
    },
    
  3. Clean Install: I’ve tried removing node_modules, package-lock.json, clearing the npm cache, and reinstalling dependencies.

  4. Updated MUI: I have updated MUI to the latest version.

  5. Corrected imports in ssr.jsx: I have checked my imports in the ssr.jsx file.

  6. verified vite config output and ssr output: I have verified the output of the vite config, and the ssr output directory.

Relevant Code Snippets:

  • vite.config.js:

    import { defineConfig } from 'vite';
    import laravel from 'laravel-vite-plugin';
    import react from '@vitejs/plugin-react';
    
    export default defineConfig({
        plugins: [
            laravel({
                input: 'resources/js/app.jsx',
                ssr: 'resources/js/ssr.jsx', 
                refresh: true,
            }),
            react(),
        ],
        build: {
            outDir: 'public/build',
        },
        ssr: {
            build: {
                outDir: 'bootstrap/ssr',
            },
            noExternal: [
                '@inertiajs/server',
                '@mui/material',
                '@mui/material/utils',
                '@mui/utils',
                '@mui/system',
                '@mui/styled-engine',
                '@mui/icons-material',
                '@emotion/react',
                '@emotion/styled',
                '@lexical/code',
                '@lexical/react',
                'lexical',
                'react-dom/server',
                'react'
            ], 
        },
        resolve: {
            alias: {
                '@': '/resources/js',
                '@css': '/resources/css',
                '@shared': '/resources/js/Shared',
                '@utils': '/resources/js/utils',
            }
        },
    });
    
  • config/inertia.php:

    <?php
    
    return [
        'ssr' => [
            'enabled' => env('INERTIA_SSR_ENABLED', true),
            'url' => env('INERTIA_SSR_URL', 'http://127.0.0.1:13714'),
            'bundle' => base_path('bootstrap/ssr/ssr.js'),
        ],
    ];
    
  • resources/js/ssr.jsx:

    import React from 'react';
    import { createInertiaApp } from '@inertiajs/react';
    import createServer from '@inertiajs/react/server'
    import { renderToString } from 'react-dom/server';
    import Layout from '@shared/Layout';
    
    createServer((page) =>
        createInertiaApp({
            page,
            render: renderToString,
            resolve: name => {
              const pages = import.meta.glob('./Pages/**/*.jsx', { eager: true })
              return pages[`./Pages/${name}.jsx`]
            },
            setup({ App, props }) {
                return <Layout children={<App {...props} />} />;
            },
        })
    );
    

Expected Behavior:

I expect the SSR server to start without any ERR_UNSUPPORTED_DIR_IMPORT errors.

Actual Behavior:

The ERR_UNSUPPORTED_DIR_IMPORT error persists, preventing the SSR server from starting.

Question:

How can I resolve the ERR_UNSUPPORTED_DIR_IMPORT error with @mui/material/utils during Vite SSR with Inertia.js? Is there a specific configuration or workaround needed to handle MUI’s internal module resolution in this context?