Files
NotionNext/next.config.js
2025-05-27 10:06:47 +08:00

239 lines
6.7 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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]
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,
// 支持的所有多语言,按需填写即可
locales: 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
: () => {
return [
{
source: '/feed',
destination: '/rss/feed.xml',
permanent: true
}
]
},
// 重写url
rewrites: process.env.EXPORT
? undefined
: () => {
// 处理多语言重定向
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
: () => {
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: 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