"use client"; import { useEffect } from "react"; export function FaviconUpdater() { useEffect(() => { let isDisposed = false; // 从 API 获取最新的 favicon 设置 fetch("/api/site-settings") .then((res) => res.json()) .then((settings) => { if (!settings.favicon || isDisposed) { return; } const faviconUrl = settings.favicon; const timestamp = Date.now(); const urlWithCache = `${faviconUrl}${faviconUrl.includes("?") ? "&" : "?"}v=${timestamp}`; // 仅处理本组件创建的 link,避免删除 Next/React 管理的 head 节点 const oldLinks = document.querySelectorAll( 'link[data-managed-favicon="true"]' ); oldLinks.forEach((link) => { if (link.parentNode) { link.parentNode.removeChild(link); } }); const createManagedLink = (rel: string, href: string, type?: string) => { const link = document.createElement("link"); link.rel = rel; link.href = href; link.setAttribute("data-managed-favicon", "true"); if (type) { link.type = type; } document.head.appendChild(link); }; createManagedLink("icon", urlWithCache, "image/x-icon"); createManagedLink("apple-touch-icon", urlWithCache); createManagedLink("shortcut icon", urlWithCache); }) .catch((error) => { console.error("[Favicon] Error updating favicon:", error); }); return () => { isDisposed = true; }; }, []); return null; }