Building a Vue + SpringBoot Management System: Setup, Architecture, and Deployment
This step‑by‑step guide shows backend developers how to create a small management system with Vue 3, TypeScript, Vite, and SpringBoot, covering the technology stack, development‑tool installation, project scaffolding, core components, routing, Pinia state, Axios API wrappers, TypeScript interfaces, environment configuration, and deployment.
This document is a step‑by‑step tutorial for backend developers who want to build a small management system using Vue 3, TypeScript, Vite and SpringBoot. It explains why Vue is chosen over jQuery, lists the technology stack, shows the project structure, and walks through environment preparation, scaffolding, core files, routing, state management, API encapsulation, interface definitions, environment configuration and deployment.
Technology stack
Backend: SpringBoot Frontend: Vue 3 + TypeScript + Vite + VueRouter + Axios + ElementPlus + Pinia
Installation of development tools
Node.js v18.12.1 to /usr/local/bin/node
npm v8.19.2 to /usr/local/bin/npmConfigure npm registry (optional acceleration):
// 查看当前数据源
npm config get registry // 默认是 https://registry.npmjs.org/
// 设置为淘宝源
npm config set registry https://registry.npm.taobao.orgInstall Visual Studio Code and the Vue Volar extension.
Project scaffolding with Vite
npm init vue@latest // runs create‑vue, the official Vue scaffolding tool ✔ Project name: … my-project
✔ Add TypeScript? … Yes
✔ Add Vue Router for SPA development? … Yes
✔ Add Pinia for state management? … Yes cd my-project
npm install
npm run dev // starts Vite dev server, http://localhost:5177/The generated directory structure includes index.html , src/main.ts , src/App.vue , layout components, view pages (login, home, book list), and utility folders.
Core framework files
<!-- index.html – entry point –>
<html lang="en">
...
<!-- root container -->
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</html> // src/main.ts – create app, register plugins
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
import './assets/main.css'
import '@/router/permission'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.mount('#app') <script setup lang="ts">
import { RouterView } from 'vue-router'
</script>
<template>
<RouterView />
</template>Layout and component design
The layout component ( src/layout/index.vue ) uses ElementPlus el-container to provide a header, aside menu and main content area. The menu ( src/layout/Menu.vue ) defines router links for Home and Book Management.
<template>
<el-menu default-active="1" router>
<el-menu-item index="/">首页</el-menu-item>
<el-menu-item index="/bookList">书籍管理</el-menu-item>
</el-menu>
</template>
<script lang="ts" setup>
import { Document, Menu as IconMenu } from '@element-plus/icons-vue'
</script>Routing
import { createRouter, createWebHashHistory } from 'vue-router'
const router = createRouter({
history: createWebHashHistory(import.meta.env.BASE_URL),
routes: [
{ path: '/login', name: 'login', component: () => import('@/views/login/LoginView.vue') },
{
path: '/',
name: 'layout',
component: () => import('@/layout/index.vue'),
children: [
{ path: '/', name: 'home', component: () => import('@/views/home/HomeView.vue') },
{ path: '/bookList', name: 'bookList', component: () => import('@/views/book/BookListView.vue') }
]
}
]
})
export default routerRoute guard ( src/router/permission.ts ) checks the login token stored in Pinia and redirects unauthenticated users to /login .
router.beforeEach((to, from, next) => {
const userStore = useUserStore()
if (userStore.getToken()) {
to.path === '/login' ? next('/') : next()
} else {
whiteList.includes(to.path) ? next() : next('/login')
}
})State management with Pinia
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', () => {
function saveToken(token) { localStorage.setItem('token_vue_springboot', token) }
function getToken() { return localStorage.getItem('token_vue_springboot') }
// other token‑time helpers omitted for brevity
return { saveToken, getToken }
})Components communicate via props and emitted events; examples show how AddBookDialog.vue receives a bookValue prop and emits getBooks after a successful add/update.
API encapsulation with Axios
import axios from "axios"
import { useUserStore } from '@/stores/user/user'
const axiosService = axios.create({
baseURL: import.meta.env.VITE_DOMAIN_URL_VUE_BOOT,
timeout: 3000
})
axiosService.interceptors.request.use(config => {
const userStore = useUserStore()
if (userStore.tokenTimeIsExpire()) { logout(); return Promise.reject(new Error('token expired')) }
return config
})
export default axiosServiceBusiness‑level APIs (e.g., login.ts , book.ts ) call the Axios instance. export function login(data) { return axiosService.request({ url: 'user/login', method: 'post', data }) }
TypeScript interface definitions
// types/book.ts
export interface Book { id: number; name: string }
export interface BookRequest { name: string; pageNum: number; pageSize: number }Components import these types for strong‑typing of request parameters and responses.
Environment configuration
Separate .env.development and .env.production files define VITE_DOMAIN_URL_VUE_BOOT and other variables. The vite.config.ts build options are adjusted to remove hash from output filenames for stable deployment.
build: {
rollupOptions: {
input: "./src/main.ts",
output: {
dir: "dist",
entryFileNames: "assets/[name].js"
}
}
}Deployment
Static assets are served from a CDN, while the backend (SpringBoot) renders a minimal index.html that loads the compiled main.js . This keeps the front‑end bundle independent of backend releases.
References include Vue3 admin system tutorials, TypeScript quick‑start videos, and official documentation of each listed technology.
DaTaobao Tech
Official account of DaTaobao Technology
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.