perf(website): avoid blocking root render on GitHub

This commit is contained in:
Mohamed Boudra
2026-05-07 23:06:27 +07:00
parent a1ac402154
commit 89a500cd3e
2 changed files with 59 additions and 13 deletions

View File

@@ -49,16 +49,20 @@ interface ReleaseInfo {
windowsArm64Asset: string | null; windowsArm64Asset: string | null;
} }
const fallbackVersion = websitePackage.version.replace(/-.*$/, "");
const fallbackRelease: ReleaseInfo = {
version: fallbackVersion,
windowsX64Asset: `Paseo-Setup-${fallbackVersion}.exe`,
windowsArm64Asset: null,
};
const GITHUB_RELEASES_URL = "https://api.github.com/repos/getpaseo/paseo/releases?per_page=10"; const GITHUB_RELEASES_URL = "https://api.github.com/repos/getpaseo/paseo/releases?per_page=10";
const RELEASE_REFRESH_MS = 60_000;
let cachedRelease = fallbackRelease;
let cachedReleaseAt = 0;
let refreshReleasePromise: Promise<void> | null = null;
async function fetchLatestReadyRelease(): Promise<ReleaseInfo> { async function fetchLatestReadyRelease(): Promise<ReleaseInfo> {
const fallbackVersion = websitePackage.version.replace(/-.*$/, "");
const fallback: ReleaseInfo = {
version: fallbackVersion,
windowsX64Asset: `Paseo-Setup-${fallbackVersion}.exe`,
windowsArm64Asset: null,
};
try { try {
const res = await fetch(GITHUB_RELEASES_URL, { const res = await fetch(GITHUB_RELEASES_URL, {
headers: { headers: {
@@ -74,11 +78,11 @@ async function fetchLatestReadyRelease(): Promise<ReleaseInfo> {
cacheKey: "github-releases-latest", cacheKey: "github-releases-latest",
}, },
} as RequestInit); } as RequestInit);
if (!res.ok) return fallback; if (!res.ok) return fallbackRelease;
const releases = (await res.json()) as GitHubRelease[]; const releases = (await res.json()) as GitHubRelease[];
const ready = releases.find((r) => !r.prerelease && !r.draft && hasRequiredAssets(r)); const ready = releases.find((r) => !r.prerelease && !r.draft && hasRequiredAssets(r));
if (!ready) return fallback; if (!ready) return fallbackRelease;
const win = pickWindowsAssets(ready.assets); const win = pickWindowsAssets(ready.assets);
return { return {
version: versionFromTag(ready.tag_name), version: versionFromTag(ready.tag_name),
@@ -86,10 +90,28 @@ async function fetchLatestReadyRelease(): Promise<ReleaseInfo> {
windowsArm64Asset: win.arm64, windowsArm64Asset: win.arm64,
}; };
} catch { } catch {
return fallback; return fallbackRelease;
} }
} }
function refreshLatestRelease(): Promise<void> {
refreshReleasePromise ??= fetchLatestReadyRelease()
.then((release) => {
cachedRelease = release;
cachedReleaseAt = Date.now();
return undefined;
})
.finally(() => {
refreshReleasePromise = null;
});
return refreshReleasePromise;
}
export const getLatestRelease = createServerFn({ method: "GET" }).handler(async () => { export const getLatestRelease = createServerFn({ method: "GET" }).handler(async () => {
return fetchLatestReadyRelease(); if (Date.now() - cachedReleaseAt > RELEASE_REFRESH_MS) {
void refreshLatestRelease();
}
return cachedRelease;
}); });

View File

@@ -11,6 +11,11 @@ function formatStars(count: number): string {
} }
const GITHUB_REPO_URL = "https://api.github.com/repos/getpaseo/paseo"; const GITHUB_REPO_URL = "https://api.github.com/repos/getpaseo/paseo";
const STAR_REFRESH_MS = 60_000;
let cachedStars = "";
let cachedStarsAt = 0;
let refreshStarsPromise: Promise<void> | null = null;
async function fetchStarCount(): Promise<string> { async function fetchStarCount(): Promise<string> {
try { try {
@@ -34,7 +39,26 @@ async function fetchStarCount(): Promise<string> {
} }
} }
function refreshStarCount(): Promise<void> {
refreshStarsPromise ??= fetchStarCount()
.then((stars) => {
if (stars) {
cachedStars = stars;
cachedStarsAt = Date.now();
}
return undefined;
})
.finally(() => {
refreshStarsPromise = null;
});
return refreshStarsPromise;
}
export const getStarCount = createServerFn({ method: "GET" }).handler(async () => { export const getStarCount = createServerFn({ method: "GET" }).handler(async () => {
const stars = await fetchStarCount(); if (Date.now() - cachedStarsAt > STAR_REFRESH_MS) {
return { stars }; void refreshStarCount();
}
return { stars: cachedStars };
}); });