Integrating Vue with Spring Boot

In this tutorial, I will show you step by step to integrate Vue.js with Spring Boot so that Spring Boot project can serve Vue App. You will also know how to configure Vue SPA Routing to avoid Whitelabel Error Page.

Vue & Spring Boot application Overview

Assume that we have 2 projects: Vue & Spring Boot:

For example, if we run them separately:

Using Vue to call Spring Rest API:

Otherwise, when deploying Vue production-build with Spring Boot project, we only need to run Spring Boot Project for the fullstack (Vue.js + Spring Boot) system.

In this example, we access http://localhost:8080/.

Technology Stack

  • Node.js
  • Vue 2.6
  • Vue Router 3
  • Vue Cli Service 4
  • Spring Boot 2
  • Spring Tool Suite
  • Maven 3.6.1

Setup Vue Client

You can use your own Vue.js Project, or just download the source code on Github, or follow these steps to create a new one.

Open cmd at the folder you want to save Project folder, run command:
vue create vue-js-crud

You will see some options, choose default (babel, eslint).
After the process is done. We create new folders and files like the following tree:

public
— index.html
src
— components
— — AddTutorial.vue
— — Tutorial.vue
— — TutorialsList.vue
— services
— — TutorialDataService.js
— App.vue
— main.js
package.json

Because I want to keep this tutorial simple and brief, please continue to develop this App with instruction in the post:
Vue.js 2 CRUD Application with Vue Router & Axios

Import Vue Project to Spring Tool Suite

Open Spring Tool Suite, right click on Package Explorer and choose Import -> General -> Projects from Folder or Archieve, press Next.

Find the Vue.js Project that we’ve just created above and press Finish, vue-js-crud is imported like this:

To clean the source code in STS, we need to remove node_modules folder by following the steps:

  • Right click on vue-js-crud project, choose Properties, then Resource -> Resource Filter.
  • Press Add Filter…, choose Filter Type: Exclude all, Applies to: Files and folders, and check All children (recursive), with ‘File and Folder Atributes’, we specify node_modules:

Press OK, then Apply, the result will be like this:

Setup Spring Boot Server

You can use your own Spring Boot Project, or just download the source code on Github, or follow these steps to create a new one.

Use Spring web tool or your development tool (Spring Tool Suite, Eclipse, Intellij) to create a Spring Boot project.

Then open pom.xml and add these dependencies:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>

The instruction can be found in the post:
Spring Boot, Spring Data JPA — Rest CRUD API example

Now we have 2 projects together in Spring Tool Suite:

Let’s continue to the most important part.

Integrating Vue.js with Spring Boot

Build Vue App

Currently Vue Client and Express server work independently on ports 8081 and 8080.

The first thing we need to do is to build Vue App for production.

Open package.json file, modify the scripts so that output files and folders will be stored in build folder:

{
...
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build --dest build",
"lint": "vue-cli-service lint"
},
...
}

Run command: npm run build

E:\STS\WorkPlace\vue-js-crud>npm run build> vue-js-client-crud@0.1.0 build E:\STS\WorkPlace\vue-js-crud
> vue-cli-service build --dest build
| Building for production...Browserslist: caniuse-lite is outdated. Please run next command `npm update
`
/ Building for production...Browserslist: caniuse-lite is outdated. Please run next command `npm update
`
| Building for production...
DONE Compiled successfully in 19202ms 6:50:36 PM File Size Gzipped build\js\chunk-vendors.6a5b8348.js 115.12 KiB 40.60 KiB
build\js\chunk-1b8a9a30.48200924.js 17.45 KiB 6.13 KiB
build\js\chunk-24926a39.dbd26b18.js 8.95 KiB 3.51 KiB
build\js\chunk-7d82c670.cf3aa735.js 7.73 KiB 3.25 KiB
build\js\app.7e2a4494.js 4.81 KiB 2.07 KiB
build\js\chunk-29724baf.89c3a7e4.js 2.98 KiB 1.10 KiB
build\css\chunk-29724baf.1ae50cfb.css 0.05 KiB 0.07 KiB
build\css\chunk-7d82c670.465f69d9.css 0.04 KiB 0.06 KiB
build\css\chunk-24926a39.2d561e0d.css 0.04 KiB 0.06 KiB
Images and other types of assets omitted. DONE Build complete. The build directory is ready to be deployed.
INFO Check out deployment instructions at https://cli.vuejs.org/guide/deployment.html

Now you can see new build folder with content as following:

Integrate Vue production into Spring Boot Project

Now we need to copy all files from Vue build folder to src/target/classes/static folder of Spring Boot project.

There are 2 way to do this:

  1. Manually copy/paste
  2. Using maven-resources-plugin

Open pom.xml, add following plugin:

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/classes/static/</outputDirectory>
<resources>
<resource>
<directory>${basedir}/../vue-js-crud/build</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

In the code above, we specify outputDirectory for the destination folder, and resource>directory for the source folder.

Serve Vue App on Spring Boot

Build and run the Spring Boot server with commands:
mvn clean install
mvn spring-boot:run

Open browser with url: http://localhost:8080/.
The result:

Spring Boot + Vue: Whitelabel Error Page

Oh yeah! Everything looks good.
But wait, let’s try to refresh the page.
What happened?

To handle this error, we’re gonna re-enable hash(#) in Vue App Routing. It will keep the UI route in hash part of the URL, which should not make the server return 404.

The default mode for Vue Router is hash mode. It uses a URL hash to simulate a full URL so that the page won’t be reloaded when the URL changes. In the source code, we already set Vue Router to history mode to get rid of the hash.

So, in Vue Project, let’s open router.js file and comment or remove mode: "history":

import Vue from "vue";
import Router from "vue-router";
Vue.use(Router);export default new Router({
// mode: "history",
routes: [
{
..
}
]
});

Don’t forget to rebuild the Vue App and copy all files and folders in build directory (Vue project) into views (Node.js Express project).

Now Our Url is hashed(#) after port number: http://localhost:8080/#/tutorials

Now you can refresh the page without worrying about Whitelabel Error.

Conclusion

Today we’ve learned how to integrate Vue.js with Spring Boot Application. We also handle “Whitelabel Error Page” case for Spring Boot + Vue Project. Now you can use Spring Boot to serve Vue App easily on the same server/port.

There are many fullstack Spring Boot + Vue examples that you can apply this approach to integrate:
Vue.js + Spring Boot + MySQL/PostgreSQL example
Vue.js + Spring Boot + MongoDB example
Spring Boot + Vue.js: Authentication with JWT & Spring Security Example

Serverless:
Vue Firebase Realtime Database: CRUD example
Vue Firestore: Build a CRUD App example

Further Reading

Source Code

You can find the complete source code for this tutorial at Github.

Originally published at https://bezkoder.com.

A passionate engineer in software development, especially web, mobile & cross-platform application. I love sharing knowledge by writing blogs & tutorials.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store