React With Spring Boot Crash Course

React is a very popular javascript library for building user interfaces, that was originally developed by Facebook. React only deals with updating the view, so is depending on other frameworks for handing everything else.

Spring Boot is essentially an easy to setup java based environment that makes it simple to develop and deploy web applications based on the Spring framework.

Here we will look at creating an application with both React.js as the client UI and Spring Boot as the server.

React Components

A React UI is fundamentally built up of components. Components are how you define each part of the react UI that you see in the browser. Each of the components are built to be stand alone, and then brought together to create the complex UI you require.

A React UI will usually have a root or top level component that is the entry point for the starting point or entry point for the UI in React. This will be the parent component for other components that make up the React UI. For instance we can have lots of components that make up our UI and can be used by this page or many pages in the UI app.

Each component in a UI can be built seperately them integrated to build the compete UIs that we require.

React Class Components

A React component can be implemented as a javascript class component, that maintains its own state (the data), and presents that state in the UI using the render() method. The render() methods generates javascripts objects.

The DOM and the Virtual Dom

The DOM or Document Object Model is a way of accessing and describing elements in a document. The World Wide Web Consortium describe the DOM as

The W3C Document Object Model (DOM) is a platform and language-neutral interface that allows programs and scripts to dynamically access and update the content, structure, and style of a document.

https://www.w3schools.com/js/js_htmldom.asp

In the brower, documents are represent as HTML, and the DOM is the object model and programming interface used to access the elements of the DOM in the browser. So every time we change something in the UI the DOM needs to be updated, which of course comes with a performance overhead. So if we need to update the UI regularly, updating the DOM will take some time.

Updating the DOM is dependent on how many elements you have in your UI, so of course the more elements in the UI, the slower it will be to update. To help with this, React maintains its own DOM, known as the virtual DOM.

React will use the virtual DOM to determine what has changed in the UI. Rather than updating the whole of the real DOM, React will use some intelligence to figure out which elements in the UI have actually changed, and thus only update the parts of the real DOM that have changed rather than the whole DOM, thus improving performance.

Why Is React So Fast?

The other benefit of not using the real DOM is that changes to the virtual DOM can be managed by the React library. This is how React can change the UI based on change to the state of the components.

Setting Up The Eclipse Maven Project For Spring Boot

Lets go to start.spring.io/  to get what we need for Spring Boot with Rest Repositories, Thymeleaf, JPA and H2 as dependencies. We might not need all of these but as we used them previously lets grab them for now then we can remove them later if needed.

We fill in the following values at start.spring.io/.

Click Generate to download a project zip file. Unpack the zip.

Open eclipse, create a new java project called sprintbootreact2.

Create your source and test folders, heres my standard setup below.

Copy the contents of the downloaded zip file into the project and yu should end up with this

If we look in src/main/java, we get a default spring application.

package com.colwil.springbootreact2;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Springbootreact2Application {

	public static void main(String[] args) {
		SpringApplication.run(Springbootreact2Application.class, args);
	}

}

From the eclipse menu, select Run, Run Configurations, then scroll down to maven build.

Right click, new configuration and fill in the details. Click Apply, then Run.

REST Application Config

We arent doing anything with Spring Data REST at the moment, but lets adjust the URI for its REST endpoint in case we use it later.

Add the following property to the application.properties file already in the src/main/resources folder to adjust its default URI so it doesnt conflict with the UI we are going to build.

spring.data.rest.base-path=/api

Modify the build path in the POM for the maven eclipse plugin to ensure that application.properties is included in the build path, by setting filtering = false.

	</dependencies>

	<build>
	    <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>false</filtering>
            </resource>
        </resources>
		<plugins>

Setting Up The Spring MVC Controller For The React UI

Create a html page for the React components to live in. We do this by defining a Spring MVC controller and defining a Thymeleaf HTML template.

The Spring MVC Controller

The @Controller marks this as a Spring MVC controller, the request mapping maps slash to the index method and index is the prefix of the html page to use.

@Controller
public class HomeController {

	@RequestMapping(value = "/")
	public String index() {
		return "index";
	}

}

The index.html Thymeleaf template

The index.html template needs to resides in src/main/resources/templates folder. The react div is where the React.js components will appear.

<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<head lang="en">
    <meta charset="UTF-8"/>
    <title>ReactJS + Spring Boot</title>
    <link rel="stylesheet" href="/main.css" />
</head>
<body>

    <div id="react"></div>

    <script src="built/bundle.js"></script>

</body>
</html>

Installing Node.js and React.js Javascript Modules Using The Pom.xml

We need to use the frontend-maven-plugin to enable us to

  • Install node.js and npm package manager
  • Install the node.js modules configured in package.json
  • run webpack to compile all the JavaScript components into a single file

So lets add the plugin config for frontend-maven-plugin to our pom, and run the build. Spring Boot will server anything found in src/main/resources/static automatically, so thats how the main.css and bundle.js (built by webpack) will be found.

