accounts/dashboard/next.config.js.bak
Haitao Pan b4696470f6 feat(dashboard): upgrade Next.js 14 → 16 with Turbopack support
- Fix @theme module resolution for Turbopack
- Add external image domain config (dl.svc.plus)
- Resolve YAML file module type errors
- Support RUNTIME_ENV env var for config selection
- Optimize next.config.mjs for Next.js 16 compatibility

Closes #upgrade-next16
2025-11-06 10:21:19 +08:00

102 lines
2.9 KiB
JavaScript
Raw 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.

/**
* 功能控制的树形结构,每个节点都可以通过 enabled 控制是否启用。
* - children 支持精确路径、动态段([param])、以及通配符(*)。
* - 当某个节点 enabled 为 false 时,其所有子级都会默认关闭。
*/
const path = require('path')
const featureToggles = require('./config/feature-toggles.json')
const normalizeSegments = (pathname = '') =>
pathname
.replace(/^\/+|\/+$/g, '')
.split('/')
.filter(Boolean)
const findDynamicChildKey = (children = {}) =>
Object.keys(children).find((key) => /^\[(\.\.\.)?.+\]$/.test(key))
const resolveToggle = (node, segments) => {
if (!node) return true
const isEnabled = node.enabled !== false
if (!isEnabled) return false
if (!segments.length) return isEnabled
const children = node.children || {}
const [current, ...rest] = segments
const exactChild = children[current]
const dynamicChildKey = findDynamicChildKey(children)
const wildcardChild = children['*']
const nextNode =
exactChild ?? (dynamicChildKey ? children[dynamicChildKey] : undefined) ?? wildcardChild
if (!nextNode) return isEnabled
return resolveToggle(nextNode, rest)
}
const isFeatureEnabled = (section, pathname) => {
const tree = featureToggles[section]
if (!tree) return true
const segments = normalizeSegments(pathname)
return resolveToggle(tree, segments)
}
// Static exports are incompatible with dynamic route handlers used for auth.
// Allow opting-in explicitly to avoid breaking the default production build.
const shouldUseStaticExport = process.env.NEXT_SHOULD_EXPORT === 'true'
/** @type {import('next').NextConfig} */
const nextConfig = {
...(shouldUseStaticExport ? { output: 'export' } : {}),
trailingSlash: false,
reactStrictMode: true,
compress: false, // 压缩交给 Nginx省 Node CPU
poweredByHeader: false,
images: { unoptimized: true }, // 关闭服务端图片处理
httpAgentOptions: {
keepAlive: true,
},
async headers() {
return [
{
source: '/api/:path*',
headers: [
{
key: 'Cache-Control',
value: 'no-store',
},
],
},
]
},
async rewrites() {
return [
{
source: '/api/:path*/',
destination: '/api/:path*',
},
]
},
webpack(config) {
config.module.rules.push({
test: /\.ya?ml$/i,
type: 'asset/source',
})
config.resolve.alias = {
...(config.resolve.alias ?? {}),
'@cms': path.join(__dirname, 'cms'),
'@components': path.join(__dirname, 'components'),
'@i18n': path.join(__dirname, 'i18n'),
'@lib': path.join(__dirname, 'lib'),
'@types': path.join(__dirname, 'types'),
'@server': path.join(__dirname, 'server'),
'@theme': path.join(__dirname, 'src', 'theme'),
'@templates': path.join(__dirname, 'src', 'templates'),
'@src': path.join(__dirname, 'src'),
}
return config
},
}
module.exports = nextConfig