brackt/server.ts

88 lines
2.6 KiB
TypeScript
Raw Normal View History

import compression from "compression";
import express, { Express, Request, Response, NextFunction } from "express";
import morgan from "morgan";
import { createServer } from "http";
import type { ViteDevServer } from "vite";
import path from "path";
import { fileURLToPath } from "url";
// ESM module resolution helpers
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Configuration
// Resolve paths relative to project root (one level up from dist/ in production, or current dir in dev)
const PROJECT_ROOT = path.resolve(__dirname, "..");
const BUILD_PATH = path.join(PROJECT_ROOT, "build/server/index.js");
const CLIENT_BUILD_PATH = path.join(PROJECT_ROOT, "build/client");
const CLIENT_ASSETS_PATH = path.join(PROJECT_ROOT, "build/client/assets");
const DEVELOPMENT = process.env.NODE_ENV === "development";
const PORT = Number.parseInt(process.env.PORT || "3000", 10);
async function createAppServer(): Promise<void> {
const app: Express = express();
app.use(compression());
app.disable("x-powered-by");
if (DEVELOPMENT) {
console.log("Starting development server");
// Dynamic import Vite only in development
const { createServer: createViteServer } = await import("vite");
const viteDevServer: ViteDevServer = await createViteServer({
server: { middlewareMode: true },
});
app.use(viteDevServer.middlewares);
app.use(async (req: Request, res: Response, next: NextFunction) => {
try {
const source = await viteDevServer.ssrLoadModule("./server/app.ts");
return await source.app(req, res, next);
} catch (error) {
if (error instanceof Error) {
viteDevServer.ssrFixStacktrace(error);
}
next(error);
}
});
} else {
console.log("Starting production server");
app.use(
"/assets",
express.static(CLIENT_ASSETS_PATH, {
immutable: true,
maxAge: "1y"
})
);
app.use(morgan("tiny"));
app.use(express.static(CLIENT_BUILD_PATH, { maxAge: "1h" }));
// Import the built React Router app
const { app: productionApp } = await import(BUILD_PATH);
app.use(productionApp);
}
// Create HTTP server
const httpServer = createServer(app);
// Initialize Socket.IO
const { initializeSocketIO } = await import("./server/socket");
initializeSocketIO(httpServer);
// Start server
httpServer.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
}
// Start the server with error handling
createAppServer().catch((error) => {
console.error("Failed to start server:", error);
process.exit(1);
});