Gin 打包vue或react项目输出文件到程序二进制文件

news2024/9/24 15:25:50

Gin 打包vue或react项目输出文件到程序二进制文件

  • 背景
  • 解决方案
    • 1. 示例目录结构
    • 2. 有如下问题要解决:
    • 3. 方案探索
  • 效果

背景

前后端分离已成为行业主流,vuereact等项目生成的文件独立在一个单独目录,与后端项目无关。
实际部署中,通常前面套一个nginx,根据请求返回静态资源或者代理到后端go服务上。
安装配置一套环境繁琐,加上有时需要部署在windows上,希望借助go的夸平台编译运行+embed嵌入文件能力,实现单个文件部署即可。

Created with Raphaël 2.3.0 用户请求 nginx 是否是静态资源? dist目录文件 go-app yes no

nginx配置样例

server {
    listen 80;
    root /usr/share/nginx/html;
    location / {
        try_files $uri $uri/index.html /index.html;
    }
    location /api {
        proxy_pass http://localhost/to-go-app-server;
        proxy_set_header   X-Forwarded-Proto $scheme;
        proxy_set_header   X-Real-IP         $remote_addr;
    }
}

解决方案

1. 示例目录结构

  • app.go为代码文件,同dist一个目录
  • app-server为编译后的单个exe
.
├── app.go
├── app-server
└── dist
    ├── assets
    │   ├── index-43d6e8d0.css
    │   └── index-f5e49ae2.js
    ├── CNAME
    ├── element-plus-logo-small.svg
    ├── favicon.svg
    ├── index.html
    └── vite.svg

2. 有如下问题要解决:

  • http://exmpale.com/跟路由如何定向到dist/index.html
  • http://exmpale.com/xx.svg 以及 http://exmpale.com/assets/xxxxx.js 这些动态路由如何生成
  • http://exmpale.com/正常业务路由与上面静态文件路由冲突如何处理

3. 方案探索

经过参考gin官方github.com/gin-contrib/static的插件,找出以下简单有效的解决方案

  • 使用embed将整个文件夹嵌入
  • 所有请求增加一个中间件, 判断embed.FS总是否存在url中路径的文件
  • 存在使用http.fileserver处理,并中断处理链
  • 不存在处理正常的逻辑
package main

import (
	"embed"
	"io/fs"
	"net/http"

	"github.com/gin-gonic/gin"
)

//go:embed dist
var dist embed.FS

func main() {
	r := gin.Default()
	r.Use(ServerStatic("dist", dist))

	r.GET("/ping", func(ctx *gin.Context) {
		ctx.String(http.StatusOK, "pong")
	})
	r.Run("localhost:81")
}

/*
假设vue/react项目输出文件夹名字为dist,拷贝到该go文件所在目录下
注意"dist"前后不能有 /
r.Use(ServerStatic("dist", dist))
*/
func ServerStatic(prefix string, embedFs embed.FS) gin.HandlerFunc {
	return func(ctx *gin.Context) {
		// 去掉前缀
		fsys, err := fs.Sub(embedFs, prefix)
		if err != nil {
			panic(err)
		}
		fs2 := http.FS(fsys)
		f, err := fs2.Open(ctx.Request.URL.Path)
		if err != nil {
			// 判断文件不存在,退出交给其他路由函数
			ctx.Next()
			return
		}
		defer f.Close()
		http.FileServer(fs2).ServeHTTP(ctx.Writer, ctx.Request)
		ctx.Abort()
	}
}

效果

  • 访问http://localhost:81/ 返回的是vue页面
  • 访问http://localhost:81/ping 返回的是逻辑处理结果pong

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1014383.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Scrum敏捷开发端到端管理流程

Leangoo领歌是Scrum中文网(scrum.cn)旗下的一款永久免费的敏捷研发管理工具。 Leangoo领歌覆盖了敏捷研发全流程,它提供端到端敏捷研发管理解决方案,包括小型团队敏捷开发,规模化敏捷SAFe,Scrum of Scrums…

父子进程区别与GDB多进程调试

父子进程之间的关系: 区别: 1.fork()函数的返回值不同,父进程中:>0 返回的子进程ID 子进程中:ID0 2.pcb中的数据有区别,当前进程的id pid ,当前父进程的id ppid,信号集 共同点…

黑马头条 后端项目部署_持续集成 Jenkins配置

项目部署_持续集成 1 今日内容介绍 1.1 什么是持续集成 持续集成( Continuous integration , 简称 CI )指的是,频繁地(一天多次)将代码集成到主干 持续集成的组成要素 一个自动构建过程, 从检出…

如何在RK3568开发板上实现USBNET?——飞凌嵌入式/USB Gadget/USB-NET/网络

本文将借助飞凌嵌入式OK3568-C开发板为大家介绍实现USBNET模式的方法,在这之前需要先知道什么是USB Gadget——USB Gadget是指所开发的电子设备以USB从设备的模式通过USB连接到主机。举个例子:将手机通过USB线插入PC后,手机就是USB Gadget。同…

【IP数据报】IP地址和MAC地址的区别

1、用IP地址来标识Internet的主机 在每个IP数据报中,都会携带源IP地址和目标IP地址来标识该IP数据报的源和目的主机。IP数据报在传输过程中,每个中间节点(IP 网关)还需要为其选择从源主机到目的主机的合适的转发路径(即路由)。IP协议可以根据路由选择协…

Android Update Engine 分析(十九)Extent 到底是个什么鬼?

