Skip to content

Fix top-level await in server.js causes error in Phusion Passenger #482

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 94 additions & 91 deletions frontend/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,117 +13,120 @@ import * as nodeUrl from "node:url";

installGlobals();

const base = process.env.BASE || "/";
const port = process.argv.includes("--port")
? process.argv[process.argv.indexOf("--port") + 1]
: process.env.NODE_PORT || 5678;
const isProduction = process.env.NODE_ENV === "production";
async function main() {
const base = process.env.BASE || "/";
const port = process.argv.includes("--port")
? process.argv[process.argv.indexOf("--port") + 1]
: process.env.NODE_PORT || 5678;
const isProduction = process.env.NODE_ENV === "production";

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const __dirname = path.dirname(fileURLToPath(import.meta.url));

const templateHtml = isProduction
? await fs.readFile("./dist/client/index.html", "utf-8")
: "";
const templateHtml = isProduction
? await fs.readFile("./dist/client/index.html", "utf-8")
: "";

const ssrManifest = isProduction
? await fs.readFile("./dist/client/.vite/ssr-manifest.json", "utf-8")
: undefined;
const ssrManifest = isProduction
? await fs.readFile("./dist/client/.vite/ssr-manifest.json", "utf-8")
: undefined;

const app = express();
app.use(cookieParser());
const app = express();
app.use(cookieParser());

app.use('/.well-known', express.static(path.join(__dirname, 'public/.well-known')));
app.use('/.well-known', express.static(path.join(__dirname, 'public/.well-known')));

let vite;
let vite;

if (!isProduction) {
vite = await viteServer({
server: {middlewareMode: true},
appType: "custom",
base,
});

app.use(vite.middlewares);
} else {
app.use(compression());
app.use(base, sirv(path.join(__dirname, "./dist/client"), {extensions: []}));
}
if (!isProduction) {
vite = await viteServer({
server: { middlewareMode: true },
appType: "custom",
base,
});

const getViteEnvironmentVariables = () => {
const envVars = {};
for (const key in process.env) {
if (key.startsWith('VITE_')) {
envVars[key] = process.env[key];
}
app.use(vite.middlewares);
} else {
app.use(compression());
app.use(base, sirv(path.join(__dirname, "./dist/client"), { extensions: [] }));
}
return JSON.stringify(envVars);
};

app.use("*", async (req, res) => {
const url = req.originalUrl.replace(base, "");

try {
let template;
let render;

if (!isProduction) {
template = await fs.readFile(path.join(__dirname, "./index.html"), "utf-8");
template = await vite.transformIndexHtml(url, template);
render = (await vite.ssrLoadModule("/src/entry.server.tsx")).render;
} else {
template = templateHtml;
render = (await dynamicImport(path.join(__dirname, "./dist/server/entry.server.js"))).render;

const getViteEnvironmentVariables = () => {
const envVars = {};
for (const key in process.env) {
if (key.startsWith('VITE_')) {
envVars[key] = process.env[key];
}
}
return JSON.stringify(envVars);
};

const {appHtml, dehydratedState, helmetContext} = await render(
{req, res},
ssrManifest
);
const stringifiedState = JSON.stringify(dehydratedState);
app.use("*", async (req, res) => {
const url = req.originalUrl.replace(base, "");

try {
let template;
let render;

if (!isProduction) {
template = await fs.readFile(path.join(__dirname, "./index.html"), "utf-8");
template = await vite.transformIndexHtml(url, template);
render = (await vite.ssrLoadModule("/src/entry.server.tsx")).render;
} else {
template = templateHtml;
render = (await dynamicImport(path.join(__dirname, "./dist/server/entry.server.js"))).render;
}

const helmetHtml = Object.values(helmetContext.helmet || {})
.map((value) => value.toString() || "")
.join(" ");
const { appHtml, dehydratedState, helmetContext } = await render(
{ req, res },
ssrManifest
);
const stringifiedState = JSON.stringify(dehydratedState);

const envVariablesHtml = `<script>window.hievents = ${getViteEnvironmentVariables()};</script>`;
const helmetHtml = Object.values(helmetContext.helmet || {})
.map((value) => value.toString() || "")
.join(" ");

const headSnippets = [];
if (process.env.VITE_FATHOM_SITE_ID) {
headSnippets.push(`
const envVariablesHtml = `<script>window.hievents = ${getViteEnvironmentVariables()};</script>`;

const headSnippets = [];
if (process.env.VITE_FATHOM_SITE_ID) {
headSnippets.push(`
<script src="https://cdn.usefathom.com/script.js" data-spa="auto" data-site="${process.env.VITE_FATHOM_SITE_ID}" defer></script>
`);
}
}

const html = template
.replace("<!--head-snippets-->", headSnippets.join("\n"))
.replace("<!--app-html-->", appHtml)
.replace("<!--dehydrated-state-->", `<script>window.__REHYDRATED_STATE__ = ${stringifiedState}</script>`)
.replace("<!--environment-variables-->", envVariablesHtml)
.replace(/<!--render-helmet-->.*?<!--\/render-helmet-->/s, helmetHtml);

res.setHeader("Content-Type", "text/html");
return res.status(200).end(html);
} catch (error) {
if (error instanceof Response) {
if (error.status >= 300 && error.status < 400) {
return res.redirect(error.status, error.headers.get("Location") || "/");
} else {
return res.status(error.status).send(await error.text());
const html = template
.replace("<!--head-snippets-->", headSnippets.join("\n"))
.replace("<!--app-html-->", appHtml)
.replace("<!--dehydrated-state-->", `<script>window.__REHYDRATED_STATE__ = ${stringifiedState}</script>`)
.replace("<!--environment-variables-->", envVariablesHtml)
.replace(/<!--render-helmet-->.*?<!--\/render-helmet-->/s, helmetHtml);

res.setHeader("Content-Type", "text/html");
return res.status(200).end(html);
} catch (error) {
if (error instanceof Response) {
if (error.status >= 300 && error.status < 400) {
return res.redirect(error.status, error.headers.get("Location") || "/");
} else {
return res.status(error.status).send(await error.text());
}
}
}

console.error(error);
res.status(500).send("Internal Server Error");
}
});
console.error(error);
res.status(500).send("Internal Server Error");
}
});

app.listen(port, () => {
console.info(`SSR Serving at http://localhost:${port}`);
});
app.listen(port, () => {
console.info(`SSR Serving at http://localhost:${port}`);
});

const dynamicImport = async (path) => {
return import(
nodePath.isAbsolute(path) ? nodeUrl.pathToFileURL(path).toString() : path
);
const dynamicImport = async (path) => {
return import(
nodePath.isAbsolute(path) ? nodeUrl.pathToFileURL(path).toString() : path
);

}
}
main();