Grails Adapter for Inertia.js
Owner: matrei | 1.2.0 | Feb 22, 2023 | Package | Issues | Source | Documentation | License: Apache-2.0
dependencies {
compile 'io.github.matrei:grails-inertia-plugin:1.2.0'
}
Grails Adapter for Inertia.js
Grails plugin for using Inertia.js to build single-page apps without building an API.
What is Inertia.js?
Inertia.js lets you, in its own words, “quickly build modern single-page React, Vue and Svelte apps using classic server-side routing and controllers”.
Using Inertia.js allows using your favorite MVC server-side framework (Grails obviously) with your favorite client-side SPA framework - no need to build a separate API.
Demo
A port (using this plugin) of the original Laravel/PHP Inertia.js Ping CRM demo is available.
Installation
If you don't have an application already:
grails create-app myapp
cd myapp
Add the plugin dependency to the project:
// myapp/build.gradle
dependencies {
//...
// Replace $inertiaPluginVersion with a suitable release version for your project, or define it in ~/myapp/gradle.properties
implementation "io.github.matrei:grails-inertia-plugin:$inertiaPluginVersion"
//...
}
To add the client dependencies and workflow to a Grails project, create the following files (Vue 3 example):
// myapp/package.json (versions @ 2023-03-01)
{
"name": "myapp",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vite --port 3000",
"build": "vite build"
},
"dependencies": {
"@inertiajs/vue3": "^1.0.2",
"vue": "^3.2.47"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.0.0",
"vite": "^4.1.4"
}
}
// myapp/vite.config.js
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig(({ command }) => ({
base: command === 'serve' ? '' : '/static/dist/',
publicDir: false,
build: {
manifest: true,
outDir: 'src/main/resources/public/dist',
assetsDir: 'js',
rollupOptions: {
input: 'src/main/javascript/main.js'
}
},
plugins: [vue()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src/main/javascript', import.meta.url))
}
},
server: {
// Needed for changes to picked up when running in WSL on Windows
watch: {
usePolling: true
}
}
}))
// myapp/src/main/javascript/main.js
import { createApp, h } from 'vue'
import { createInertiaApp } from '@inertiajs/vue3'
createInertiaApp({
resolve: async (name) => {
const pages = import.meta.glob('./Pages/**/*.vue')
return (await pages[`./Pages/${name}.vue`]()).default
},
setup ({el, App, props, plugin}) {
createApp({ render: () => h(App, props) })
.use(plugin)
.mount(el)
}
})
It can be a good idea to add the following entries to your .gitignore
# myapp/.gitignore
# ...
node_modules
src/main/resources/public/dist
And run:
npm install
Usage
In your controllers, you can now select which JavaScript Page Component to render and pass the values of the props to it.
// myapp/grails-app/controllers/myapp/BookController.groovy
package myapp
class BookController {
BookService bookService
def index() {
def books = bookService.listBooks()
renderInertia 'Books/Index', [books: books]
}
}
Here is an example Vue 3 Single File Component to that will render the books as a list.
<!-- myapp/src/main/javascript/Pages/Books/Index.vue -->
<script setup>
defineProps({ books: Array })
</script>
<template>
<ul>
<li v-for="book in books">{{ book.name }}</li>
</ul>
</template>
For development with Hot Module Replacement of the application run: (in separate terminals)
npm run serve
./gradlew bootRun
For production or test, first build production version of JavaScript app:
npm run build
and then run whatever you want to do:
./gradlew integrationTest
./gradlew bootJar