文章目录 0. 导读1. 什么是 Extent?1. 什么是 Extent?2. Wikipedia 中的解释3. Ext4 中的 Extent2. Android OTA 中的 Extent2.1 update_metadata.proto 中的 Extent2.2 update engine 代码中的 Extentpayload_consumer 中的 Extentpayload_generator 中的 Extent2.3 OTA 中的…

Shell 正则表达式及综合案例及文本处理工具

目录 一、常规匹配 二、常用特殊字符 三、匹配手机号 四、案例之归档文件 五、案例之定时归档文件 六、Shell文本处理工具 1. cut工具 2. awk工具 一、常规匹配 一串不包含特殊字符的正则表达式匹配它自己 例子,比如说想要查看密码包含root字符串的&#x…

【华为云云耀云服务器L实例评测|云原生】自定制轻量化表单Docker快速部署云耀云服务器

🤵‍♂️ 个人主页: AI_magician 📡主页地址: 作者简介:CSDN内容合伙人,全栈领域优质创作者。 👨‍💻景愿:旨在于能和更多的热爱计算机的伙伴一起成长!!&…

发现某设备 adb shell ps 没有输出完整信息

某错误示例 并不是都使用 -ef 参数查找都能够返回完整信息,某些版本设备不适用 -ef 也不会返回完整信息。 简单兼容 简单兼容不同版本 Android 设备查找进程列表,没有通过脚本判断 Android 版本,如有兴趣可以自己修改。 :loop adb shell…

代码配置仓库GitLab安装部署

Github是目前世界上代码行数最多的在线软件版本配置库平台,而Gitlab是Github对应的开源版本,本文主要描述Gitlab的安装部署。 https://about.gitlab.com/ https://gitlab.cn/install/ 如上所示,从官方网站中下载不同操作系统的版本&#xf…

聚合物发光材料荧光量子效率测量

近年来‚聚合物发光材料与器件受到人们的极大关注和高度重视‚其关键是聚合物发光器件具有光吸收范围宽‚吸收强度大‚发光效率高‚激发阈值低以及制备工艺简便灵活等显著特点‚已成为有机固体激光领域一个新的研究热点。 现有的聚合物发光材料体系主要集中在:聚噻…

04-Flask-新版Flask运行方式

新版Flask运行方式 前言老版本运行方式新版本运行方式命令行方式运行pycharm运行 前言 本篇来学习下新版Flask运行方式 老版本运行方式 app.run():1.0之前版本 # -*- coding: utf-8 -*- # Time : 2023/9/16 # Author : 大海# 导入flask from flask import F…

react路由02——react-routerV6 中路由表的使用(useRoutes钩子)

react路由02——react-routerV6 中路由表的使用(useRoutes钩子) 1. 不使用路由表1.1 关于react-routerV6路由简单使用1.2 未配置路由表 2. 路由表——useRoutes钩子2.1 配置路由表2.2 一级路由组件——useRoutes钩子2.3 二级路由组件——Outlet组件2.4 目…

进化算法、遗传编程和学习

一、说明 进化算法是一系列搜索算法,其灵感来自自然界(达尔文主义)进化过程。所有不同家庭成员的共同点是,通过应用受自然遗传学和自然选择启发的 算子,通过进化出最初 随机的候选解决方案群体来解决问题&#…

打包发布异常01

缺一不可 Build starting... Start: Fri Sep 15 08:07:01 UTC 2023 bfdf11d63b70 Git: 0.33-0-g6190381 commit 61903816b88ff5cf3e0848cd19fcb190af0801cd Author: 米伟强 Date: Fri Sep 15 15:57:28 2023 0800gradle插件版本Init SDKMan Found Android manifest Android …

Rust :与C交互

rust调用C端的库函数,有很多方法。今天介绍通过cc库的方式,实现rust调用c端库函数。 1、相关准备: 在ffi目录下,创建了c_part和rust_ffi文件夹。 c_part下放了ctools.c文件,里面有一些库函数,需要让rust调…

华为云云耀云服务器L实例评测|基于Docker环境快速部署Halo个人博客实操

目录 一、基本介绍 1.1 云耀云服务器L实例介绍 1.2 实操介绍 二、云耀云服务器的购买及基本使用 2.1 服务器购买流程 2.2 初始化连接流程 2.3 系统环境检查 三、Docker中运行Halo 3.1 Halo基本介绍 3.2 Docker的安装 3.3 使用 Docker 镜像创建容器 四、安装初始化H…

LVS负载均衡DR直接路由

LVS负载均衡DR直接路由 一、DR工作原理二、 数据包流向三、DR模式特点四、ARP问题4.1第一次访问完整(不考虑实际问题)4.2问题一:IP 地址冲突 五、部署LVS-DR集群5.2、第一台web服务器5.3、第二台Web节点服务器5.4、在客户机测试(1…

QT : 仿照QQ 完成弹出登录窗口,并实例化组件

1. 运行效果图 2. Headers #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow>class MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent nullptr);~MainWindow(); }; #endif // MAINWINDOW_H 3. mainWindow.cpp &#xff1a…

Android studio实现登录验证后返回token及用户信息,使用token获取用户信息并生成列表展示

大概时序图 登录成功保存token&#xff0c;然后带token请求获取用户列表 实现效果&#xff1a; 依赖 build.gradle(:app) dependencies {implementation androidx.recyclerview:recyclerview:1.2.1implementation com.google.code.gson:gson:2.8.9implementation com.tenc…