feat(api-versioning): remove git-based versioning and serve via HTML script tag

- Remove `getGitHash` function from `src/utils/server.ts` as it relied on `.git` directory presence which is not available in production builds.
- Remove the `/api/app-version` endpoint from `src/index.tsx` since fetching version via API is no longer needed.
- Update `src/hooks/useAppVersion.ts` to derive the version directly from the `src` attribute of a script tag in the HTML head.
- This change improves performance by avoiding an extra API request and ensures version accuracy across all deployment environments without requiring Git metadata.
This commit is contained in:
kyuuseiryuu 2026-03-17 11:23:25 +09:00
parent eef4656f87
commit c7faeb1b65
3 changed files with 10 additions and 33 deletions

View File

@ -1,9 +1,11 @@
import { useRequest } from "ahooks"; import { useLayoutEffect, useState } from "react";
export const useAppVersion = () => { export const useAppVersion = () => {
const versionRequest = useRequest( const [appVersion, setAppVersion] = useState('');
() => fetch('/api/app-version').then(res => res.json()).then(json => json.version), useLayoutEffect(() => {
{ debounceWait: 300 } const src = document.querySelector('head > script')?.getAttribute('src') ?? '';
); const version = /\b(?<ver>\w*).js/.exec(src)?.groups?.ver ?? '';
return versionRequest.data; setAppVersion(version.toUpperCase());
}, []);
return appVersion;
} }

View File

@ -1,5 +1,5 @@
import { serve } from "bun"; import { serve } from "bun";
import { getGitHash, getMatchInfo, verifyLogtoToken, xcxApi } from "./utils/server"; import { getMatchInfo, verifyLogtoToken, xcxApi } from "./utils/server";
import ics from 'ics'; import ics from 'ics';
import index from "./index.html"; import index from "./index.html";
import { getUidScore } from "./services/uidScoreStore"; import { getUidScore } from "./services/uidScoreStore";
@ -13,17 +13,12 @@ import type { IEventInfo } from "./types";
dayjs.extend(utc); dayjs.extend(utc);
dayjs.extend(timezone); dayjs.extend(timezone);
console.debug('AppVersion: %s', await getGitHash(8));
const server = serve({ const server = serve({
port: process.env.PORT || 3000, port: process.env.PORT || 3000,
routes: { routes: {
// Serve index.html for all unmatched routes. // Serve index.html for all unmatched routes.
"/*": index, "/*": index,
"/api/app-version": {
async GET() {
return Response.json({ version: await getGitHash(8) });
}
},
"/api/club/find": { "/api/club/find": {
async GET(req) { async GET(req) {
const searchParams = new URL(req.url).searchParams; const searchParams = new URL(req.url).searchParams;

View File

@ -119,23 +119,3 @@ export const verifyLogtoToken = async (headers: Headers) => {
// Sub is the user ID, used for user identification // Sub is the user ID, used for user identification
return payload return payload
} }
export async function getGitHash(length = 6): Promise<string> {
try {
// 1. 读取 HEAD 指针
const headContent = await file(".git/HEAD").text();
// 情况 A: 处于分支上 (内容格式为 "ref: refs/heads/master")
if (headContent.startsWith("ref:")) {
const refPath = headContent.replace("ref: ", "").trim();
const fullHash = await file(`.git/${refPath}`).text();
return fullHash.trim().substring(0, length);
}
// 情况 B: 处于分离头指针状态 (内容直接就是 Hash)
return headContent.trim().substring(0, length);
} catch (e) {
console.error("无法读取 Git 信息:", e);
return "unknown";
}
}