Skip to content
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

app-vite v2 / app-webpack v4 - boot files are broken in SSR #17658

Closed
yusufkandemir opened this issue Nov 22, 2024 · 4 comments
Closed

app-vite v2 / app-webpack v4 - boot files are broken in SSR #17658

yusufkandemir opened this issue Nov 22, 2024 · 4 comments
Assignees
Labels

Comments

@yusufkandemir
Copy link
Member

yusufkandemir commented Nov 22, 2024

Adding any boot file, even if totally empty, results in the SSR app silently exiting the app with exit code 13. Node 22 also prints a warning. The exit code 13 stands for unsettled top-level await. This is happening due to: nodejs/node#55468

This most likely started happening after moving quasar/wrappers to #q-app/wrappers. A compiled boot file contains import { d as defineBoot } from "../server-entry.js";. So, it produces a cyclic dependency, which matches the description in the Node bug linked above.

Old description

Title: Gracefully handle boot file errors in SSR

server-entry uses a top-level await Promise.all(...) call. So, if there is a failing boot file, the app silently exits with code 13. Even if you use node --trace-warnings index.js, you don't get much useful info because the file consists of a single line for minification reasons.

client-entry template uses Promise.allSettled to load the boot files, then prints an error in case of an error. So, we should adjust the server-entry template to do the same.

This can be put in to the app-vite v2 / app-webpack v4, then also be ported back to app-vite v1 / app-webpack v3.

@LydiaSFCompetitionline
Copy link

I am working the whole week on this problem now.
The problem with the top level await in /dist/ssr/server/server-entry.mjs came up with the changes made in @quasar/app-vite-v2.0.0-beta.12
bootFiles was changed into bootFunctions and an await was moved from serverEntry to top level.

by running npx quasar build -m ssr --debug and open /dist/ssr/server/server-entry.mjs you can compare it:
unminified server-entry.mjs before updating to @quasar/app-vite-v2.0.0-beta.12:

const bootFiles =   Promise.all([ //no top level await
  [...] //not showing all imports
  Promise.resolve().then(() => axios$1),
  import("./assets/polyfill-BwV_9ARc.mjs"),
  import("./assets/sentry-BDCNs69F.mjs")
]).then((bootFiles2) => bootFiles2.map((entry) => entry.default).filter((entry) => typeof entry === "function"));
const serverEntry = (ssrContext) => {
  return new Promise(async (resolve, reject) => {
    const bootFunctions = await bootFiles; // here is the await

and since @quasar/app-vite-v2.0.0-beta.12:

const bootFunctions = await Promise.all([ // await is now top level
  [...] //not showing all imports
  Promise.resolve().then(() => axios$1),
  import("./assets/polyfill-BwV_9ARc.mjs"),
  import("./assets/sentry-BDCNs69F.mjs")
]).then((bootFiles) => bootFiles.map((entry) => entry.default).filter((entry) => typeof entry === "function"));
const serverEntry = (ssrContext) => {
  return new Promise(async (resolve, reject) => {
    // directly use awaited bootFunctions from above here

You can quickly test if your quasar project is running the build with this command: node index.js; echo $?
Then node code 13 will come up which means "Unsettled Top-Level Await: await was used outside of a function in the top-level code, but the passed Promise never settled." (see here)

Reproduction steps with new blank project

So i wondered if my project maybe have some custom issues. But no, i have node 18+ and set es2022 in quasar.conf.js as browser target, both support top level awaits. I tested if a new quasar project, created by quasar cli, will have node code 13 too.
Important Creation Steps:
yarn create quasar

  • App with Quasar CLI
  • Pick Quasar version: Quasar v2
  • Pick Quasar App CLI variant: Quasar App CLI with Vite 6 ([...] v2)
  • Check the features needed for your project:
    • axios (important, because the fresh new project needs to create the bootFunctions in /dist/ssr/server/server-entry.mjs to import axios by using this top level await)

cd quasar-project/
npx quasar build -m ssr --debug
cd dist/ssr/
node index.js; echo $?
By doing this you will get node code 13.

Try Reverting commit "tweak SSR boot files management" from beta.12

I also tried it the other way around in my real project. I changed back the changes made in @quasar/app-vite-v2.0.0-beta.12 for /dist/ssr/server/server-entry.mjs by doing this:

const bootFunctionsFix = Promise.all([ // renamed bootFunctions, no more top level await
  [...] //not showing all imports
  Promise.resolve().then(() => axios$1),
  import("./assets/polyfill-BwV_9ARc.mjs"),
  import("./assets/sentry-BDCNs69F.mjs")
]).then((bootFiles) => bootFiles.map((entry) => entry.default).filter((entry) => typeof entry === "function"));
const serverEntry = (ssrContext) => {
  return new Promise(async (resolve, reject) => {
    const bootFunctions = await bootFunctionsFix; // define bootFunction here again with await

I put the await back into serverEntry, away from top level and node index.js; echo $? will start the server listening at port 3000.

@yusufkandemir yusufkandemir changed the title Gracefully handle boot file errors in SSR app-vite v2 / app-webpack v4 - boot files are broken in SSR Nov 22, 2024
@yusufkandemir
Copy link
Member Author

@LydiaSFCompetitionline I've updated the issue description with my recent findings if you want to check it. Top-level await on itself is not the issue, but some other changes resulted in a cyclic-dependency between the server-entry and boot files. That shouldn't also cause problems, but there is a NodeJS bug about this, which is linked in the PR description. Thanks for sharing your findings, they could serve as a solution.

@rstoenescu
Copy link
Member

  1. My fix is temporary. I still want to improve things but this will require a more extensive change, though there will be no breaking changes towards the devs.
  2. q/app-webpack v4 does not suffer from the same thing, because it's CJS so top level awaits are not possible :) So no change required. Although, I'll do a small tweak to it too.

Fix will be available in q/app-vite v2.0.0

@rstoenescu
Copy link
Member

Thanks, both of you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants