main Initial commit
This commit is contained in:
commit
ac7df91600
65 changed files with 8957 additions and 0 deletions
115
src/services/ViteService.ts
Normal file
115
src/services/ViteService.ts
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
import express from 'express';
|
||||
import fs from 'fs/promises';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import tailwindcss from '@tailwindcss/vite';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import logger from '../utils/logger.js';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
export class ViteService {
|
||||
private static server: any = null;
|
||||
|
||||
static async setupMiddleware(app: express.Application, isProduction: boolean = false, base: string = '/') {
|
||||
try {
|
||||
const webRoot = path.resolve(__dirname, '../web');
|
||||
const distDir = path.resolve(__dirname, '../../dist/web');
|
||||
|
||||
if (!isProduction) {
|
||||
// Add CSP middleware for development
|
||||
app.use((req, res, next) => {
|
||||
res.setHeader('Content-Security-Policy',
|
||||
"default-src 'self'; " +
|
||||
"script-src 'self' 'unsafe-inline' 'unsafe-eval'; " +
|
||||
"connect-src 'self' ws: wss: http: https:; " +
|
||||
"style-src 'self' 'unsafe-inline';"
|
||||
);
|
||||
next();
|
||||
});
|
||||
|
||||
// Create vite server
|
||||
const vite = await import('vite');
|
||||
|
||||
const viteServer = await vite.createServer({
|
||||
plugins: [react(), tailwindcss()],
|
||||
root: webRoot,
|
||||
server: {
|
||||
middlewareMode: true
|
||||
},
|
||||
appType: 'spa',
|
||||
base,
|
||||
build: {
|
||||
outDir: distDir,
|
||||
emptyOutDir: true,
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': webRoot,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
app.use(base, viteServer.middlewares);
|
||||
this.server = viteServer;
|
||||
|
||||
logger.info(`🎨 Vite dev middleware setup on ${base}`);
|
||||
} else {
|
||||
// Production mode - serve static files
|
||||
const publicDir = distDir;
|
||||
|
||||
// Serve static assets
|
||||
app.use(base, express.static(publicDir));
|
||||
|
||||
logger.info(`📦 Static files served from ${publicDir} on ${base}`);
|
||||
}
|
||||
|
||||
// SPA fallback middleware - works for both dev and prod, but only for non-API routes
|
||||
app.use((req, res, next) => {
|
||||
// Skip API routes and static assets
|
||||
if (req.path.startsWith('/api/') || req.path.includes('.')) {
|
||||
return next();
|
||||
}
|
||||
|
||||
if (!isProduction) {
|
||||
// In development, let Vite handle SPA routing
|
||||
return next();
|
||||
}
|
||||
|
||||
// In production, serve index.html for SPA routes
|
||||
const indexPath = path.join(distDir, 'index.html');
|
||||
fs.readFile(indexPath, 'utf-8')
|
||||
.then(index => {
|
||||
res.set('content-type', 'text/html');
|
||||
res.send(index);
|
||||
})
|
||||
.catch(error => {
|
||||
logger.error('Failed to serve index.html:', error);
|
||||
res.status(404).send('Frontend not built. Please run build first.');
|
||||
});
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
logger.error('Failed to setup Vite middleware:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
static async stop() {
|
||||
if (this.server) {
|
||||
await this.server.close();
|
||||
logger.info('Vite server stopped');
|
||||
this.server = null;
|
||||
}
|
||||
}
|
||||
|
||||
static isRunning() {
|
||||
return this.server !== null;
|
||||
}
|
||||
|
||||
// Legacy method for backward compatibility
|
||||
static async startDevServer(port: number = 3001) {
|
||||
logger.warn('startDevServer is deprecated. Use setupMiddleware instead.');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue