简介
目前 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: { proxy: { "/api": { target: "http://localhost:5731", changeOrigin: true, }, }, }, });
|
额外配置 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
| var indexHtml []byte
var vue embed.FS
func main() {
r.Use(cors.New(cors.Config{ AllowOrigins: []string{"*"}, AllowMethods: []string{"GET", "POST", "PUT", "DELETE"}, AllowHeaders: []string{"Origin", "Content-Type", "Authorization", "Cache-Control"}, AllowCredentials: true, }))
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
的
由于StaticFS
和embed
的底层代码逻辑
在前端根目录的文件一般不多,这里只有index.html
和 icon 文件
可通过单独获取、或通过fs.ReadFile
获取,分别参考index.html
和favicon.ico
对于前端其他文件,需要通过fs.Sub
下移到对应目录后才能通过r.StaticFS("/assets", http.FS(assets))
配置路由,且前端文件夹名和后端路由必须相同,二者缺一不可,否则会出现空白页面,即请求 js 等文件不存在的,页面无法加载等情况