116 lines
3.3 KiB
JavaScript
116 lines
3.3 KiB
JavaScript
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')
|
|
);
|
|
let remixHandler;
|
|
if (viteDevServer) {
|
|
const {createViteRuntime} = await import('vite');
|
|
const runtime = await createViteRuntime(viteDevServer);
|
|
const {handleUpgrade} = await runtime.executeEntrypoint('/app/server/websocket.js');
|
|
server.on('upgrade', handleUpgrade);
|
|
remixHandler = createRequestHandler({build});
|
|
}
|
|
else {
|
|
const ssr = await build();
|
|
server.on('upgrade', ssr.entry.module.handleUpgrade);
|
|
remixHandler = createRequestHandler({
|
|
build: async () => {
|
|
return 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' }));
|
|
}
|
|
|
|
// silphius resources
|
|
app.use(
|
|
'/resources',
|
|
express.static('resources', { maxAge: '1h' }),
|
|
);
|
|
|
|
app.use(morgan('tiny'));
|
|
|
|
// handle SSR requests
|
|
app.all('*', remixHandler);
|
|
|
|
// finally let requests resolve
|
|
resolve();
|