Skip to content

Commit c0f8c96

Browse files
committed
feat(seo): 实现全面的SEO优化方案
- 添加SEO组件和工具函数用于生成meta标签和结构化数据 - 优化所有页面的title、description和keywords - 实现动态站点地图生成功能 - 更新robots.txt添加爬虫延迟设置 - 添加SEO文档说明优化细节和使用方法 - 改进Layout组件支持完整的SEO元数据
1 parent 129bc9d commit c0f8c96

16 files changed

Lines changed: 752 additions & 12 deletions

blog-web/SEO_README.md

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
# SEO 优化实现说明
2+
3+
本项目已完成全面的SEO优化,包括meta标签、结构化数据、站点地图等功能。
4+
5+
## 🎯 已实现的SEO功能
6+
7+
### 1. Meta标签优化
8+
- ✅ 基础meta标签(title, description, keywords, author)
9+
- ✅ Open Graph标签(社交媒体分享优化)
10+
- ✅ Twitter Card标签
11+
- ✅ 文章特定标签(发布时间、修改时间、标签等)
12+
- ✅ Canonical URL
13+
- ✅ Robots meta标签
14+
15+
### 2. 结构化数据(Schema.org)
16+
- ✅ WebSite结构化数据
17+
- ✅ BlogPosting结构化数据
18+
- ✅ Person和Organization数据
19+
- ✅ JSON-LD格式实现
20+
21+
### 3. 站点地图
22+
- ✅ 动态生成sitemap-index.xml
23+
- ✅ 静态页面sitemap
24+
- ✅ 博客文章动态sitemap
25+
- ✅ Robots.txt优化
26+
27+
### 4. 技术优化
28+
- ✅ HTML压缩
29+
- ✅ 内联样式优化
30+
- ✅ 爬虫友好的robots.txt
31+
32+
## 📁 文件结构
33+
34+
```
35+
src/
36+
├── components/
37+
│ └── SEO.astro # 独立SEO组件
38+
├── layouts/
39+
│ └── Layout.astro # 主布局(已优化SEO)
40+
├── pages/
41+
│ ├── robots.txt.ts # 动态robots.txt
42+
│ ├── sitemap-index.xml.ts # 站点地图索引
43+
│ ├── sitemap-0.xml.ts # 具体站点地图
44+
│ ├── index.astro # 首页(已优化)
45+
│ ├── about.astro # 关于页面(已优化)
46+
│ ├── projects.astro # 项目页面(已优化)
47+
│ ├── blog/
48+
│ │ ├── index.astro # 博客列表(已优化)
49+
│ │ └── [slug].astro # 博客详情(已优化)
50+
│ └── tools/
51+
│ ├── index.astro # 工具页面(已优化)
52+
│ └── markdownrender.astro # Markdown编辑器(已优化)
53+
└── utils/
54+
└── seo.ts # SEO工具函数
55+
```
56+
57+
## 🚀 使用方法
58+
59+
### 1. 使用Layout组件(推荐)
60+
61+
```astro
62+
---
63+
// 在页面中使用
64+
import Layout from '../layouts/Layout.astro';
65+
---
66+
67+
<Layout
68+
title="页面标题"
69+
description="页面描述"
70+
keywords="关键词1,关键词2"
71+
type="website"
72+
image="/images/page-image.jpg"
73+
>
74+
<!-- 页面内容 -->
75+
</Layout>
76+
```
77+
78+
### 2. 使用独立SEO组件
79+
80+
```astro
81+
---
82+
import SEO from '../components/SEO.astro';
83+
---
84+
85+
<html>
86+
<head>
87+
<SEO
88+
title="页面标题"
89+
description="页面描述"
90+
keywords="关键词1,关键词2"
91+
type="article"
92+
publishedTime="2024-01-01T00:00:00Z"
93+
tags={['标签1', '标签2']}
94+
/>
95+
</head>
96+
<body>
97+
<!-- 页面内容 -->
98+
</body>
99+
</html>
100+
```
101+
102+
### 3. 博客文章SEO
103+
104+
博客文章页面会自动从API获取文章数据并生成相应的SEO标签:
105+
106+
- 动态标题:`文章标题 | ExquisiteCore Blog`
107+
- 动态描述:文章摘要或内容前150字符
108+
- 文章标签作为keywords
109+
- 发布和修改时间
110+
- 文章分类信息
111+
112+
## 🛠 SEO工具函数
113+
114+
`src/utils/seo.ts` 提供了以下工具函数:
115+
116+
- `generateTitle()` - 生成页面标题
117+
- `generateDescription()` - 生成并截断描述
118+
- `generateKeywords()` - 处理关键词
119+
- `generateImageUrl()` - 生成图片URL
120+
- `generateStructuredData()` - 生成结构化数据
121+
- `validateSEOData()` - 验证SEO数据
122+
123+
## 📊 SEO检查清单
124+
125+
### 页面级别
126+
- [ ] 每个页面都有唯一的title(10-60字符)
127+
- [ ] 每个页面都有描述性的meta description(50-160字符)
128+
- [ ] 关键词相关且不过度堆砌
129+
- [ ] 图片都有alt属性
130+
- [ ] 内部链接结构合理
131+
132+
### 技术级别
133+
- [x] 站点地图正常生成
134+
- [x] Robots.txt配置正确
135+
- [x] 结构化数据验证通过
136+
- [x] Open Graph标签完整
137+
- [x] 页面加载速度优化
138+
139+
### 内容级别
140+
- [ ] 内容原创且有价值
141+
- [ ] 标题层级结构清晰(H1-H6)
142+
- [ ] 内容长度适中
143+
- [ ] 定期更新内容
144+
145+
## 🔧 配置说明
146+
147+
### Astro配置
148+
149+
`astro.config.mjs` 中的SEO相关配置:
150+
151+
```javascript
152+
export default defineConfig({
153+
site: "https://blog.exquisitecore.xyz", // 站点URL
154+
integrations: [
155+
sitemap({
156+
changefreq: 'weekly',
157+
priority: 0.7,
158+
filter: (page) => !page.includes('/admin')
159+
})
160+
],
161+
compressHTML: true, // HTML压缩
162+
build: {
163+
inlineStylesheets: 'auto' // 样式优化
164+
}
165+
});
166+
```
167+
168+
### 环境变量
169+
170+
建议在 `.env` 文件中配置:
171+
172+
```env
173+
PUBLIC_SITE_URL=https://blog.exquisitecore.xyz
174+
PUBLIC_API_URL=http://localhost:8080
175+
```
176+
177+
## 📈 监控和分析
178+
179+
建议集成以下工具:
180+
181+
1. **Google Search Console** - 监控搜索表现
182+
2. **Google Analytics** - 分析用户行为
183+
3. **Schema.org验证工具** - 验证结构化数据
184+
4. **PageSpeed Insights** - 监控页面性能
185+
186+
## 🔄 维护建议
187+
188+
1. **定期检查**:每月检查一次SEO标签的完整性
189+
2. **内容更新**:保持内容的新鲜度和相关性
190+
3. **性能监控**:关注页面加载速度
191+
4. **链接检查**:定期检查内外部链接的有效性
192+
5. **移动端优化**:确保移动端SEO表现良好
193+
194+
## 📚 相关资源
195+
196+
- [Google SEO指南](https://developers.google.com/search/docs)
197+
- [Schema.org文档](https://schema.org/)
198+
- [Open Graph协议](https://ogp.me/)
199+
- [Twitter Card文档](https://developer.twitter.com/en/docs/twitter-for-websites/cards)
200+
- [Astro SEO指南](https://docs.astro.build/en/guides/integrations-guide/sitemap/)

blog-web/astro.config.mjs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,29 @@ export default defineConfig({
1616
},
1717

1818
site: "https://blog.exquisitecore.xyz",
19-
integrations: [solidJs({ devtools: true }), sitemap()],
19+
integrations: [
20+
solidJs({ devtools: true }),
21+
sitemap({
22+
// 自定义sitemap配置
23+
changefreq: 'weekly',
24+
priority: 0.7,
25+
lastmod: new Date(),
26+
// 排除某些页面(如果需要)
27+
filter: (page) => !page.includes('/admin'),
28+
// 自定义URL
29+
customPages: [
30+
'https://blog.exquisitecore.xyz/tools',
31+
'https://blog.exquisitecore.xyz/tools/markdownrender'
32+
]
33+
})
34+
],
2035
output: "static",
2136
adapter: node({
2237
mode: "standalone",
2338
}),
39+
// SEO相关配置
40+
compressHTML: true,
41+
build: {
42+
inlineStylesheets: 'auto'
43+
}
2444
});

blog-web/src/components/Footer.astro

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const currentYear = new Date().getFullYear();
1111
<a
1212
href="https://beian.miit.gov.cn/"
1313
target="_blank"
14-
class="link link-hover">蒙ICP备2025026598号</a
14+
class="link link-hover beian-link">蒙ICP备2025026598号-1</a
1515
>
1616
</div>
1717

@@ -73,3 +73,14 @@ const currentYear = new Date().getFullYear();
7373
</div>
7474
</div>
7575
</footer>
76+
77+
<style>
78+
.beian-link {
79+
text-decoration: underline;
80+
color: #4b6bfb; /* 蓝色 */
81+
transition: color 0.3s ease;
82+
}
83+
.beian-link:hover {
84+
color: #7c3aed; /* 紫色 */
85+
}
86+
</style>

blog-web/src/components/SEO.astro

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
---
2+
// SEO组件 - 提供更灵活的SEO管理
3+
interface Props {
4+
title?: string;
5+
description?: string;
6+
keywords?: string;
7+
author?: string;
8+
image?: string;
9+
type?: string;
10+
url?: string;
11+
publishedTime?: string;
12+
modifiedTime?: string;
13+
section?: string;
14+
tags?: string[];
15+
noindex?: boolean;
16+
canonical?: string;
17+
}
18+
19+
const {
20+
title = "ExquisiteCore - 个人博客",
21+
description = "ExquisiteCore的个人博客,分享全栈开发、游戏开发和技术思考。探索有趣的项目和创新想法。",
22+
keywords = "ExquisiteCore,个人博客,全栈开发,游戏开发,技术博客,编程,开发者",
23+
author = "ExquisiteCore",
24+
image = "https://blog.exquisitecore.xyz/logo.svg",
25+
type = "website",
26+
url = Astro.url.href,
27+
publishedTime,
28+
modifiedTime,
29+
section,
30+
tags = [],
31+
noindex = false,
32+
canonical = url,
33+
} = Astro.props;
34+
35+
// 生成结构化数据
36+
const structuredData = {
37+
"@context": "https://schema.org",
38+
"@type": type === "article" ? "BlogPosting" : "WebSite",
39+
name: title,
40+
headline: title,
41+
description: description,
42+
url: url,
43+
image: image,
44+
author: {
45+
"@type": "Person",
46+
name: author,
47+
url: "https://blog.exquisitecore.xyz",
48+
},
49+
publisher: {
50+
"@type": "Organization",
51+
name: "ExquisiteCore Blog",
52+
logo: {
53+
"@type": "ImageObject",
54+
url: "https://blog.exquisitecore.xyz/logo.svg",
55+
},
56+
},
57+
...(type === "article" &&
58+
publishedTime && {
59+
datePublished: publishedTime,
60+
dateModified: modifiedTime || publishedTime,
61+
articleSection: section,
62+
keywords: tags.join(", "),
63+
}),
64+
};
65+
---
66+
67+
<!-- 基础 SEO Meta 标签 -->
68+
<title>{title}</title>
69+
<meta name="description" content={description} />
70+
<meta name="keywords" content={keywords} />
71+
<meta name="author" content={author} />
72+
<meta name="robots" content={noindex ? "noindex, nofollow" : "index, follow"} />
73+
<link rel="canonical" href={canonical} />
74+
75+
<!-- Open Graph Meta 标签 -->
76+
<meta property="og:type" content={type} />
77+
<meta property="og:title" content={title} />
78+
<meta property="og:description" content={description} />
79+
<meta property="og:image" content={image} />
80+
<meta property="og:url" content={url} />
81+
<meta property="og:site_name" content="ExquisiteCore Blog" />
82+
<meta property="og:locale" content="zh_CN" />
83+
{
84+
type === "article" && publishedTime && (
85+
<>
86+
<meta property="article:published_time" content={publishedTime} />
87+
<meta
88+
property="article:modified_time"
89+
content={modifiedTime || publishedTime}
90+
/>
91+
<meta property="article:author" content={author} />
92+
{section && <meta property="article:section" content={section} />}
93+
{tags.map((tag) => (
94+
<meta property="article:tag" content={tag} />
95+
))}
96+
</>
97+
)
98+
}
99+
100+
<!-- Twitter Card Meta 标签 -->
101+
<meta name="twitter:card" content="summary_large_image" />
102+
<meta name="twitter:title" content={title} />
103+
<meta name="twitter:description" content={description} />
104+
<meta name="twitter:image" content={image} />
105+
<meta name="twitter:creator" content="@ExquisiteCore" />
106+
<meta name="twitter:site" content="@ExquisiteCore" />
107+
108+
<!-- 结构化数据 -->
109+
<script type="application/ld+json" set:html={JSON.stringify(structuredData)} />

0 commit comments

Comments
 (0)