DEV Community

sbc640964
sbc640964

Posted on

Using Vite with Inertia — Laravel, *React* & Tailwind

I rely on this post:

I tried to follow it with React as well, and having failed as you will see in this comment, I share with you the process and the solution.

First I also followed this tutorial - 5 parts:

First - Immediately after creating a new laravel project, package.json should be modified
so:

{
    "private": true,
    "scripts": {
        "dev": "vite",
        "production": "vite build"
    },
    "devDependencies": {
        "axios": "^0.24.0",
        "lodash": "^4.17.21",
        "vite": "^2.7.9",
        "autoprefixer": "^10.4.0",
        "postcss": "^8.4.5",
        "tailwindcss": "^3.0.7",
        "@inertiajs/inertia": "^0.10.1",
        "@inertiajs/inertia-react": "^0.7.1",
        "react": "^17.0.2",
        "react-dom": "^17.0.2",
        "@inertiajs/progress": "^0.2.6"
        "@vitejs/plugin-react": "^1.1.3"
   }
}
Enter fullscreen mode Exit fullscreen mode

Add a tailwind.config.js file and a postcss.config.js file

//tailwind.config.js
module.exports = {
    content: [
        "./resources/**/*.blade.php",
        "./resources/**/*.jsx",
        "./resources/**/*.js",
    ],
    theme: {
        extend: {},
    },
    plugins: [],
}
Enter fullscreen mode Exit fullscreen mode
//postcss.config.js
module.exports = {
    plugins: {
        tailwindcss: {},
        autoprefixer: {},
    },
}
Enter fullscreen mode Exit fullscreen mode

add file vite.config.js

// vite.config.js
import react from '@vitejs/plugin-react';

export default ({ command }) => ({
    base: command === 'serve' ? '' : '/build/',
    publicDir: 'fake_dir_so_nothing_gets_copied',
    build: {
        manifest: true,
        outDir: 'public/build',
        rollupOptions: {
            input: 'resources/js/app.js',
        },
    },

    plugins: [
        react(),
        //add blade plugin to reload page on change blade files
        {
            name: 'blade',
            handleHotUpdate({ file, server }) {
                if (file.endsWith('.blade.php')) {
                    server.ws.send({
                        type: 'full-reload',
                        path: '*',
                    });
                }
            },
        }
    ],
});
Enter fullscreen mode Exit fullscreen mode

add to resources/css/app.css

@tailwind base;
@tailwind components;
@tailwind utilities;
Enter fullscreen mode Exit fullscreen mode

change resources/js/app.js file
Do not try to use JSX components The file is JS and compilation will fail.

The truth is at first I tried like that
render(App({...props}), el)
It caused this error

/*This file is not JSX so VITE will not automatically inject the React import*/
import React from 'react'
import {render} from 'react-dom'
import {createInertiaApp} from '@inertiajs/inertia-react'

import '../css/app.css';//import the app css

createInertiaApp({
    resolve: async (name) => {
        return (await import(`./Pages/${name}`)).default
    },
    setup({el, App, props}) {
        render(React.createElement(App, props), el)
    },
})
Enter fullscreen mode Exit fullscreen mode

Excellent, now just need to take care of bringing the files to the app.blade.php

add Helpers/vite.php file ( make the Helpers directory )

<?php

use Illuminate\Support\Facades\Http;
use Illuminate\Support\HtmlString;

function vite_assets(): HtmlString
{
    $devServerIsRunning = false;

    if (app()->environment('local')) {
        try {
            Http::get("http://localhost:3000");
            $devServerIsRunning = true;
        } catch (Exception) {
        }
    }

    if ($devServerIsRunning) {
        return new HtmlString(<<<HTML
            <script type="module">
                import RefreshRuntime from "http://localhost:3000/@react-refresh"
                RefreshRuntime.injectIntoGlobalHook(window)
                window.\$RefreshReg$ = () => {}
                window.\$RefreshSig$ = () => (type) => type
                window.__vite_plugin_react_preamble_installed__ = true
            </script>
            <script type="module" src="http://localhost:3000/@vite/client"></script>
            <script type="module" src="http://localhost:3000/resources/js/app.js"></script>
        HTML);
    }

    $manifest = json_decode(file_get_contents(
        public_path('build/manifest.json')
    ), true);

    return new HtmlString(<<<HTML
        <script type="module" src="/build/{$manifest['resources/js/app.js']['file']}"></script>
        <link rel="stylesheet" href="/build/{$manifest['resources/js/app.js']['css'][0]}">
    HTML);
}
Enter fullscreen mode Exit fullscreen mode

add function to app.blade.php head

<!-- Scripts -->
{ vite_assets() }}
Enter fullscreen mode Exit fullscreen mode

Add autoload to the new file you just created
include it to composer.json

"autoload": {
     "psr-4": {
          ...
     },
    "files": [
         "app/Helpers/vite.php"
    ]
},
Enter fullscreen mode Exit fullscreen mode

Just a few runs at the terminal:

to autoload file

composer dump-autoload
Enter fullscreen mode Exit fullscreen mode

require the inetria to server side

composer require inertiajs/inertia-laravel
Enter fullscreen mode Exit fullscreen mode

install npm packages

npm install
Enter fullscreen mode Exit fullscreen mode

That is!
from now on redirect routers to Inertia::render as shown here

Discussion (0)