integrating-vue-with-spring-boot-feature-image

How to integrate Vue.js 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.

Related Posts:
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


Vue.js & Spring Boot application Overview

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

integrating-vue-with-spring-boot-project-structure

For example, if we run them separately:

  • Spring Boot Server exports Rest Apis at Url: http://localhost:8080/
  • Vue.js Client runs at url: http://localhost:8081/

Using Vue to call Spring Rest API:

integrating-vue-with-spring-boot-run-separated-ports

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/.

integrating-vue-with-spring-boot-run-on-same-server-port

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:

integrating-vue-with-spring-boot-import-vue-client-project

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:
  • integrating-vue-with-spring-boot-node-modules

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

integrating-vue-with-spring-boot-exclude-node-modules

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:

integrating-vue-with-spring-boot-project-structure

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:

integrating-vue-with-spring-boot-vue-build-folder

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:

integrating-vue-with-spring-boot-run-demo

Spring Boot + Vue: Whitelabel Error Page

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

integrating-vue-with-spring-boot-whitelabel-error-page

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

integrating-vue-with-spring-boot-run-on-same-server-port

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.

Leave a Reply

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