|
1 | 1 | # Inertia + Leaf |
| 2 | + |
| 3 | +[Inertia](https://inertiajs.com/) is a new approach to building classic server-driven web apps. It allows you to create fully client-side rendered, single-page apps, without the complexity that comes with modern SPAs. |
| 4 | + |
| 5 | +In short, Inertia let's you use your favourite frontend framework together with Leaf, reaping the benefits of both. While it's still more popular to build completely separate frontend and backends, combining them lets you have your code in one place. |
| 6 | + |
| 7 | +## Setting Up |
| 8 | + |
| 9 | +We've simplified the whole setup process into one command for you. Whether you are using Leaf MVC or just Leaf, you can use the CLI to scaffold a basic UI integration using your preferred frontend tooling. |
| 10 | + |
| 11 | +To get started, you can run: |
| 12 | + |
| 13 | +::: code-group |
| 14 | + |
| 15 | +```bash:no-line-numbers [Leaf CLI] |
| 16 | +leaf view:install |
| 17 | +``` |
| 18 | + |
| 19 | +```bash:no-line-numbers [Leaf MVC CLI] |
| 20 | +php leaf view:install |
| 21 | +``` |
| 22 | + |
| 23 | +::: |
| 24 | + |
| 25 | +This will prompt you to select your preferred frontend framework. You can choose from Vue, React, and Svelte. There is also support for styling with Tailwind/Bootstrap. After selecting your preferred framework, Leaf will automatically install and setup inertia for you, including examples for you to get started with. |
| 26 | + |
| 27 | +::: tip view:install |
| 28 | + |
| 29 | +If you know the specific frontend framework you want to use, you can pass the `--{framework}` flag to the `view:install` command. For example, to install inertia for Vue, you can run: |
| 30 | + |
| 31 | +```bash |
| 32 | +php leaf view:install --vue |
| 33 | +``` |
| 34 | + |
| 35 | +::: |
| 36 | + |
| 37 | +To run your app, you'll need to start two servers. One to actively bundle your frontend dependencies (your framework, styles, ...): |
| 38 | + |
| 39 | +::: code-group |
| 40 | + |
| 41 | +```bash:no-line-numbers [Leaf CLI] |
| 42 | +leaf view:dev |
| 43 | +``` |
| 44 | + |
| 45 | +```bash:no-line-numbers [npm] |
| 46 | +npm i && npm run dev |
| 47 | +``` |
| 48 | + |
| 49 | +```bash:no-line-numbers [pnpm] |
| 50 | +pnpm i && pnpm run dev |
| 51 | +``` |
| 52 | + |
| 53 | +```bash:no-line-numbers [yarn] |
| 54 | +yarn && yarn dev |
| 55 | +``` |
| 56 | + |
| 57 | +::: |
| 58 | + |
| 59 | +And then your main Leaf server which will run your app: |
| 60 | + |
| 61 | +::: code-group |
| 62 | + |
| 63 | +```bash:no-line-numbers [Leaf CLI] |
| 64 | +leaf serve |
| 65 | +``` |
| 66 | + |
| 67 | +```bash:no-line-numbers [Leaf MVC CLI] |
| 68 | +php leaf serve |
| 69 | +``` |
| 70 | + |
| 71 | +::: |
| 72 | + |
| 73 | +If you want to read more on why 2 servers are necessary, you can check out the [Leaf + Vite documentation](/docs/frontend/vite#vite-other-frameworks) |
| 74 | + |
| 75 | +## Setting up your routes |
| 76 | + |
| 77 | +Adding Inertia to your Leaf app doesn't change the way you handle routing, it just replaces your PHP views with your frontend framework. This means you are still going to use Leaf's routing system to handle your routes: |
| 78 | + |
| 79 | +```php |
| 80 | +app()->get('/', function () { |
| 81 | + echo 'This is a route'; |
| 82 | +}); |
| 83 | +``` |
| 84 | + |
| 85 | +The only difference is that you need to return an Inertia response instead of a normal response. You can do this by using the `Inertia::render` method: |
| 86 | + |
| 87 | +```php |
| 88 | +app()->get('/', function () { |
| 89 | + Inertia::render('Home'); |
| 90 | +}); |
| 91 | +``` |
| 92 | + |
| 93 | +The `Home` argument is the name of the file you created in your components directory. |
| 94 | + |
| 95 | +## Passing data to your Views |
| 96 | + |
| 97 | +You can also pass data from your Leaf app to your frontend framework by passing an array as the second argument to the `Inertia::render` method: |
| 98 | + |
| 99 | +```php |
| 100 | +app()->get('/', function () { |
| 101 | + return Inertia::render('Home', [ |
| 102 | + 'name' => 'Leaf', |
| 103 | + ]); |
| 104 | +}); |
| 105 | +``` |
| 106 | + |
| 107 | +If you have used any templating engine before, this should look really familiar to you. |
| 108 | + |
| 109 | +For this example, we're passing a `name` variable to our frontend framework which we can access in our frontend framework as props. You can then access the `name` prop like this: |
| 110 | + |
| 111 | +::: code-group |
| 112 | + |
| 113 | +```jsx [React] |
| 114 | +import Layout from './Layout'; |
| 115 | +import { Head } from '@inertiajs/react'; |
| 116 | + |
| 117 | +export default function Home({ name }) { |
| 118 | + return ( |
| 119 | + <Layout> |
| 120 | + <Head title="Welcome" /> |
| 121 | + <h1>Welcome</h1> |
| 122 | + <p>Hello {name}, welcome to your first Inertia app!</p> |
| 123 | + </Layout> |
| 124 | + ); |
| 125 | +} |
| 126 | +``` |
| 127 | + |
| 128 | +```jsx [Home.vue] |
| 129 | +<script setup> |
| 130 | +import Layout from './Layout'; |
| 131 | +import { Head } from '@inertiajs/vue3'; |
| 132 | + |
| 133 | +defineProps({ name: String }); |
| 134 | +</script> |
| 135 | + |
| 136 | +<template> |
| 137 | + <Layout> |
| 138 | + <Head title="Welcome" /> |
| 139 | + <h1>Welcome</h1> |
| 140 | + <p>Hello {{ name }}, welcome to your first Inertia app!</p> |
| 141 | + </Layout> |
| 142 | +</template> |
| 143 | +``` |
| 144 | + |
| 145 | +```svelte [Home.svelte] |
| 146 | +<script> |
| 147 | + import Layout from './Layout.svelte'; |
| 148 | +
|
| 149 | + export let name |
| 150 | +</script> |
| 151 | +
|
| 152 | +<Layout> |
| 153 | + <svelte:head> |
| 154 | + <title>Welcome</title> |
| 155 | + </svelte:head> |
| 156 | + <H1>Welcome</H1> |
| 157 | + <p>Hello {name}, welcome to your first Inertia app!</p> |
| 158 | +</Layout> |
| 159 | +``` |
| 160 | + |
| 161 | +::: |
| 162 | + |
| 163 | +You can find more information on using Inertia with your frontend framework in the [Inertia documentation](https://inertiajs.com/). |
| 164 | + |
| 165 | +## Manually setting up inertia |
| 166 | + |
| 167 | +If you don't want to use the Leaf CLI, you can manually setup inertia. This guide will show you how to setup inertia with Vite and React. You can use this guide to setup inertia with any frontend framework. |
| 168 | + |
| 169 | +### Setting up Vite |
| 170 | + |
| 171 | +To get started, you need to setup Vite. We have a Leaf plugin that takes care of a lot of the heavy lifting for you. We have a detailed guide on how to setup vite with Leaf [here](/docs/frontend/vite). |
| 172 | + |
| 173 | +```bash |
| 174 | +npm i -D vite @leafphp/vite-plugin |
| 175 | +leaf install vite |
| 176 | +``` |
| 177 | + |
| 178 | +### Vite Config |
| 179 | + |
| 180 | +The [Leaf Vite docs](/docs/frontend/vite#vite-config) have a detailed guide on how to setup vite config files. You should however note that for the best developer experience, you should point Vite to your view directory so you can enjoy hot module reloading. |
| 181 | + |
| 182 | +```js |
| 183 | +... |
| 184 | + |
| 185 | +export default defineConfig({ |
| 186 | + plugins: [ |
| 187 | + leaf({ |
| 188 | + ... |
| 189 | + refresh: ['yourviews/**'], |
| 190 | + }), |
| 191 | + ], |
| 192 | +}); |
| 193 | +``` |
| 194 | + |
| 195 | +Also note that your entry-point should be your base JavaScript file. For the best experience, CSS and other assets should be imported from your base JavaScript file. |
| 196 | + |
| 197 | +```js |
| 198 | +leaf({ |
| 199 | + input: ['js/app.jsx'], |
| 200 | + ... |
| 201 | +}), |
| 202 | +``` |
| 203 | + |
| 204 | +### Setting up Inertia |
| 205 | + |
| 206 | +To setup inertia, you need to install the inertia package for whatever frontend framework you want to use, together with the Vite plugin for that framework. For example, if you want to use React, you should install the Inertia React package, React Vite plugin as well as React itself: |
| 207 | + |
| 208 | +```bash |
| 209 | +npm i react react-dom @inertiajs/react @vitejs/plugin-react |
| 210 | +``` |
| 211 | + |
| 212 | +You should also install the Leaf Inertia PHP adapter: |
| 213 | + |
| 214 | +```bash |
| 215 | +leaf install inertia |
| 216 | +``` |
| 217 | + |
| 218 | +Or with composer: |
| 219 | + |
| 220 | +```bash |
| 221 | +composer require leafs/inertia |
| 222 | +``` |
| 223 | + |
| 224 | +After adding the React Vite plugin, you should add it to your vite config file: |
| 225 | + |
| 226 | +```js{3,10} |
| 227 | +import { defineConfig } from 'vite'; |
| 228 | +import leaf from '@leafphp/vite-plugin'; |
| 229 | +import react from '@vitejs/plugin-react'; |
| 230 | +
|
| 231 | +export default defineConfig({ |
| 232 | + plugins: [ |
| 233 | + leaf({ |
| 234 | + ... |
| 235 | + }), |
| 236 | + react(), |
| 237 | + ], |
| 238 | +}); |
| 239 | +``` |
| 240 | + |
| 241 | +### Setting up your base JavaScript file |
| 242 | + |
| 243 | +You should create a base JavaScript file that will be used to mount your app. This file should import your CSS and other assets. For example, if you're using React, your base JavaScript file should look like this: |
| 244 | + |
| 245 | +```jsx |
| 246 | +import { createRoot } from 'react-dom/client'; |
| 247 | +import { createInertiaApp } from '@inertiajs/react'; |
| 248 | +import { resolvePageComponent } from '@leafphp/vite-plugin/inertia-helpers'; |
| 249 | + |
| 250 | +const appName = import.meta.env.VITE_APP_NAME || 'Leaf PHP'; |
| 251 | + |
| 252 | +createInertiaApp({ |
| 253 | + title: (title) => `${title} - ${appName}`, |
| 254 | + resolve: (name) => |
| 255 | + resolvePageComponent( |
| 256 | + `./DIRECTORYFORCOMPONENTS/${name}.jsx`, |
| 257 | + import.meta.glob('./DIRECTORYFORCOMPONENTS/**/*.jsx') |
| 258 | + ), |
| 259 | + setup({ el, App, props }) { |
| 260 | + createRoot(el).render(<App {...props} />); |
| 261 | + }, |
| 262 | +}); |
| 263 | +``` |
| 264 | + |
| 265 | +`DIRECTORYFORCOMPONENTS` is the directory where your React pages are located. You can change this to whatever you want. You should also change the `setup` function to match your frontend framework. For example, if you're using Vue, you should change the `setup` function to: |
| 266 | + |
| 267 | +```js |
| 268 | +setup({ el, App, props }) { |
| 269 | + createApp({ |
| 270 | + render: () => h(App, props), |
| 271 | + }).mount(el); |
| 272 | +}, |
| 273 | +``` |
| 274 | + |
| 275 | +### Setting up your base PHP file |
| 276 | + |
| 277 | +You should create a base PHP file that will be used to render your app. By default, the Leaf Inertia PHP adapter will look for a file named `_inertia.view.php` in your views directory. You can change this by passing the path to your base PHP file to the `Inertia::setRoot` method. |
| 278 | + |
| 279 | +```php |
| 280 | +Inertia::setRoot('myfiles/_base'); |
| 281 | +``` |
| 282 | + |
| 283 | +Since the Leaf Inertia PHP adapter is built using the [Bare UI engine](/modules/views/bareui/), your base file needs to maintain the `.view.php` extension. For example, if you're using React, your base PHP file should look like this: |
| 284 | + |
| 285 | +```php |
| 286 | +<!DOCTYPE html> |
| 287 | +<html lang="en"> |
| 288 | + |
| 289 | +<head> |
| 290 | + <meta charset="UTF-8"> |
| 291 | + <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| 292 | + <title inertia>Document</title> |
| 293 | + <?php echo \Leaf\Vite::reactRefresh(); ?> |
| 294 | + <?php echo vite(['/js/app.jsx', "/js/Pages/{$page['component']}.jsx"]); ?> |
| 295 | + <?php |
| 296 | + if (!isset($__inertiaSsrDispatched)) { |
| 297 | + $__inertiaSsrDispatched = true; |
| 298 | + $__inertiaSsrResponse = (new \Leaf\Inertia\Ssr\Gateway())->dispatch($page); |
| 299 | + } |
| 300 | + |
| 301 | + if ($__inertiaSsrResponse) { |
| 302 | + echo $__inertiaSsrResponse->head; |
| 303 | + } |
| 304 | + ?> |
| 305 | +</head> |
| 306 | + |
| 307 | +<body> |
| 308 | + <?php |
| 309 | + if (!isset($__inertiaSsrDispatched)) { |
| 310 | + $__inertiaSsrDispatched = true; |
| 311 | + $__inertiaSsrResponse = (new \Leaf\Inertia\Ssr\Gateway())->dispatch($page); |
| 312 | + } |
| 313 | + |
| 314 | + if ($__inertiaSsrResponse) { |
| 315 | + echo $__inertiaSsrResponse->body; |
| 316 | + } else { |
| 317 | + echo '<div id="app" data-page="' . json_encode($page) . '"></div>'; |
| 318 | + } |
| 319 | + ?> |
| 320 | +</body> |
| 321 | + |
| 322 | +</html> |
| 323 | +``` |
| 324 | + |
| 325 | +This might look pretty ugly, but you'll never have to touch this file again. You can also use the Leaf CLI to generate this file for you: |
| 326 | + |
| 327 | +```bash |
| 328 | +leaf view:install --inertia |
| 329 | +``` |
| 330 | + |
| 331 | +### Setting up your frontend framework |
| 332 | + |
| 333 | +In the setup above, we told Inertia to look for our frontend framework files in `./DIRECTORYFORCOMPONENTS/`. You should create this directory and add your frontend framework files to it. For example, if you're using React, you should create a file named `Home.jsx` in this directory: |
| 334 | + |
| 335 | +```jsx |
| 336 | +const Home = () => { |
| 337 | + return ( |
| 338 | + <div> |
| 339 | + <h1>Hello World</h1> |
| 340 | + </div> |
| 341 | + ); |
| 342 | +}; |
| 343 | + |
| 344 | +export default Home; |
| 345 | +``` |
0 commit comments