AwsLinker/scripts/test-static.js
2025-09-16 17:19:58 +08:00

195 lines
5.8 KiB
JavaScript

#!/usr/bin/env node
/**
* 测试静态构建和404页面功能
*/
const fs = require('fs');
const path = require('path');
function testStaticBuild() {
console.log('🧪 测试静态构建...\n');
const checks = [
{
name: 'out目录存在',
test: () => fs.existsSync('out'),
required: true
},
{
name: 'index.html存在',
test: () => fs.existsSync('out/index.html'),
required: true
},
{
name: '404.html存在',
test: () => fs.existsSync('out/404.html'),
required: true
},
{
name: 'public/404.html存在',
test: () => fs.existsSync('public/404.html'),
required: true
},
{
name: 'zh-CN目录存在',
test: () => fs.existsSync('out/zh-CN'),
required: false
},
{
name: 'en目录存在',
test: () => fs.existsSync('out/en'),
required: false
},
{
name: 'zh-TW目录存在',
test: () => fs.existsSync('out/zh-TW'),
required: false
}
];
let passed = 0;
let failed = 0;
checks.forEach(check => {
const result = check.test();
const icon = result ? '✅' : (check.required ? '❌' : '⚠️');
const status = result ? 'PASS' : (check.required ? 'FAIL' : 'SKIP');
console.log(`${icon} ${check.name}: ${status}`);
if (result) {
passed++;
} else if (check.required) {
failed++;
}
});
console.log(`\n📊 测试结果: ${passed} 通过, ${failed} 失败\n`);
if (failed > 0) {
console.log('❌ 静态构建测试失败!');
console.log('💡 建议运行: npm run build:static\n');
return false;
} else {
console.log('✅ 静态构建测试通过!\n');
return true;
}
}
function test404Content() {
console.log('🔍 测试404页面内容...\n');
const files = ['public/404.html', 'out/404.html'];
files.forEach(file => {
if (fs.existsSync(file)) {
const content = fs.readFileSync(file, 'utf8');
const checks = [
{ name: '包含DOCTYPE', test: content.includes('<!DOCTYPE html>') },
{ name: '包含404标题', test: content.includes('404') },
{ name: '包含语言检测', test: content.includes('detectLanguage') },
{ name: '包含样式', test: content.includes('<style>') },
{ name: '包含JavaScript', test: content.includes('<script>') },
{ name: '包含导航链接', test: content.includes('btn-primary') }
];
console.log(`📄 ${file}:`);
checks.forEach(check => {
const icon = check.test ? '✅' : '❌';
console.log(` ${icon} ${check.name}`);
});
console.log();
} else {
console.log(`${file} 不存在\n`);
}
});
}
function checkHydrationIssues() {
console.log('🔍 检查潜在的hydration问题...\n');
const problematicPatterns = [
{
pattern: /new Date\(\)/g,
description: '使用 new Date() 可能导致服务器和客户端时间不匹配'
},
{
pattern: /window\./g,
description: '直接使用 window 对象而没有检查 typeof window !== "undefined"'
},
{
pattern: /document\./g,
description: '直接使用 document 对象而没有检查'
},
{
pattern: /localStorage/g,
description: '使用 localStorage 可能导致hydration问题'
},
{
pattern: /sessionStorage/g,
description: '使用 sessionStorage 可能导致hydration问题'
}
];
const componentFiles = [
'app/components/Header.tsx',
'app/components/news/BackButton.tsx',
'app/components/news/ShareButton.tsx',
'app/components/news/NewsPageClient.tsx',
'app/components/news/NewsArticlePageClient.tsx'
];
let issuesFound = 0;
componentFiles.forEach(file => {
if (fs.existsSync(file)) {
const content = fs.readFileSync(file, 'utf8');
problematicPatterns.forEach(pattern => {
const matches = content.match(pattern.pattern);
if (matches) {
// 检查是否有适当的检查
const hasCheck = content.includes('typeof window !== "undefined"') ||
content.includes('typeof document !== "undefined"') ||
content.includes('useEffect');
if (!hasCheck) {
console.log(`⚠️ ${file}: ${pattern.description}`);
console.log(` 发现 ${matches.length} 个匹配项\n`);
issuesFound++;
}
}
});
}
});
if (issuesFound === 0) {
console.log('✅ 未发现明显的hydration问题\n');
} else {
console.log(`⚠️ 发现 ${issuesFound} 个潜在的hydration问题\n`);
}
}
function main() {
console.log('🚀 静态构建测试工具\n');
console.log('=' .repeat(50));
const buildOk = testStaticBuild();
test404Content();
checkHydrationIssues();
console.log('=' .repeat(50));
if (buildOk) {
console.log('🎉 测试完成!可以运行 npm run preview 预览网站');
} else {
console.log('❌ 测试失败!请检查构建过程');
process.exit(1);
}
}
if (require.main === module) {
main();
}