Heres the additional bits for the POM for the frontend-maven-plugin

        <plugin>
            <groupId>com.github.eirslett</groupId>
            <artifactId>frontend-maven-plugin</artifactId>
            <version>1.6</version>
            <configuration>
                <installDirectory>target</installDirectory>
            </configuration>
            <executions>
                <execution>
                    <id>install node and npm</id>
                    <goals>
                        <goal>install-node-and-npm</goal>
                    </goals>
                    <configuration>
                        <nodeVersion>v10.11.0</nodeVersion>
                        <npmVersion>6.4.1</npmVersion>
                    </configuration>
                </execution>
                <execution>
                    <id>npm install</id>
                    <goals>
                        <goal>npm</goal>
                    </goals>
                    <configuration>
                        <arguments>install</arguments>
                    </configuration>
                </execution>
                <execution>
                    <id>webpack build</id>
                    <goals>
                        <goal>webpack</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

we need to also create a package.json file to configure NPM

{
  "name": "reactjs-aand-sprintboot",
  "version": "0.1.0",
  "description": "Demo of ReactJS + Spring Boot",
  "repository": {
    "type": "git",
    "url": "git@github.com/colwildotcom/springbootreact2.git"
  },
  "keywords": [
    "rest",
    "hateoas",
    "spring",
    "data",
    "react"
  ],
  "author": "Colin Williams",
  "license": "Apache-2.0",
  "bugs": {
    "url": "https://github.com/colwildotcom/springbootreact2/issues"
  },
  "homepage": "https://github.com/colwildotcom/springbootreact2",
  "dependencies": {
    "react": "^16.10.2",
    "react-dom": "^16.10.2",
    "rest": "^2.0.0",
    "sockjs-client": "^1.4.0",
    "stompjs": "^2.3.3"
  },
  "scripts": {
    "watch": "webpack --watch -d"
  },
  "devDependencies": {
    "@babel/core": "^7.6.4",
    "@babel/preset-env": "^7.6.3",
    "@babel/preset-react": "^7.6.3",
    "babel-loader": "^8.0.6",
    "webpack": "^4.41.2",
    "webpack-cli": "^3.3.9"
  }
}

and also webpack.config.js to configure webpack.

var path = require('path');

module.exports = {
    entry: './src/main/js/app.js',
    devtool: 'sourcemaps',
    cache: true,
    mode: 'development',
    resolve: {
        alias: {
            'stompjs': __dirname + '/node_modules' + '/stompjs/lib/stomp.js',
        }
    },
    output: {
        path: __dirname,
        filename: './src/main/resources/static/built/bundle.js'
    },
    module: {
        rules: [
            {
                test: path.join(__dirname, '.'),
                exclude: /(node_modules)/,
                use: [{
                    loader: 'babel-loader',
                    options: {
                        presets: ["@babel/preset-env", "@babel/preset-react"]
                    }
                }]
            }
        ]
    }
};

also lets create the skeleton React.js app.js file

const React = require('react');
const ReactDOM = require('react-dom');

Lets run our maven eclipse build again

Success!

