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
4.3 KiB
Docker Deployment Fix - Vite Module Error
Problem
When deploying the TaskFlow application using a Docker image built by Drone CI, the container failed to start with the following error:
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'vite' imported from /app/dist/index.js
Root Cause
The issue occurred because:
- Build Process: The original build script used esbuild with the
--bundleflag, which bundled all imports (including dynamic imports) into a singledist/index.jsfile - Production Dependencies: The Dockerfile only installed production dependencies (excluding dev dependencies like
vite) - Import Resolution: Even though the code conditionally imported vite only in development, the bundled JavaScript still contained references to the vite module
- Runtime Failure: At runtime in production, Node.js tried to resolve the vite module which wasn't available in node_modules
Solution Implemented
Changed Build Strategy
Instead of bundling all server code into a single file, we now compile each server file separately without bundling:
Before (bundled):
esbuild server/index.ts --platform=node --packages=external --bundle --format=esm --outdir=dist
After (separate compilation):
esbuild server/index.ts server/routes.ts server/storage.ts server/db.ts server/static.ts --platform=node --packages=external --format=esm --outdir=dist
Updated Dockerfile
The Dockerfile now explicitly compiles each server module separately:
# Build server files separately (without bundling)
RUN npx esbuild server/index.ts server/routes.ts server/storage.ts server/db.ts server/static.ts --platform=node --packages=external --format=esm --outdir=dist
Created Production-Only Module
Created server/static.ts containing only production dependencies:
log()function for loggingserveStatic()function for serving built frontend assets- No vite imports
Conditional Module Loading
Updated server/index.ts to dynamically load the appropriate module:
if (app.get("env") === "development") {
const viteModule = await import("./vite"); // Loads vite in dev
// ...
} else {
const staticModule = await import("./static"); // Loads production module
// ...
}
How It Works Now
Development Mode
- NODE_ENV is set to "development"
- Server imports
./vitemodule (includes vite dependency) - Vite dev server starts with HMR
Production Mode (Docker)
- NODE_ENV is set to "production"
- Server imports
./staticmodule (no vite dependency) - Serves pre-built static files from
dist/public - vite is never loaded or required
Files Modified
- ✅
server/static.ts- New production-only module - ✅
server/index.ts- Conditional module loading - ✅
Dockerfile- Separate server file compilation
Testing
Local Development
npm run dev
# Should work as before with Vite HMR
Docker Build & Run
# Build image (or let Drone CI do it)
docker build -t taskflow:latest .
# Run with docker-compose
docker-compose up -d
# Check logs
docker-compose logs -f app
# Should see:
# serving on port 5000
# Database schema is up to date
# ✓ Database initialized successfully
Benefits
- ✅ Smaller Production Image - Only production dependencies included
- ✅ Faster Startup - No vite module loading in production
- ✅ Cleaner Separation - Development and production code paths are separate
- ✅ Easier Debugging - Separate compiled files instead of one bundled file
- ✅ No Runtime Errors - Production never tries to load vite
Drone CI Integration
Your .drone.yml file doesn't need any changes. The Docker build process now correctly handles the server compilation.
When Drone builds your image, it will:
- Install all dependencies (dev + prod) in build stage
- Build frontend with Vite
- Compile server files separately
- Copy only production dependencies to final image
- Copy compiled server files (without vite references)
Deployment
After Drone builds and pushes your image, deploy it with:
# Pull latest image
docker pull registry.local.nothaft.cloud/taskflow:latest
# Start with docker-compose
docker-compose up -d
The application will now start successfully without the vite module error! 🚀