Files
task-manager/server/index.ts
T
paul-nothaft e0512aa412
continuous-integration/drone/push Build is passing
Fix Vite module not found error in production Docker deployments
Update Dockerfile to compile server files separately without bundling, preventing Vite dependency issues in production. Includes troubleshooting documentation for the Vite module error.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: ceced2fc-aa46-458d-ba87-ddd4b7bb1518
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/659922a9-0087-461c-90dd-6d9a58b81d4d/ceced2fc-aa46-458d-ba87-ddd4b7bb1518/SBF5OKZ
2025-10-23 15:00:04 +00:00

132 lines
3.8 KiB
TypeScript

import express, { type Request, Response, NextFunction } from "express";
import { registerRoutes } from "./routes";
import { initializeDatabase, closeDatabase } from "./db";
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use((req, res, next) => {
const start = Date.now();
const path = req.path;
let capturedJsonResponse: Record<string, any> | undefined = undefined;
const originalResJson = res.json;
res.json = function (bodyJson, ...args) {
capturedJsonResponse = bodyJson;
return originalResJson.apply(res, [bodyJson, ...args]);
};
res.on("finish", () => {
const duration = Date.now() - start;
if (path.startsWith("/api")) {
const formattedTime = new Date().toLocaleTimeString("en-US", {
hour: "numeric",
minute: "2-digit",
second: "2-digit",
hour12: true,
});
let logLine = `${req.method} ${path} ${res.statusCode} in ${duration}ms`;
if (capturedJsonResponse) {
logLine += ` :: ${JSON.stringify(capturedJsonResponse)}`;
}
if (logLine.length > 80) {
logLine = logLine.slice(0, 79) + "…";
}
console.log(`${formattedTime} [express] ${logLine}`);
}
});
next();
});
(async () => {
// Import utilities based on environment
// Use require-style imports to avoid bundler issues
let log: (message: string, source?: string) => void;
let serveStatic: (app: express.Express) => void;
let setupVite: ((app: express.Express, server: any) => Promise<void>) | undefined;
if (app.get("env") === "development") {
try {
const viteModule = await import("./vite");
log = viteModule.log;
setupVite = viteModule.setupVite;
serveStatic = viteModule.serveStatic;
} catch (error) {
console.error("Failed to load vite module:", error);
process.exit(1);
}
} else {
const staticModule = await import("./static");
log = staticModule.log;
serveStatic = staticModule.serveStatic;
}
// Initialize database if using production mode or USE_DB is true
if (process.env.NODE_ENV === 'production' || process.env.USE_DB === 'true') {
try {
await initializeDatabase();
} catch (error) {
console.error('Failed to initialize database:', error);
process.exit(1);
}
}
const server = await registerRoutes(app);
app.use((err: any, _req: Request, res: Response, _next: NextFunction) => {
const status = err.status || err.statusCode || 500;
const message = err.message || "Internal Server Error";
res.status(status).json({ message });
throw err;
});
// importantly only setup vite in development and after
// setting up all the other routes so the catch-all route
// doesn't interfere with the other routes
if (app.get("env") === "development") {
if (setupVite) {
await setupVite(app, server);
}
} else {
serveStatic(app);
}
// ALWAYS serve the app on the port specified in the environment variable PORT
// Other ports are firewalled. Default to 5000 if not specified.
// this serves both the API and the client.
// It is the only port that is not firewalled.
const port = parseInt(process.env.PORT || '5000', 10);
server.listen({
port,
host: "0.0.0.0",
reusePort: true,
}, () => {
log(`serving on port ${port}`);
});
// Graceful shutdown
const gracefulShutdown = async (signal: string) => {
log(`${signal} received, closing server gracefully...`);
server.close(async () => {
log('HTTP server closed');
await closeDatabase();
process.exit(0);
});
// Force close after 30 seconds
setTimeout(() => {
console.error('Forced shutdown after timeout');
process.exit(1);
}, 30000);
};
process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
process.on('SIGINT', () => gracefulShutdown('SIGINT'));
})();