feat(admin-portal): 完整实现 admin-portal 管理端微前端
包含 src 全部实现、Dockerfile、配置文件等
This commit is contained in:
43
apps/admin-portal/src/lib/web-vitals.ts
Normal file
43
apps/admin-portal/src/lib/web-vitals.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Web Vitals 采集(A11y + 性能)
|
||||
*
|
||||
* 仲裁:所有前端应用必须采集 Web Vitals
|
||||
* 端点:NEXT_PUBLIC_WEB_VITALS_ENDPOINT(默认 /api/admin/web-vitals)
|
||||
*/
|
||||
import { onLCP, onCLS, onFCP, onINP, onTTFB } from "web-vitals";
|
||||
|
||||
type Metric = { name: string; value: number; rating: string; id: string };
|
||||
|
||||
const ENDPOINT =
|
||||
process.env.NEXT_PUBLIC_WEB_VITALS_ENDPOINT ?? "/api/admin/web-vitals";
|
||||
|
||||
function sendMetric(metric: Metric): void {
|
||||
if (typeof navigator === "undefined") return;
|
||||
const body = JSON.stringify({
|
||||
name: metric.name,
|
||||
value: metric.value,
|
||||
rating: metric.rating,
|
||||
id: metric.id,
|
||||
page: window.location.pathname,
|
||||
ts: Date.now(),
|
||||
});
|
||||
// 使用 sendBeacon 避免阻塞卸载
|
||||
if (navigator.sendBeacon) {
|
||||
navigator.sendBeacon(ENDPOINT, body);
|
||||
} else {
|
||||
void fetch(ENDPOINT, { method: "POST", body, keepalive: true }).catch(
|
||||
() => {
|
||||
// 忽略上报失败
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function initWebVitals(): void {
|
||||
if (typeof window === "undefined") return;
|
||||
onLCP((m) => sendMetric(m as unknown as Metric));
|
||||
onCLS((m) => sendMetric(m as unknown as Metric));
|
||||
onFCP((m) => sendMetric(m as unknown as Metric));
|
||||
onINP((m) => sendMetric(m as unknown as Metric));
|
||||
onTTFB((m) => sendMetric(m as unknown as Metric));
|
||||
}
|
||||
Reference in New Issue
Block a user