import {createRequestHandler} from '@remix-run/express'; import compression from 'compression'; import express from 'express'; import morgan from 'morgan'; // patch pixi server context import('./app/server/pixi-context.js'); const isProduction = process.env.NODE_ENV === 'production'; const isInsecure = process.env.SILPHIUS_INSECURE_HTTP; const app = express(); let server; if (isInsecure) { const {createServer} = await import('node:http'); server = createServer(app); } else { const {execSync} = await import('node:child_process'); const {mkdirSync, readFileSync, statSync} = await import('node:fs'); const cacheDirectory = `${import.meta.dirname}/node_modules/.cache`; mkdirSync(cacheDirectory, {recursive: true}); try { statSync(`${cacheDirectory}/localhost-key.pem`); } catch (error) { // eslint-disable-line no-unused-vars execSync(`mkcert -cert-file ${cacheDirectory}/localhost.pem -key-file ${cacheDirectory}/localhost-key.pem localhost`) } const serverOptions = { key: readFileSync(`${cacheDirectory}/localhost-key.pem`), cert: readFileSync(`${cacheDirectory}/localhost.pem`), }; const {createServer} = await import('node:https'); server = createServer(serverOptions, app); } // immediately start listening and queueing up connections let resolve, promise = new Promise((res) => { resolve = res; }); app.use(async (req, res, next) => { await promise; next(); }); const port = process.env.PORT || 3000; server.listen(port, () => console.log(`Express server listening at http${isInsecure ? '' : 's'}://localhost:${port}`) ); // possibly load dev server and build the request handler up front const viteDevServer = isProduction ? undefined : await import('vite').then((vite) => vite.createServer({ server: {middlewareMode: {server}}, }) ); const build = () => ( viteDevServer ? viteDevServer.ssrLoadModule('virtual:remix/server-build') : import('./build/server/index.js') ); const ssr = await build(); await ssr.entry.module.websocket(server, viteDevServer); const remixHandler = createRequestHandler({ build: () => ssr, }); // configure middleware app.use(compression()); // http://expressjs.com/en/advanced/best-practice-security.html#at-a-minimum-disable-x-powered-by-header app.disable('x-powered-by'); // handle asset requests if (viteDevServer) { app.use(viteDevServer.middlewares); } else { // Vite fingerprints its assets so we can cache forever. app.use( '/assets', express.static('build/client/assets', { immutable: true, maxAge: '1y' }) ); } // Everything else (like favicon.ico) is cached for an hour. You may want to be // more aggressive with this caching. app.use(express.static('build/client', { maxAge: '1h' })); app.use(morgan('tiny')); // handle SSR requests app.all('*', remixHandler); // finally let requests resolve resolve();