130 lines
3.6 KiB
JavaScript
130 lines
3.6 KiB
JavaScript
import {createRequestHandler} from '@remix-run/express';
|
|
import express from 'express';
|
|
import morgan from 'morgan';
|
|
import sylvite from 'sylvite';
|
|
|
|
import environment from './environment.server.js';
|
|
|
|
const cacheDirectory = `${import.meta.dirname}/node_modules/.cache`;
|
|
const {hooks} = await sylvite({
|
|
entry: 'node',
|
|
...await import('./sylvite.config.js'),
|
|
});
|
|
|
|
const {
|
|
httpsCert,
|
|
httpsKey,
|
|
isInsecure,
|
|
isProduction,
|
|
port,
|
|
useMkcert,
|
|
} = environment();
|
|
|
|
const app = express();
|
|
hooks.call('@/sylvite/cha0s-remix:initializeExpress', app);
|
|
|
|
const httpServerOptions = hooks.call('@/sylvite/cha0s-remix:httpServerOptions', {});
|
|
|
|
let server;
|
|
if (isInsecure) {
|
|
// http://
|
|
const {createServer} = await import('node:http');
|
|
server = createServer(httpServerOptions, app);
|
|
}
|
|
else {
|
|
const {readFile} = await import('node:fs/promises');
|
|
// generate certificates
|
|
if (useMkcert) {
|
|
const {execSync} = await import('node:child_process');
|
|
const {mkdirSync, statSync} = await import('node:fs');
|
|
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`)
|
|
}
|
|
}
|
|
// https://
|
|
const [cert, key] = await Promise.all([readFile(httpsCert), readFile(httpsKey)]);
|
|
const serverOptions = {
|
|
cert,
|
|
key,
|
|
...httpServerOptions,
|
|
};
|
|
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();
|
|
});
|
|
server.listen(port, () => {
|
|
console.log(`Express server listening at http${isInsecure ? '' : 's'}://localhost:${port}`);
|
|
});
|
|
|
|
const requestHandlerOptions = {
|
|
getLoadContext: (req) => {
|
|
return hooks.call('@/sylvite/cha0s-remix:getRemixLoadContext', {}, req);
|
|
},
|
|
};
|
|
|
|
if (isProduction) {
|
|
// remix handler
|
|
requestHandlerOptions.build = () => import('./build/server/index.js');
|
|
// websocket handler
|
|
const {entry: {module: {handleUpgrade}}} = await requestHandlerOptions.build();
|
|
server.on('upgrade', handleUpgrade);
|
|
// serve assets
|
|
app.use('/assets', express.static('build/client/assets', {
|
|
// vite fingerprints its assets so we can cache forever.
|
|
immutable: true,
|
|
maxAge: '1y',
|
|
}));
|
|
app.use(express.static('build/client', {
|
|
// everything else (like favicon.ico) is cached for an hour.
|
|
maxAge: '1h',
|
|
}));
|
|
}
|
|
else {
|
|
const viteDevServer = await import('vite').then((vite) => (
|
|
vite.createServer({
|
|
server: {
|
|
middlewareMode: true,
|
|
},
|
|
})
|
|
));
|
|
// remix handler
|
|
requestHandlerOptions.build = () => viteDevServer.ssrLoadModule('virtual:remix/server-build');
|
|
const {createViteRuntime} = await import('vite');
|
|
// websocket handler
|
|
const runtime = await createViteRuntime(viteDevServer);
|
|
const {handleUpgrade} = await runtime.executeEntrypoint('/app/websocket.js');
|
|
server.on('upgrade', handleUpgrade);
|
|
// serve assets
|
|
app.use(viteDevServer.middlewares);
|
|
app.get('/storybook', async (req, res) => {
|
|
const url = new URL(req.url, `http${isInsecure ? '' : 's'}://${req.headers.host}`);
|
|
url.pathname = '/';
|
|
url.port = 11337;
|
|
res.redirect(url.href);
|
|
});
|
|
}
|
|
|
|
hooks.call('@/sylvite/cha0s-remix:additionalAssets', app);
|
|
|
|
app.use(morgan('tiny'));
|
|
|
|
hooks.call('@/sylvite/cha0s-remix:beforeExpressCatchAll', app);
|
|
|
|
// handle SSR requests
|
|
app.all('*', createRequestHandler(requestHandlerOptions));
|
|
|
|
// finalize; let requests resolve
|
|
resolve();
|