Inertia.js adapter for Silverstripe, based on inertia-bundle.
Visit inertiajs.com to learn more.
Install the server adapter.
composer require cambis/silverstripe-inertia
Install the preferred client adapter.
yarn add -D @inertiajs/react
yarn add -D @inertiajs/vue3
yarn add -D @inertiajs/svelte
Here is a basic configuration to get started with.
First, configure your Silverstripe application with the following:
Create a config file:
---
Name: inertia
After:
- requestprocessors
---
SilverStripe\Core\Injector\Injector:
SilverStripe\Control\Director:
properties:
Middlewares:
InertiaMiddleware: '%$Cambis\Inertia\Control\Middleware\InertiaMiddleware'
PageController:
extensions:
- Cambis\Inertia\Extension\InertiaPageControllerExtension
In your root Page.ss
template, add:
<head>
...
+$InertiaHead($PageData)
</head>
<body>
-$Layout
+$InertiaBody($PageData)
...
</body>
The root template location is optionally configurable:
Cambis\Inertia\Inertia:
root_view: MyAlternativePage
Configure your PageController
class to serve Inertia.
use SilverStripe\CMS\Controllers\ContentController;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse;
class PageController extends ContentController
{
/**
* @return HTTPResponse
*/
public function index(HTTPRequest $request) {
return $this->inertia->render('Dashboard', ['prop' => 'value']);
}
}
If your IDE supports the @mixin
directive, add it to your PageController
for autocomplete:
+use Cambis\Inertia\Extension\InertiaPageControllerExtension;
use SilverStripe\CMS\Controllers\ContentController;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse;
+/**
+ * @mixin InertiaPageControllerExtension
+ */
class PageController extends ContentController
{
/**
* @return HTTPResponse
*/
public function index(HTTPRequest $request) {
return $this->inertia->render('Dashboard', ['prop' => 'value']);
}
}
Alternatively, you can use the @property
directive:
+use Cambis\Inertia\Inertia;
use SilverStripe\CMS\Controllers\ContentController;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse;
+/**
+ * @property Inertia $inertia
+ */
class PageController extends ContentController
{
/**
* @return HTTPResponse
*/
public function index(HTTPRequest $request) {
return $this->inertia->render('Dashboard', ['prop' => 'value']);
}
}
Once your Silverstripe application is setup, you can configure the client application.
import { createInertiaApp } from '@inertiajs/react';
import { createRoot } from 'react-dom/client';
createInertiaApp({
resolve: (name) => import(`./Pages/${name}`),
setup({ el, App, props }) {
createRoot(el).render(<App {...props} />);
},
});
import { createApp, h } from 'vue'
import { createInertiaApp } from '@inertiajs/vue3'
createInertiaApp({
resolve: (name) => import(`./Pages/${name}`),
setup({ el, App, props, plugin }) {
createApp({ render: () => h(App, props) })
.use(plugin)
.mount(el)
},
})
import { createInertiaApp } from '@inertiajs/svelte'
createInertiaApp({
resolve: (name) => import(`./Pages/${name}`),
setup({ el, App, props }) {
new App({ target: el, props })
},
})
Sometimes you don't want to re-evaluate data when making visits to the same page type. This can be accomplised
server-side by using a callback function or lazy()
.
Check the offical documentation for client side configuration.
return $this->inertia->render('Dashboard', [
// ALWAYS included on first visit...
// OPTIONALLY included on partial reloads...
// ALWAYS evaluated...
'foo' => 'bar',
// ALWAYS included on first visit...
// OPTIONALLY included on partial reloads...
// ONLY evaluated when needed...
'foo' => static function (): string { return 'bar'; },
// NEVER included on first visit...
// OPTIONALLY included on partial reloads...
// ONLY evaluated when needed...
'foo' => $this->inertia->lazy(static function (): string { return 'bar'; }),
]);
You can share props between all components using the $this->inertia->share(string, mixed)
function.
One use case is populating the navigation menu for a website, this can be accomplished using a SilverStripe\Core\Extension
.
<?php
namespace App\Inertia\Extension;
use Page;
use PageController;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Core\Extension;
/**
* @method PageController&$this getOwner()
*/
class InertiaControllerMenuExtension extends Extension
{
public function beforeCallActionHandler(HTTPRequest $request, string $action): void
{
$inertia = $this->getOwner()->inertia;
$items = [];
/** @var Page $page */
foreach ($this->getOwner()->getMenu(1) as $page) {
$item = [
'id' => static function () use ($page): int {
return $page->ID;
},
'menuTitle' => static function () use ($page): string {
return $page->MenuTitle;
},
'link' => static function () use ($page): string {
return $page->Link();
},
];
$items[] = $item;
}
$inertia->share('menu', $items);
}
}
You can pass data to your root Silverstripe template via the render()
parameter in the render function:
return $this->inertia->render('Dashboard', ['prop' => 'value'], ['Title' => 'My title']);
You can also pass data using the $this->inertia->viewData(string, mixed)
function:
$this->inertia->viewData(['Title' => 'My title'])
Data is accessible using the $ViewData
variable
$ViewData.Title // 'My title'
By default, the middleware checks for the config variables asset_url
and manifest_file
to get the current asset version.
Cambis\Inertia\Inertia:
assert_url: https://example.cdn.com/manifest.json
# OR
Cambis\Inertia\Inertia:
manifest_file: /themes/default/dist/manifest.json
You can specify your application's asset version by extending the Cambis\Inertia\Control\Middleware\InertiaMiddleware
class.
namespace App\Inertia\Control\Middleware;
use Cambis\Inertia\Control\Middleware\InertiaMiddleware as BaseMiddleware;
use SilverStripe\Control\HTTPRequest;
class InertiaMiddleware extends BaseMiddleware
{
public function version(HTTPRequest $request): ?string
{
// Custom logic here
}
}
Don't forget to update your configuration if you do this!
SilverStripe\Core\Injector\Injector:
SilverStripe\Control\Director:
properties:
Middlewares:
- InertiaMiddleware: '%$Cambis\Inertia\Control\Middleware\InertiaMiddleware'
+ InertiaMiddleware: '%$App\Inertia\Control\Middleware\InertiaMiddleware'
Alternatively, you can use the $this->inertia->version(mixed)
function to set the current asset version
$this->inertia->version('foo');
$this->inertia->version(static function (): string { return 'foo'; }) // Lazily...
Check the offical documentation for information on cache busting.
To enable server-side rendering, first enable the following config variables ssr_enabled
and ssr_host
:
Cambis\Inertia\Inertia:
ssr_enabled: true
ssr_host: https://my-ssr-host/render
Check the official documentation for information on client-side setup.
You can find a basic demo here