import 'dotenv/config' import fs from 'node:fs/promises'; import { URL } from 'node:url'; import { Transform } from 'node:stream'; import { Readable } from 'node:stream'; import { Hono } from 'hono'; import { logger } from 'hono/logger'; import { createServer as createNodeServer } from 'node:http'; import process from 'node:process'; import { createAdaptorServer } from '@hono/node-server' // 创建 Hono 应用 const app = new Hono(); // 全局使用 Hono 日志中间件 app.use('*', logger()); // 常量定义 const isProduction = process.env.NODE_ENV === 'production'; const port = process.env.PORT || 8080; const base = process.env.BASE || '/'; const ABORT_DELAY = 10000; console.log('========================================'); console.log('开始初始化服务器...'); console.log(`环境: ${isProduction ? '生产环境' : '开发环境'}`); console.log(`端口: ${port}`); console.log(`基础路径: ${base}`); console.log('========================================'); // 解析基础路径为 URL 对象 const baseUrl = new URL(base, `http://localhost:${port}`); console.log(`基础URL解析完成: ${baseUrl.href}`); // 创建服务器实例 console.log('正在创建服务器实例...'); const parentServer = createAdaptorServer({ fetch: app.fetch, createServer: createNodeServer, port: port, }) console.log('服务器实例创建成功'); // 生产环境中间件 let compressionMiddleware; let sirvMiddleware; if (isProduction) { console.log('生产环境: 加载压缩和静态文件中间件...'); compressionMiddleware = (await import('compression')).default(); sirvMiddleware = (await import('sirv')).default('./dist/client', { extensions: [], baseUrl: base }); console.log('生产环境中间件加载完成'); } // Vite 开发服务器 /** @type {import('vite').ViteDevServer | undefined} */ let vite; if (!isProduction) { console.log('开发环境: 初始化 Vite 开发服务器...'); const { createServer } = await import('vite'); vite = await createServer({ server: { middlewareMode: { server: parentServer }, hmr: { port: 8081, clientPort: 443, path: 'vite-hmr' }, proxy: { '/vite-hmr': { target: 'ws://localhost:8081', ws: true, }, }, }, appType: 'custom', base, }); console.log('Vite 开发服务器初始化完成'); } // 开发环境模板处理函数 - 仅处理模板转换 const processDevTemplate = async (template) => { if (!isProduction && vite) { console.log('开发环境: 处理模板...'); const processedTemplate = await vite.transformIndexHtml('/', template); console.log('开发环境模板处理完成'); return processedTemplate; } return template; }; // 生产环境模板处理函数 - 仅处理资源路径替换 const processProdTemplate = async (template) => { console.log('生产环境: 处理模板资源路径...'); try { // 读取 manifest const manifestPath = new URL('./dist/client/.vite/manifest.json', import.meta.url); const manifestContent = await fs.readFile(manifestPath, 'utf-8'); const manifest = JSON.parse(manifestContent); console.log('生产环境: 成功读取 manifest.json'); // 获取 src/client/index.tsx 对应的资源信息 const indexManifest = manifest['src/client/index.tsx']; if (!indexManifest) { throw new Error('manifest 中未找到 src/client/index.tsx 入口配置'); } // 获取 src/style.css 对应的资源信息 const styleManifest = manifest['src/style.css']; if (!styleManifest) { throw new Error('manifest 中未找到 src/style.css 入口配置'); } const cssPath = new URL(styleManifest.file, baseUrl).pathname; const cssLinks = ``; // 替换入口脚本 const jsEntryPath = new URL(indexManifest.file, baseUrl).pathname; const entryScript = ``; // 执行替换 const processedTemplate = template .replace(//, cssLinks) .replace(/