-
-
Notifications
You must be signed in to change notification settings - Fork 11k
/
next.config.js
234 lines (219 loc) · 6.68 KB
/
next.config.js
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
const { THEME } = require('./blog.config')
const fs = require('fs')
const path = require('path')
const BLOG = require('./blog.config')
const { extractLangPrefix } = require('./lib/utils/pageId')
// 打包时是否分析代码
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: BLOG.BUNDLE_ANALYZER
})
// 扫描项目 /themes下的目录名
const themes = scanSubdirectories(path.resolve(__dirname, 'themes'))
// 检测用户开启的多语言
const locales = (function () {
// 根据BLOG_NOTION_PAGE_ID 检查支持多少种语言数据.
// 支持如下格式配置多个语言的页面id xxx,zh:xxx,en:xxx
const langs = [BLOG.LANG.slice(0, 2)]
if (BLOG.NOTION_PAGE_ID.indexOf(',') > 0) {
const siteIds = BLOG.NOTION_PAGE_ID.split(',')
for (let index = 0; index < siteIds.length; index++) {
const siteId = siteIds[index]
const prefix = extractLangPrefix(siteId)
// 如果包含前缀 例如 zh , en 等
if (prefix) {
if (!langs.includes(prefix)) {
langs.push(prefix)
}
}
}
}
return langs
})()
// 编译前执行
// eslint-disable-next-line no-unused-vars
const preBuild = (function () {
if (
!process.env.npm_lifecycle_event === 'export' &&
!process.env.npm_lifecycle_event === 'build'
) {
return
}
// 删除 public/sitemap.xml 文件 ; 否则会和/pages/sitemap.xml.js 冲突。
const sitemapPath = path.resolve(__dirname, 'public', 'sitemap.xml')
if (fs.existsSync(sitemapPath)) {
fs.unlinkSync(sitemapPath)
console.log('Deleted existing sitemap.xml from public directory')
}
const sitemap2Path = path.resolve(__dirname, 'sitemap.xml')
if (fs.existsSync(sitemap2Path)) {
fs.unlinkSync(sitemap2Path)
console.log('Deleted existing sitemap.xml from root directory')
}
})()
/**
* 扫描指定目录下的文件夹名,用于获取所有主题
* @param {*} directory
* @returns
*/
function scanSubdirectories(directory) {
const subdirectories = []
fs.readdirSync(directory).forEach(file => {
const fullPath = path.join(directory, file)
const stats = fs.statSync(fullPath)
if (stats.isDirectory()) {
subdirectories.push(file)
}
// subdirectories.push(file)
})
return subdirectories
}
/**
* @type {import('next').NextConfig}
*/
const nextConfig = {
eslint: {
ignoreDuringBuilds: true
},
output: process.env.EXPORT ? 'export' : process.env.NEXT_BUILD_STANDALONE === 'true' ? 'standalone' : undefined,
staticPageGenerationTimeout: 120,
// 多语言, 在export时禁用
i18n: process.env.EXPORT
? undefined
: {
defaultLocale: BLOG.LANG.slice(0, 2),
// 支持的所有多语言,按需填写即可
locales
},
images: {
// 图片压缩
formats: ['image/avif', 'image/webp'],
// 允许next/image加载的图片 域名
domains: [
'gravatar.com',
'www.notion.so',
'avatars.githubusercontent.com',
'images.unsplash.com',
'source.unsplash.com',
'p1.qhimg.com',
'webmention.io',
'ko-fi.com'
]
},
// 默认将feed重定向至 /public/rss/feed.xml
redirects: process.env.EXPORT
? undefined
: async () => {
return [
{
source: '/feed',
destination: '/rss/feed.xml',
permanent: true
}
]
},
// 重写url
rewrites: process.env.EXPORT
? undefined
: async () => {
// 处理多语言重定向
const langsRewrites = []
if (BLOG.NOTION_PAGE_ID.indexOf(',') > 0) {
const siteIds = BLOG.NOTION_PAGE_ID.split(',')
const langs = []
for (let index = 0; index < siteIds.length; index++) {
const siteId = siteIds[index]
const prefix = extractLangPrefix(siteId)
// 如果包含前缀 例如 zh , en 等
if (prefix) {
langs.push(prefix)
}
console.log('[Locales]', siteId)
}
// 映射多语言
// 示例: source: '/:locale(zh|en)/:path*' ; :locale() 会将语言放入重写后的 `?locale=` 中。
langsRewrites.push(
{
source: `/:locale(${langs.join('|')})/:path*`,
destination: '/:path*'
},
// 匹配没有路径的情况,例如 [domain]/zh 或 [domain]/en
{
source: `/:locale(${langs.join('|')})`,
destination: '/'
},
// 匹配没有路径的情况,例如 [domain]/zh/ 或 [domain]/en/
{
source: `/:locale(${langs.join('|')})/`,
destination: '/'
}
)
}
return [
...langsRewrites,
// 伪静态重写
{
source: '/:path*.html',
destination: '/:path*'
}
]
},
headers: process.env.EXPORT
? undefined
: async () => {
return [
{
source: '/:path*{/}?',
headers: [
{ key: 'Access-Control-Allow-Credentials', value: 'true' },
{ key: 'Access-Control-Allow-Origin', value: '*' },
{
key: 'Access-Control-Allow-Methods',
value: 'GET,OPTIONS,PATCH,DELETE,POST,PUT'
},
{
key: 'Access-Control-Allow-Headers',
value:
'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version'
}
]
}
]
},
webpack: (config, { dev, isServer }) => {
// 动态主题:添加 resolve.alias 配置,将动态路径映射到实际路径
config.resolve.alias['@'] = path.resolve(__dirname)
if (!isServer) {
console.log('[默认主题]', path.resolve(__dirname, 'themes', THEME))
}
config.resolve.alias['@theme-components'] = path.resolve(
__dirname,
'themes',
THEME
)
// Enable source maps in development mode
if (process.env.NODE_ENV_API === 'development') {
config.devtool = 'source-map'
}
return config
},
experimental: {
scrollRestoration: true
},
exportPathMap: async function (
defaultPathMap,
{ dev, dir, outDir, distDir, buildId }
) {
// export 静态导出时 忽略/pages/sitemap.xml.js , 否则和getServerSideProps这个动态文件冲突
const pages = { ...defaultPathMap }
delete pages['/sitemap.xml']
delete pages['/auth']
return pages
},
publicRuntimeConfig: {
// 这里的配置既可以服务端获取到,也可以在浏览器端获取到
THEMES: themes
}
}
module.exports = process.env.ANALYZE
? withBundleAnalyzer(nextConfig)
: nextConfig