[INFO] Scanning for projects...
[INFO] 
[INFO] --------------------< com.colwil:springbootreact2 >---------------------
[INFO] Building springbootreact2 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-eclipse-plugin:2.10:clean (default-cli) @ springbootreact2 ---
[INFO] Deleting file: .project
[INFO] Deleting file: .classpath
[INFO] Deleting file: .wtpmodules
[INFO] Deleting file: .settings
[INFO] 
[INFO] >>> maven-eclipse-plugin:2.10:eclipse (default-cli) > generate-resources @ springbootreact2 >>>
[INFO] 
[INFO] --- frontend-maven-plugin:1.6:install-node-and-npm (install node and npm) @ springbootreact2 ---
[INFO] Installing node version v10.16.3
[INFO] Downloading https://nodejs.org/dist/v10.16.3/win-x64/node.exe to C:\Users\.m2\repository\com\github\eirslett\node\10.16.3\node-10.16.3-win-x64.exe
[INFO] No proxies configured
[INFO] No proxy was configured, downloading directly
[INFO] Copying node binary from C:\Users\.m2\repository\com\github\eirslett\node\10.16.3\node-10.16.3-win-x64.exe to C:\springbootreact2\target\node\node.exe
[INFO] Installed node locally.
[INFO] Installing npm version 6.12.0
[INFO] Downloading https://registry.npmjs.org/npm/-/npm-6.12.0.tgz to C:\Users\.m2\repository\com\github\eirslett\npm\6.12.0\npm-6.12.0.tar.gz
[INFO] No proxies configured
[INFO] No proxy was configured, downloading directly
[INFO] Unpacking C:\Users\.m2\repository\com\github\eirslett\npm\6.12.0\npm-6.12.0.tar.gz into C:\springbootreact2\target\node\node_modules
[INFO] Installed npm locally.
[INFO] 
[INFO] --- frontend-maven-plugin:1.6:npm (npm install) @ springbootreact2 ---
[INFO] Running 'npm install' in C:\springbootreact2
[INFO] 
[INFO] > websocket@1.0.30 install C:\springbootreact2\node_modules\websocket
[INFO] > (node-gyp rebuild 2> builderror.log) || (exit 0)
[INFO] 
[INFO] 
[INFO] C:\springbootreact2\node_modules\websocket>if not defined npm_config_node_gyp (node "C:\springbootreact2\target\node\node_modules\npm\node_modules\npm-lifecycle\node-gyp-bin\\..\..\node_modules\node-gyp\bin\node-gyp.js" rebuild )  else (node "C:\springbootreact2\target\node\node_modules\npm\node_modules\node-gyp\bin\node-gyp.js" rebuild ) 
[ERROR] npm notice created a lockfile as package-lock.json. You should commit this file.
[WARNING] npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9 (node_modules\fsevents):
[WARNING] npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.9: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
[ERROR] 
[INFO] added 538 packages from 271 contributors and audited 6771 packages in 246.887s
[INFO] found 0 vulnerabilities
[INFO] 
[INFO] 
[INFO] --- frontend-maven-plugin:1.6:webpack (webpack build) @ springbootreact2 ---
[INFO] Running 'webpack.js ' in C:\springbootreact2
[INFO] Hash: 2549115dcdb13a73e1db
[INFO] Version: webpack 4.41.2
[INFO] Time: 18724ms
[INFO] Built at: 10/17/2019 5:37:31 PM
[INFO]                                           Asset      Size  Chunks                   Chunk Names
[INFO]     ./src/main/resources/static/built/bundle.js  1.05 MiB    main  [emitted]        main
[INFO] ./src/main/resources/static/built/bundle.js.map  1.23 MiB    main  [emitted] [dev]  main
[INFO] Entrypoint main = ./src/main/resources/static/built/bundle.js ./src/main/resources/static/built/bundle.js.map
[INFO] [./src/main/js/app.js] 67 bytes {main} [built]
[INFO]     + 11 hidden modules
[INFO] 
[INFO] <<< maven-eclipse-plugin:2.10:eclipse (default-cli) < generate-resources @ springbootreact2 <<<
[INFO] 
[INFO] 
[INFO] --- maven-eclipse-plugin:2.10:eclipse (default-cli) @ springbootreact2 ---
[INFO] Using Eclipse Workspace: C:\
[INFO] Adding default classpath container: org.eclipse.jdt.launching.JRE_CONTAINER
[INFO] Not writing settings - defaults suffice
[INFO] File C:\springbootreact2\.project already exists.
       Additional settings will be preserved, run mvn eclipse:clean if you want old settings to be removed.
[INFO] Wrote Eclipse project for "springbootreact2" to C:\springbootreact2.
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 10:08 min
[INFO] Finished at: 2019-10-17T17:38:58+01:00
[INFO] ------------------------------------------------------------------------

Spring Boot and create-react-app

Many of the React.js tutorials you see will reference setting up your React.js application with the create-react-app npm command line tool. As we are setting up React.js to run out of Spring Boot it would be nice if we could so that as part of the build process.

So what does create-react-app actually do? Seems like it create a package.json file, does some other checks, and then downloads the selected version of react-scripts. So if we download the latest version of react-scripts, we should have everything we need for more tutorials.

So ive added react-scripts to the package.json file, and rerun the eclipse build script

    "react-scripts": "^3.2.0",
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 26:35 min
[INFO] Finished at: 2019-10-17T18:28:57+01:00
[INFO] ------------------------------------------------------------------------

Editing React.js Code With Visual Studio Code

I going to try editing my React.js javascript code with Microsofts Visual Studio Code rather than Eclipse, as it has better support for React. Will see how I get on with this, as many of the tutorials on youtube use it.

As per tutorials, I have added the following extensions

Prettier by Esben Petersen

Simple React Snippets by Burke Holland

ive also enabled format on save, settings, search for “format on save” and set to true.

Developing Your React.js App

While you are working on the React.js UI ,you want to be able to update the js code and see those changes reflected in the UI as quickly as possible. To help with that, its easier to create another React.js app, and have a Node.js server running to serve the UI changes.

  • Download the latest node.js and install from https://nodejs.org/en/download/
  • open a command window
  • Run npm install -g create-react-app to setup the react app creator
  • Go to where you want to create the react app and run create-react-app <app_name>
  • Run cd <app_name>
  • Run npm start

So we now have a node.js instance running on port 3000 that we can use to check our React.js code without rebuilding Spring Boot each time.

These are the files that got created in the reacto app that i generated

Lets delete those and start from scratch, and also open the source folder in visual studio. If we delete everything from the src folder and create a new index.js, notice that the browser window will automatically reload. This is because an application thats been automatically generated with create-react-app will be setup to automatically compile and reload in the browser.

Leave a Comment

Your email address will not be published. Required fields are marked *