DEV Community

Simcha
Simcha

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

Top comments (1)

Collapse
 
danielrios549 profile image
Daniel Rios

For me, the parameter of resolve callback is undefined, this is the name of the route passed by Laravel backend, without it nothing works...