Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

alejadeveloper's avatar

How can I get antd and inertia SSR working?

I'm working on an application that requires the antd framework, but when using SSR, it doesn't integrate well during compilation. I don't want to see flickering or rearranging of styles. The official documentation talks about how to integrate it into next.js, but I'm using inertia with laravel and I've tried many things, but it hasn't worked at all.

app.tsx

Wrapper.tsx

import i18n from '@/Config/i18n';
import theme from '@/Utils/theme';
import { createCache, StyleProvider } from '@ant-design/cssinjs';
import { ConfigProvider } from 'antd';
import esES from 'antd/locale/es_ES';
import { PropsWithChildren } from 'react';
import { I18nextProvider } from 'react-i18next';

export default function Wrapper({ children }: PropsWithChildren) {
    const cache = createCache();
    return (
        <I18nextProvider i18n={i18n}>
            <StyleProvider cache={cache}>
                <ConfigProvider locale={esES} theme={theme} prefixCls="astur">
                    {children}
                </ConfigProvider>
            </StyleProvider>
        </I18nextProvider>
    );
}
0 likes
3 replies
RemiM's avatar

[...] but when using SSR, it doesn't integrate well during compilation. I don't want to see flickering or rearranging of styles.

I'm not sure to understand. You are talking about the visual aspect of your application after running npm run build. Or maybe how the files are processed and "rearranged" in your folder structure?

For installing npm packages on a Laravel project, I recommend following the Vite installation guide instead of using the Next.js for your application to work properly.

I did a quick test locally, with Laravel 11, React (no Typescript tho), and it worked both in development and after building the assets (tested with the antd button component). However, it was a minimal setup, so it may not fully reflect the complexities of your project with a more intricate architecture.

1 like
RemiM's avatar

I'm not sure what could be causing the flickering after building the assets while starting SSR, especially since you didn't provide your vite.config.js and ssr.tsx files. However, I can share some of the relevant files from my basic project, which might help you pinpoint the issue in your environment.

To start, I installed the new project using Breeze React with SSR as the initial setup.

Next, I installed antd:

npm install antd --save    

imported the DatePicker component from antd in the Login.jsx file that comes with the initial setup described above.

Here are the relevant files:

package.json:

{
    "private": true,
    "type": "module",
    "scripts": {
        "build": "vite build && vite build --ssr",
        "dev": "vite"
    },
    "devDependencies": {
        "@headlessui/react": "^2.0.0",
        "@inertiajs/react": "^2.0.0",
        "@tailwindcss/forms": "^0.5.3",
        "@vitejs/plugin-react": "^4.2.0",
        "autoprefixer": "^10.4.12",
        "axios": "^1.7.4",
        "concurrently": "^9.0.1",
        "laravel-vite-plugin": "^1.2.0",
        "postcss": "^8.4.31",
        "react": "^18.2.0",
        "react-dom": "^18.2.0",
        "tailwindcss": "^3.2.1",
        "vite": "^6.0.11"
    },
    "dependencies": {
        "antd": "^5.24.0"
    }
}

jsconfig.json:

{
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
            "@/*": ["resources/js/*"],
            "ziggy-js": ["./vendor/tightenco/ziggy"]
        }
    },
    "exclude": ["node_modules", "public"]
}

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(),
    ],
});

app.jsx:

import '../css/app.css';
import './bootstrap';

import { createInertiaApp } from '@inertiajs/react';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { createRoot, hydrateRoot } from 'react-dom/client';

const appName = import.meta.env.VITE_APP_NAME || 'Laravel';

createInertiaApp({
    title: (title) => `${title} - ${appName}`,
    resolve: (name) =>
        resolvePageComponent(
            `./Pages/${name}.jsx`,
            import.meta.glob('./Pages/**/*.jsx'),
        ),
    setup({ el, App, props }) {
        if (import.meta.env.SSR) {
            hydrateRoot(el, <App {...props} />);
            return;
        }

        createRoot(el).render(<App {...props} />);
    },
    progress: {
        color: '#4B5563',
    },
});

ssr.jsx:

import { createInertiaApp } from '@inertiajs/react';
import createServer from '@inertiajs/react/server';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import ReactDOMServer from 'react-dom/server';
import { route } from '../../vendor/tightenco/ziggy';

const appName = import.meta.env.VITE_APP_NAME || 'Laravel';

createServer((page) =>
    createInertiaApp({
        page,
        render: ReactDOMServer.renderToString,
        title: (title) => `${title} - ${appName}`,
        resolve: (name) =>
            resolvePageComponent(
                `./Pages/${name}.jsx`,
                import.meta.glob('./Pages/**/*.jsx'),
            ),
        setup: ({ App, props }) => {
            global.route = (name, params, absolute) =>
                route(name, params, absolute, {
                    ...page.props.ziggy,
                    location: new URL(page.props.ziggy.location),
                });

            return <App {...props} />;
        },
    }),
);

I would suggest you to reduce the complexity of your project first by removing things like your wrapper.tsx, and getting everything to work as expected. Once that's done, you can gradually reintroduce complexity and identify where issues arise.

It's also important to note that my setup uses Inertia 2.0, which might be different from yours. If that's the case, you might find it helpful to check the documentation.

Please or to participate in this conversation.