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:
- 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:
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:
- Manually copy/paste
- 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
- maven-resources-plugin
- https://cli.vuejs.org/guide/build-targets.html
- https://router.vuejs.org/guide/essentials/history-mode.html
Source Code
You can find the complete source code for this tutorial at Github.
Originally published at https://bezkoder.com.