First React.js "Hello World" with Laravel & Vite

Let's install a new Laravel project and add some static text to the welcome page. But that static text would come from the React.js component, and not from the Blade.



Step 1/4. Create Laravel HTML/Blade Project 

In the Terminal, we run:

laravel new project


I'm using Laravel Valet which prepares a subdomain for me, so this is what I see as the homepage:



Let's go to resources/views/welcome.blade.php and add some static HTML like <h1> tag:

<div class="flex justify-center pt-8 sm:justify-start sm:pt-0">    
    <svg viewBox="0 0 651 192" fill="none" xmlns="http://www.w3.org/2000/svg" class="h-16 w-auto text-gray-700 sm:h-20">        
        <g clip-path="url(#clip0)" fill="#EF3B2D">        
        <!-- ... official Laravel logo -->        
        </g>    
    </svg>
</div>

<h1>Hello World from Blade</h1>

<div>
<!-- ... other text -->
</div>


This is how it looks now:


So, the goal of our lesson is to replace that <h1> with a React.js component.




Step 2/4. Create the React.js Component


We create a file resources/js/components/HelloWorld.jsx, with this code inside:

export default function HelloWorld() {
    return (
        <div>Hello World from React.</div>
    )
}


In here, we just return the static text as a JSX language.

Keep in mind, that for Vite to work with React, all components that use JSX language, need to have extension of .jsx and not .js.

Then, in our resources/views/welcome.blade.php file we change the old <h1> to this code - <div id="app"></div>:

<div class="flex justify-center pt-8 sm:justify-start sm:pt-0">    
    <svg viewBox="0 0 651 192" fill="none" xmlns="http://www.w3.org/2000/svg" class="h-16 w-auto text-gray-700 sm:h-20">        
        <g clip-path="url(#clip0)" fill="#EF3B2D">        
        <!-- ... official Laravel logo -->        
        </g>    
    </svg>
</div>

<div id="app"></div>

<div>
<!-- ... other text -->
</div>


See this <div id="app"></div>?
This is exactly the place, where our React.js application will live. So, the whole project template is Blade, but inside of that, you can choose any internal HTML tag to be dynamic and contain React. 

For that, you assign id="whatever-name" to it, and then you will mount the React.js application to specifically that tag id. We'll get to that in a few minutes.




Step 3/4. Install React and configure Vite 


Now, let's pay attention to how our future React.js components will be built after we write their code. 

This process changed from Laravel v9.19 when they changed the default front-end asset bundler tool from Laravel Mix to Vite.
From July 2022, we need to configure Vite in the file vite.config.js, which is in the main Laravel folder and partly already pre-filled for us. Before that, you would need to work with webpack.mix.js file.

To enable Vite so it would work with our main resources/js/app.js and resources/css/app.css files, in the resources/views/welcome.blade.php we add this Blade directive before </head>:

    @viteReactRefresh
    @vite(['resources/js/app.jsx', 'resources/css/app.css'])
</head>


It instructs the application to run Vite and build those two JS and CSS files to use in the browser.
Notice the important part: it's app.jsx and not the default Laravel app.js. We'll get to that file's contents, in a minute.

Vite itself doesn't know anything about React.js or any other JS framework, the default vite.config.js is only about Laravel:

import { defineConfig } from 'vite'
import laravel from 'laravel-vite-plugin'

export default defineConfig({    
    plugins: [        
        laravel([            
            'resources/css/app.css',            
            'resources/js/app.js',
        ]),
    ],
});


If you open the file in the IDE like PhpStorm, you may notice that 'vite' and 'laravel-vite-plugin' are underlined, as not installed yet.

But they are listed among the front-end packages in the main package.json file:

{
    "private": true,
    "scripts": {
        "dev": "vite",
        "build": "vite build"
    },
    "devDependencies": {
        "axios": "^0.25",
        "laravel-vite-plugin": "^0.2.1",
        "lodash": "^4.17.19",
        "postcss": "^8.1.14",
        "vite": "^2.9.11"
    }
}


So to install them, we run:

npm install


Now, they shouldn't be underlined anymore, and let's add React.js to them.


We install React itself:

npm install react@18 react-dom@18

Here, you may specify a specific version, like React 18, or just react@latest which will install the latest version.


Also, for React to work with Vite, we need to install a specific plugin:

npm i @vitejs/[email protected]

Notice that we're using a specific version 1.3.2 here, which is compatible with the default Vite 2 version which is active in Laravel.

And now, we add both of those into the vite.config.js:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import react from '@vitejs/plugin-react';

export default defineConfig({
    plugins: [
        laravel([
            'resources/css/app.css',            
            'resources/js/app.jsx',
        ]),
        react(),
    ],
});


We add import react and react() with no parameters. Also, notice that I've renamed resources/js/app.js to resources/js/app.jsx. This is exactly the file we will deal with, next.




Step 4/4. Load React.js Component into Blade


So, at this point:

- We have a React component
- We have a place id="app" to load it to
- We have installed React and configured Vite

Finally, we tie it all together by creating a React application in the resources/js/app.jsx file - renaming the old default Laravel resources/js/app.js. At the bottom of the import './bootstrap' line, we add these:

import ReactDOM from 'react-dom/client';		
import HelloWorld from './components/HelloWorld';

ReactDOM.createRoot(document.getElementById('app')).render(		
    <HelloWorld />		
);


I think it's all self-explanatory, but I will reiterate: we import the component and mount it to the <div id="app"> from the Blade file.

Now, we need to start the Vite server, by running:

npm run dev


Here's how it looks in the Terminal:


And that's it, Vite server will stay running, waiting for you to make changes in the React files.



Optional Step: Vite - Load CSS from JS


I see that some developers prefer to import the CSS into the JS file, to not reference it twice. So, you may make such changes.

In vite.config.js - remove CSS, and leave only JSX:

plugins: [
    laravel([
        'resources/js/app.jsx',
    ]),


In resources/js/app.js - import CSS on top:

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


Finally, in resources/views/welcome.blade.php leave also only JS, no CSS needed here:

@vite('resources/js/app.jsx')


Visually, nothing will change, but I see many developers doing this change, so I thought to include it here, so you wouldn't get confused.


Complete and Continue  
Discussion

2 comments