fix: 修复字体加载警告和Logo图片宽高比问题

## 修复内容

### 字体优化
- 创建 AoyagiReisho-subset.ttf 子集字体,仅包含"睿新致远"4个字符
- 文件大小从 4.4MB 减小到 5KB(99.9% 减少)
- 修复 vmtx 表解析错误导致的 48 个控制台警告

### Logo 图片修复
- 修复 Logo SVG 宽高比问题(原始 480x120,4:1 比例)
- Header: width=128 height=32
- Footer: width=192 height=48
- 消除 Next.js Image 组件警告

### 其他优化
- 简化字体加载逻辑
- 更新部署配置

## 测试结果
- 32 个回归测试全部通过
- 0 个控制台警告
- 0 个错误
This commit was merged in pull request #7.
This commit is contained in:
张翔
2026-04-22 16:00:49 +08:00
parent 4066c82939
commit 2b7efb23ec
18 changed files with 341 additions and 69 deletions
Binary file not shown.
Binary file not shown.
+12 -30
View File
@@ -1,37 +1,10 @@
@import "tailwindcss";
@font-face {
font-family: 'Aoyagi Reisho';
src: url('/fonts/AoyagiReisho.ttf') format('truetype');
font-weight: normal;
font-style: normal;
font-display: block;
font-stretch: normal;
unicode-range: U+4E00-9FFF, U+3400-4DBF, U+20000-2A6DF, U+2A700-2B73F, U+2B740-2B81F, U+2B820-2CEAF, U+F900-FAFF, U+2F800-2FA1F;
}
/* 字体加载优化 - 防止 FOUT */
.font-loading {
font-family: 'STKaiti', 'KaiTi', serif;
}
.font-loaded {
font-family: 'Aoyagi Reisho', 'STKaiti', 'KaiTi', serif;
}
.font-calligraphy {
font-family: var(--font-aoyagi-reisho), 'Aoyagi Reisho', var(--font-ma-shan-zheng), 'Ma Shan Zheng', var(--font-long-cang), 'Long Cang', 'ZCOOL XiaoWei', 'STKaiti', 'KaiTi', serif !important;
font-weight: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
}
@theme inline {
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
--font-chinese: var(--font-noto-sans-sc);
--font-calligraphy: 'Aoyagi Reisho', var(--font-long-cang), 'Long Cang', var(--font-ma-shan-zheng), 'Ma Shan Zheng', 'ZCOOL XiaoWei', 'STKaiti', 'KaiTi', serif;
--font-calligraphy: 'Ma Shan Zheng', 'ZCOOL XiaoWei', 'STKaiti', 'KaiTi', serif;
}
:root {
@@ -347,9 +320,9 @@
background-clip: text;
}
/* 青柳隶书体 - 与 Logo 保持一致 */
/* 马善政行书体 - 用于红色关键词高亮 */
.font-calligraphy {
font-family: var(--font-aoyagi-reisho), 'Aoyagi Reisho', var(--font-long-cang), 'Long Cang', var(--font-ma-shan-zheng), 'Ma Shan Zheng', 'ZCOOL XiaoWei', 'STKaiti', 'KaiTi', serif !important;
font-family: var(--font-ma-shan-zheng), 'Ma Shan Zheng', 'ZCOOL XiaoWei', 'STKaiti', 'KaiTi', serif !important;
font-weight: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
@@ -396,6 +369,15 @@
}
}
/* 青柳隷書 - 仅用于品牌标题"睿新致遠" */
@utility font-brand {
font-family: var(--font-aoyagi-reisho), 'Aoyagi Reisho', 'Ma Shan Zheng', 'ZCOOL XiaoWei', 'STKaiti', 'KaiTi', serif !important;
font-weight: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
}
@keyframes slideIn {
from {
opacity: 0;
+5 -20
View File
@@ -1,5 +1,5 @@
import type { Metadata, Viewport } from "next";
import { Geist, Geist_Mono, Noto_Sans_SC, Ma_Shan_Zheng, Long_Cang } from "next/font/google";
import { Geist, Geist_Mono, Noto_Sans_SC, Ma_Shan_Zheng } from "next/font/google";
import localFont from "next/font/local";
import "./globals.css";
import { Suspense } from "react";
@@ -41,19 +41,12 @@ const maShanZheng = Ma_Shan_Zheng({
variable: "--font-ma-shan-zheng",
subsets: ["latin"],
display: "swap",
preload: false,
});
const longCang = Long_Cang({
weight: "400",
variable: "--font-long-cang",
subsets: ["latin"],
display: "swap",
preload: false,
preload: true,
});
// 青柳隷書 - 仅用于品牌标题"睿新致遠"(子集版本,仅包含4个字符)
const aoyagiReisho = localFont({
src: "./fonts/AoyagiReisho.ttf",
src: "./fonts/AoyagiReisho-subset.ttf",
variable: "--font-aoyagi-reisho",
display: "swap",
preload: true,
@@ -131,19 +124,11 @@ export default function RootLayout({
<head>
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="apple-touch-icon" href="/favicon.svg" />
{/* 字体预加载优化 */}
<link
rel="preload"
href="/fonts/AoyagiReisho.ttf"
as="font"
type="font/ttf"
crossOrigin="anonymous"
/>
<OrganizationSchema />
<WebsiteSchema />
</head>
<body
className={`${geistSans.variable} ${geistMono.variable} ${notoSansSC.variable} ${maShanZheng.variable} ${longCang.variable} ${aoyagiReisho.variable} font-sans antialiased`}
className={`${geistSans.variable} ${geistMono.variable} ${notoSansSC.variable} ${maShanZheng.variable} ${aoyagiReisho.variable} font-sans antialiased`}
style={{ fontFamily: "'Noto Sans SC', 'Geist', -apple-system, BlinkMacSystemFont, sans-serif" }}
>
<a
+2 -2
View File
@@ -13,9 +13,9 @@ export function Footer() {
<Image
src="/logo.svg"
alt={COMPANY_INFO.name}
width={48}
width={192}
height={48}
className="h-12 w-auto transition-transform duration-200 hover:scale-105"
className="transition-transform duration-200 hover:scale-105"
loading="eager"
priority
/>
+2 -2
View File
@@ -169,9 +169,9 @@ function HeaderContent() {
<Image
src="/logo.svg"
alt={COMPANY_INFO.name}
width={32}
width={128}
height={32}
className="h-8 w-auto transition-transform duration-200 group-hover:scale-105"
className="transition-transform duration-200 group-hover:scale-105"
loading="eager"
priority
/>
+1 -1
View File
@@ -27,7 +27,7 @@ export function AboutSection() {
>
<div className="text-center mb-12">
<h2 id="about-heading" className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-6">
<span className="tracking-tight font-calligraphy text-[#C41E3A]" style={{ fontWeight: 'normal', WebkitFontSmoothing: 'antialiased', MozOsxFontSmoothing: 'grayscale', textRendering: 'optimizeLegibility' }}>{COMPANY_INFO.shortName}</span>
<span className="tracking-tight font-brand text-[#C41E3A]" style={{ fontWeight: 'normal', WebkitFontSmoothing: 'antialiased', MozOsxFontSmoothing: 'grayscale', textRendering: 'optimizeLegibility' }}>{COMPANY_INFO.shortName}</span>
</h2>
<p className="text-lg text-[#5C5C5C] mb-8">
{COMPANY_INFO.slogan}
@@ -60,7 +60,7 @@ export function HeroTitle({ isVisible }: HeroContentProps) {
initial={shouldReduceMotion ? {} : { opacity: 0, y: 20 }}
animate={isVisible ? { opacity: 1, y: 0 } : {}}
transition={shouldReduceMotion ? { duration: 0 } : { duration: 0.6, delay: 0.1 }}
className="text-5xl sm:text-6xl lg:text-7xl tracking-tight mb-6 font-calligraphy"
className="text-5xl sm:text-6xl lg:text-7xl tracking-tight mb-6 font-brand"
style={{
fontWeight: 'normal',
WebkitFontSmoothing: 'antialiased',
+2 -2
View File
@@ -43,13 +43,13 @@ describe('useFontLoading', () => {
writable: true,
});
const { result } = renderHook(() => useFontLoading('Aoyagi Reisho'));
const { result } = renderHook(() => useFontLoading('Ma Shan Zheng'));
await waitFor(() => {
expect(result.current).toBe(true);
});
expect(mockLoad).toHaveBeenCalledWith('1em "Aoyagi Reisho"');
expect(mockLoad).toHaveBeenCalledWith('1em "Ma Shan Zheng"');
});
it('should return true when font loading fails', async () => {
+1 -1
View File
@@ -2,7 +2,7 @@
import { useState, useEffect } from 'react';
export function useFontLoading(fontFamily: string = 'Aoyagi Reisho') {
export function useFontLoading(fontFamily: string = 'Ma Shan Zheng') {
const [isLoaded, setIsLoaded] = useState(false);
useEffect(() => {