-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsitemap.config.js
More file actions
151 lines (142 loc) · 4.09 KB
/
Copy pathsitemap.config.js
File metadata and controls
151 lines (142 loc) · 4.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/** @type {import('next-sitemap').IConfig} */
module.exports = {
siteUrl: process.env.SITE_URL || 'https://www.rsstabs.com',
generateRobotsTxt: true,
generateIndexSitemap: true,
sitemapSize: 1000,
alternateRefs: [
{
href: 'https://www.rsstabs.com',
hreflang: 'en'
},
{
href: 'https://www.rsstabs.com/zh',
hreflang: 'zh'
},
{
href: 'https://www.rsstabs.com/ja',
hreflang: 'ja'
},
{
href: 'https://www.rsstabs.com/ru',
hreflang: 'ru'
}
],
robotsTxtOptions: {
policies: [
{
userAgent: '*',
disallow: ['/api/*', '/_next/*', '/static/*'],
allow: '/'
}
],
additionalSitemaps: ['https://doc.rsstabs.com/sitemap.xml']
},
transform: async (config, path) => {
return {
loc: path,
changefreq: path.includes('/post/') ? 'daily' : 'weekly',
priority: path.includes('/post/') ? 0.7 : 0.9,
lastmod: config.autoLastmod ? new Date().toISOString() : undefined,
alternateRefs: config.alternateRefs ?? []
}
},
additionalPaths: async config => {
const locales = ['', 'zh', 'ja', 'ru']
const routes = [
'', // 首页
'/posts',
'/tags'
]
// 基础路由
const basicPaths = locales.flatMap(locale =>
routes.map(route => `/${locale}${route}`.replace('//', '/'))
)
// 重试函数
async function fetchWithRetry(url, options, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
const response = await fetch(url, {
...options,
timeout: 10000, // 10 秒超时
keepalive: true
})
if (response.ok) return response
} catch (err) {
console.error(`Attempt ${i + 1} failed:`, err)
if (i === retries - 1) throw err
// 等待一段时间后重试
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)))
}
}
throw new Error('Max retries reached')
}
const API_BASE_URL =
process.env.NEXT_PUBLIC_API_URL || 'https://api.rsstabs.com/rss'
try {
// 获取文章总数
const countRes = await fetchWithRetry(
`${API_BASE_URL}/api/articles/ssr/searchList`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
page: {
currentPage: 1,
pageSize: 1
}
})
}
)
const {
data: { total }
} = await countRes.json()
const pageSize = 1000
const totalPages = Math.ceil(total / pageSize)
const articlePaths = []
// 分页获取所有文章
for (let page = 1; page <= totalPages; page++) {
try {
const res = await fetchWithRetry(
`${API_BASE_URL}/api/articles/ssr/searchList`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
page: {
currentPage: page,
pageSize
}
})
}
)
const { data } = await res.json()
// 生成文章路径
const pagePaths = data.list.flatMap(article =>
locales.map(locale =>
`/${locale}${locale ? '/' : ''}post/${article.articleId}`.replace(
'//',
'/'
)
)
)
articlePaths.push(...pagePaths)
} catch (err) {
console.error(`Failed to fetch page ${page}:`, err)
continue // 跳过失败的页面,继续处理下一页
}
}
// 合并所有路径
const allPaths = [...basicPaths, ...articlePaths]
return Promise.all(allPaths.map(path => config.transform(config, path)))
} catch (error) {
console.error('Error generating article paths for sitemap:', error)
// 如果出错,至少返回基础路径
return Promise.all(basicPaths.map(path => config.transform(config, path)))
}
}
}