Files
brunoandClaude Sonnet 4.5 ec96907fb6 feat: 初始化 LJWX Docs 文档站点
## 功能特性
- ✨ VitePress 1.0 框架,支持中英文双语
- 🌐 远程访问支持(0.0.0.0:5555)
- 🎨 专业级代码块样式(圆角阴影、悬浮效果、智能复制)
- 📊 Mermaid 流程图优化(主题色节点、平滑连线)
- 📋 表格美化(渐变表头、行悬浮高亮)
- 🔍 本地搜索功能(Cmd+K 快捷键)
- 🌓 深色模式完美适配
- 💬 Giscus 评论系统集成
- 📱 响应式设计(移动端优化)

## 技术栈
- VitePress 1.0.1
- Vue 3.4.19
- TypeScript
- Express (生产服务器)

## 文档包含
- 知识资产化系统架构设计
- 自动化发布使用指南
- Dify 知识库同步指南
- 快速参考手册

## 部署支持
- Node.js 服务器
- Docker 容器化
- Nginx 静态托管
- Kubernetes 集群部署

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-23 16:06:02 +08:00

95 lines
3.0 KiB
JavaScript

import express from 'express'
import compression from 'compression'
import sirv from 'sirv'
import { fileURLToPath } from 'url'
import { dirname, join } from 'path'
import { existsSync } from 'fs'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
const app = express()
const PORT = process.env.PORT || 5555
const HOST = process.env.HOST || '0.0.0.0'
// 检查构建目录是否存在
const distPath = join(__dirname, 'dist')
if (!existsSync(distPath)) {
console.error('❌ Error: dist directory not found!')
console.error('Please run "npm run docs:build" first to build the documentation.')
process.exit(1)
}
// 启用 Gzip 压缩
app.use(compression())
// 添加安全响应头
app.use((req, res, next) => {
res.setHeader('X-Content-Type-Options', 'nosniff')
res.setHeader('X-Frame-Options', 'DENY')
res.setHeader('X-XSS-Protection', '1; mode=block')
next()
})
// 静态文件服务
const serve = sirv(distPath, {
etag: true,
maxAge: 31536000, // 1 year for immutable assets
immutable: true,
gzip: true,
brotli: true,
setHeaders: (res, pathname) => {
// HTML 文件不缓存,确保内容更新
if (pathname.endsWith('.html')) {
res.setHeader('Cache-Control', 'no-cache, must-revalidate')
}
// 静态资源长期缓存
else if (pathname.match(/\.(js|css|png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot|ico)$/)) {
res.setHeader('Cache-Control', 'public, max-age=31536000, immutable')
}
}
})
app.use(serve)
// SPA 回退处理
app.get('*', (req, res) => {
res.sendFile(join(distPath, 'index.html'))
})
// 错误处理
app.use((err, req, res, next) => {
console.error('Server error:', err)
res.status(500).send('Internal Server Error')
})
// 优雅关闭
const server = app.listen(PORT, HOST, () => {
console.log('┌─────────────────────────────────────────────┐')
console.log('│ │')
console.log('│ 🚀 LJWX Docs Server Started │')
console.log('│ │')
console.log(`│ ➜ Local: http://localhost:${PORT} │`)
console.log(`│ ➜ Network: http://${HOST}:${PORT} │`)
console.log('│ │')
console.log('│ Press Ctrl+C to stop │')
console.log('│ │')
console.log('└─────────────────────────────────────────────┘')
})
process.on('SIGTERM', () => {
console.log('\n⏳ SIGTERM signal received: closing HTTP server')
server.close(() => {
console.log('✅ HTTP server closed')
process.exit(0)
})
})
process.on('SIGINT', () => {
console.log('\n⏳ SIGINT signal received: closing HTTP server')
server.close(() => {
console.log('✅ HTTP server closed')
process.exit(0)
})
})