Contents

How to bootstrap a Micronaut Vue SPA

Bootstrapping a Micronaut Vue Single Page Application is straightforward and similar to the approach you would take if doing with React. The result is a gradle multi project build consisting of a client and server subprojects.

1. Create client project

In the client folder create a new Vue project using the vue-cli. Add the following build.gradle file.

plugins {
    id "com.github.node-gradle.node" version "2.2.4"
}

node {
    version = '10.13.0' // https://nodejs.org/en/
    yarnVersion = '1.22.5' // https://yarnpkg.com/en/
    download = true
}

task serve(type: YarnTask, dependsOn: 'yarn') {
    group = 'application'
    description = 'Run the client app'
    args = \['run', 'serve'\]
}

task build(type: YarnTask, dependsOn: 'yarn') {
    group = 'build'
    description = 'Build the client bundle'
    args = \['run', 'build'\]
}

task lint(type: YarnTask, dependsOn: 'yarn') {
    group = 'build'
    description = 'Run eslint'
    args = \['run', 'lint'\]
}

We make use of the node-gradle plugin to allow us to run the vue-cli commands in gradle, in particular the build and serve commands needed to run the app.

2. Create the server project

For the server we create a basic Micronaut application using the create-app command. The key things to note here as stated in the React guide is you need to allow the server to serve static resource. So in application.yml add the following:

micronaut:
  router:
    static-resources:
      default:
        enabled: true   
        mapping: "/\*\*"  
        paths: "classpath:public" 

And you also need to enable CORS for the client to communicate with the backend:

micronaut:
  server:
    cors:
      enabled: true

3. Combine the projects

The final step involves taking the static files generated by the yarn build and copying them to the static resources folder of the server project before generating a jar file. This is in a similar fashion to what we did for the Grails Vue profile.

We achieve this by adding the following tasks in the parent project’s build.gradle file.

task copyClientResources(dependsOn: ':client:build', type: Copy) {
    group = 'build'
    description = 'Copy client resources into server'
    from "${project(':client').projectDir}/dist"
    into "${project(':server').buildDir}/resources/main/public"
}
task assembleServerAndClient(type: Copy, dependsOn: \['copyClientResources', ':server:shadowJar'\]) {
    group = 'build'
    description = 'Build combined server & client JAR'
    from fileTree(dir: "${project(':server').buildDir}/libs/")
    into "${rootProject.buildDir}"
    doLast {
        logger.quiet "JAR generated at ${rootProject.buildDir}. It combines the server and client projects."
    }
}
project(":server").getTasksByName('shadowJar', true)\[0\].mustRunAfter(copyClientResources)

With this you can run ./gradlew assembleServerAndClient or ./gradlew build from the parent project to get an executable jar.

If you run the jar and navigate to the app url in the browser you should see the Micronaut Vue app running.

A working example built using Micronaut 2.2.0 can be found on GitHub.