简介

目前 vue 与 gin 的项目基本都是前后端分离部署

二者合并部署的教程非常少,且各有各的问题

结合各个教程后 找到一种比较完美的合并部署方案

vue

使用 axios 时进行如下配置

1
2
3
4
5
const request = axios.create({
  baseURL: `${currentDomain}/api`,
  timeout: 5000,
  headers: { "Cache-Control": "no-cache" },
});

对 baseURL 进行设置是为了能够使用户请求时,前后端的域名端口完全一致,避免造成跨域(必须

并且对于非域名部署的情况,能够方便地动态调整,避免写死 baseURL

headers 的设置是为了 vue dev 环境下,前后端的联调

同时

为了 dev 联调避免出现跨域问题,还应添加代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
export default defineConfig({
  // 其他参数
  server: {
    // port: 8080,
    // open: true,
    proxy: {
      "/api": {
        target: "http://localhost:5731",
        changeOrigin: true,
        // rewrite: (path) => path.replace(/^\/api/, ""), // 移除 /api 前缀 根据前后端代码 自行修改
      },
    },
  },
});

额外配置 build 后任务,将构建好的 dist 复制到后端目录下

1
2
3
4
5
"scripts": {
    "dev": "vite",
    "build": "vite build && robocopy ./dist 后端路径/vue /e /z /r:0",
    "preview": "vite preview"
  },

方便一部送到位

gin

1
2
3
4
5
6
7
8
❯ tree
文件夹 PATH 列表
卷序列号为 AE05-588D
C:.
├─main.go
├─其他
└─vue /* 可改 */
    └─assets

main.go 添加 embed 和路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//go:embed  vue/index.html
var indexHtml []byte

//go:embed  vue/*
var vue embed.FS

func main() {
	// 其他设置

    // 配置允许跨域 方便dev联调
	r.Use(cors.New(cors.Config{
		AllowOrigins:     []string{"*"}, // 允许的域名
		AllowMethods:     []string{"GET", "POST", "PUT", "DELETE"},
		AllowHeaders:     []string{"Origin", "Content-Type", "Authorization", "Cache-Control"},
		AllowCredentials: true,
	}))

	// 配置vue路由
	assets, _ := fs.Sub(vue, "vue/assets")
	r.StaticFS("/assets", http.FS(assets))
	icon, _ := fs.ReadFile(vue, "vue/favicon.ico")
	r.GET("/favicon.ico", func(c *gin.Context) { c.Data(200, "image/x-icon", icon) })
	r.NoRoute(func(c *gin.Context) {
		c.Data(200, "text/html; charset=utf-8", indexHtml)
	})

    // 其他路由
}

使用r.NoRoute将非后端路由全部导向 index.html,并由 index.html 获取 css、js 等

vue 中设置的 router 会被 build 进 js

通过 js 获取 url 来切换页面

对未使用 embed 的方法同理,参考代码自行设置

embed

对于使用embed

由于StaticFSembed的底层代码逻辑

在前端根目录的文件一般不多,这里只有index.html和 icon 文件

可通过单独获取、或通过fs.ReadFile获取,分别参考index.htmlfavicon.ico

对于前端其他文件,需要通过fs.Sub下移到对应目录后才能通过r.StaticFS("/assets", http.FS(assets))配置路由,且前端文件夹名和后端路由必须相同,二者缺一不可,否则会出现空白页面,即请求 js 等文件不存在的,页面无法加载等情况