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(/