Simple guide to setup React as the view layer for AdonisJS using InertiaJS (https://github.com/eidellev/inertiajs-adonisjs).
This is a rough setup guide, I intend to do a more fleshed out blog post style guide in future, or maybe even a generator.
Feel free to open a PR or issue with comments / suggestions.
This repo is a working example, do the following to see it in action:
git clone [email protected]:kevinchar93/csr-adonis-inertia-react.git
cd csr-adonis-inertia-react
npm install
node ace serve --watch
Navigate to http://127.0.0.1:3333
Based on:
- https://dev.to/eidellev/getting-started-with-adonisjs-and-inertia-js-2po0
- https://github.com/eidellev/inertiajs-adonisjs
- https://adocasts.com/lessons/adding-inertiajs-to-a-new-adonisjs-project
npm init adonis-ts-app@latest csr-adonis-inertia-react
❯ Select the project structure · web
❯ Enter the project name · csr-adonis-inertia-react
❯ Setup eslint? (y/N) · true
❯ Setup prettier? (y/N) · true
❯ Configure webpack encore for compiling frontend assets? (y/N) › true
npm i @eidellev/inertia-adonisjs
node ace configure @eidellev/inertia-adonisjs
❯ Enter the edge file you would like to use as your entrypoint · app
❯ Would you like to install the Inertia.js client-side adapter? (Y/n) · true
❯ Would you like to use SSR? (y/N) · false
❯ Which client-side adapter would you like to set up? · @inertiajs/inertia-react
Add Inertia middleware to start/kernel.ts
:
Server.middleware.register([
() => import('@ioc:Adonis/Core/BodyParser'),
() => import('@ioc:EidelLev/Inertia/Middleware'),
]);
By default Webpack Encore (AdonisJS asset bundler) is configured for JS, we want to use TS in our app, let's configure support for TS.
Install ts-loader
and @babel/preset-react
so Encore knows how to bundle Typescript files and JSX syntax.
npm install ts-loader @babel/preset-react --save-dev
Modify the entrypoint, edit webpack.config.js
changing the following:
Encore.addEntry('app', './resources/js/app.js')
into:
Encore.addEntry('app', './resources/js/app.tsx')
Encore.enableTypeScriptLoader()
Encore.enableReactPreset()
Rename ./resources/js/app.js
to ./resources/js/app.tsx
.
Create a file ./resources/js/tsconfig.json
, with contents:
{
"include": ["**/*"],
"compilerOptions": {
"lib": ["DOM"],
"jsx": "react",
"esModuleInterop": true
}
}
Also in the file tsconfig.json
at the root of your project add the following to the "compilerOptions" section
"lib": ["DOM"],
"jsx": "react",
This is to prevent warnings about using jsx
syntax in your .tsx
files down resources\js
& so you can use the document object directly without errors.
Running the config script earlier for the Inertia JS Provdier (node ace configure @eidellev/inertia-adonisjs
) should have generated this file: resources\views\app.edge
.
Its contents should be:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/png" href="/favicon.ico">
@entryPointStyles('app')
@entryPointScripts('app')
<title>csr-adonis-inertia-react</title>
</head>
<body>
@inertia
</body>
</html>
Now configure the app entrypoint file resources/js/app.tsx
to contain:
import { InertiaApp } from '@inertiajs/inertia-react'
import React from 'react'
import ReactDOM from 'react-dom'
import '../css/app.css'
// initial page object with props from server
const root = document.getElementById('app')
const page = JSON.parse(root?.dataset.page as string)
// dynamically load specified page component from "resources/js/Pages/." dir
async function resolver(pageName) {
const module = await import(`./Pages/${pageName}`)
return module.default
}
function App() {
return <InertiaApp initialPage={page} resolveComponent={resolver} initialComponent={''} />
}
ReactDOM.render(<App />, root)
Create a test component resources/js/Pages/Test.tsx
, with contents:
import React from 'react'
const Test = ({exampleProp}) => <div>Hello world, from {exampleProp}!)</div>
export default Test
Create a test route start/routes.ts
, contents:
import Route from '@ioc:Adonis/Core/Route'
Route.get('/test', async ({ inertia }) => {
return inertia.render('Test', { exampleProp: 'inertia' })
})
Boot up your server with node ace serve --watch
& navigate to http://127.0.0.1:3333/test
Voilà! ...you should now have a page rendered using React + Inertia JS served by your Adonis JS application.