Using Gradle's Kotlin DSL to Bundle React With a Spring Boot Web Application
Tags: tutorial, webdev, react, kotlin
Published: 2020-04-26 14:57:48

#Putting Together a Full-Stack Codebase
I was recently looking for a way to serve a [React](https://reactjs.org/) application in a [Spring Boot](https://spring.io/projects/spring-boot) microservice and have the two  together in a single, unified, and manageable codebase. If you're working for a large company, then it's usually best to keep the two separate. However, this is just for my personal projects and one repository to keep track of helps with velocity. 

#An Overview
For those unfamiliar with the [Spring Framework](https://spring.io/), it is a collection of different projects that make application development easier for [Java](https://www.oracle.com/java/) and [Kotlin] (https://kotlinlang.org/) developers. [Spring Boot](https://spring.io/projects/spring-boot) is a microservice starter and is one of those projects. Simply put, the `build.gradle.kts` in a Spring application is the equivalent of the `package.json` in a React project, as it has your dependencies and tasks (which are the same as scripts). 

Not too long ago, [Groovy](http://groovy-lang.org/) was the [domain-specific language](https://en.wikipedia.org/wiki/Domain-specific_language) (DSL) for the Gradle build file. I have seen various articles about achieving what I want to accomplish with Groovy, but I didn't see an examples using Kotlin, which has now become the default DSL. 

> A domain-specific language is a computer language specialized to a particular application domain. The build file in a Spring project is the application domain. 

#Spring Into Action

The [Spring Initialzr](https://start.spring.io/) can help you create an project and the only dependency you need is the **Spring Web** starter. 

The generated Spring Boot project structure will look like this:

```
├── gradle
│   └── wrapper
└── src
    ├── main
    │   ├── kotlin
    │   │   └── me
    │   │       └── darkes
    │   │           └── springbootreactgradlekotlin
    │   ├── resources
    └── test
        └── kotlin
            └── me
                └── darkes
                    └── springbootreactgradlekotlin
```


##Creating the React Application
Run the following command inside the `/src/main/` directory of your Spring Boot project.

```npx create-react-app webapp --use-npm```

This will go ahead and make a new directory called `/webapp` with your newly made React application.

##Setting Up the Gradle Build File

The whole process of having a combined codebase is possible because of the Gradle plugin, [Gradle Node Plugin](https://github.com/node-gradle/gradle-node-plugin).

In a Spring application the `resources/` directory is where we'd put our generated React `build/` files, because that is where a Spring application looks for static files to serve.

Add all of this to your `build.gradle.kts` file in your Spring Boot application root directory.
```kotlin

plugins {
    id("com.github.node-gradle.node") version "2.2.2"
}

tasks.register<NpmTask>("appNpmInstall") {
    description = "Installs all dependencies from package.json"
    workingDir = file("${project.projectDir}/src/main/webapp")
    args = listOf("install")
}

tasks.register<NpmTask>("appNpmBuild") {
    dependsOn("appNpmInstall")
    description = "Builds project"
    workingDir = file("${project.projectDir}/src/main/webapp")
    args = listOf("run", "build")
}

tasks.register<Copy>("copyWebApp") {
    dependsOn("appNpmBuild")
    description = "Copies built project to where it will be served"
    from("src/main/webapp/build")
    into("build/resources/main/static/.")
}

node {
    download = true
    version = "12.13.1"
    npmVersion = "6.12.1"
    // Set the work directory for unpacking node
    workDir = file("${project.buildDir}/nodejs")
    // Set the work directory for NPM
    npmWorkDir = file("${project.buildDir}/npm")
}

tasks.withType<KotlinCompile> {
    // So that all the tasks run with ./gradlew build
    dependsOn("copyWebApp")
    kotlinOptions {
        freeCompilerArgs = listOf("-Xjsr305=strict")
        jvmTarget = "1.8"
    }
}

```

##Building the Project
All you have to do is run `./gradlew build` from your project root directory. You'll notice after Gradle is finished, the React build directory is in the new location `build/resources/main/static/`.

If you want to see the application in action you can run `java -jar build/libs/PROJECT_NAME.jar` from the project root directory. Then visit `localhost:8080`.

##How It All Works

Typically with a normal React application you'll use `npm install` and `npm run build`. The Gradle plugin provides `NpmTask` to run those same commands. The tasks that I included are all that's needed to install, build and copy the files to where the Spring Boot application will notice them. Additionally, if you're someone who prefers [Yarn](https://yarnpkg.com/) or just wants to run a [Node.js](https://nodejs.org/en/) script, you can use this plugin to do that too! 

The code can be found here:
{% github iamdarkes/spring-boot-react-gradle-kotlin-dsl %}

I hope this was helpful. If you're used to using another language or technology for your server-side code, this starter is a great way to give Kotlin and Spring Boot a try.