sveltejs / kit

web development, streamlined
https://kit.svelte.dev
MIT License
18.56k stars 1.91k forks source link

When using `adapter-static` for prerender, an error occurs if `+layout.server.ts` file exists. #10152

Closed yahao87 closed 1 year ago

yahao87 commented 1 year ago

Describe the bug

When using adapter-static for prerender, an error occurs if +layout.server.ts file exists. This error occurs when certain pages exist only conditionally. By the way, +layout.server.ts file is needed to crawl in ssr when prerender is executed with i18n applied. Can this problem be resolved?

Reproduction

  1. checkout https://github.com/yahao87/svelte-ssg-build-fail-example
  2. npm i
  3. npm run docker-build
  4. npm run docker-preview
  5. view http://localhost:8080/ -----> 200 ok
  6. view http://localhost:8080/condition-page ----> error
  7. view http://localhost:8080/en/condition-page ----> error
  8. view http://localhost:8080/en/afdasdfasdfas ----> 404

Logs

No response

System Info

System:
    OS: macOS 12.3
    CPU: (8) arm64 Apple M1 Pro
    Memory: 71.39 MB / 32.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 16.19.0 - ~/.nvm/versions/node/v16.19.0/bin/node
    npm: 8.19.3 - ~/.nvm/versions/node/v16.19.0/bin/npm
  Browsers:
    Chrome: 114.0.5735.106
    Safari: 15.4
  npmPackages:
    @sveltejs/adapter-auto: ^2.0.0 => 2.1.0 
    @sveltejs/adapter-static: ^2.0.2 => 2.0.2 
    @sveltejs/kit: ^1.5.0 => 1.20.0 
    svelte: ^3.54.0 => 3.59.1 
    vite: ^4.3.0 => 4.3.9

Severity

serious, but I can work around it

Additional Information

A condition-page page is basically a page that appears conditionally. So it is correct that the prerendered page is not created. So it seems that it shouldn't call the __data.json file.

CleanShot 2023-06-13 at 19 47 41@2x CleanShot 2023-06-13 at 19 48 37@2x
SasaHrgovic commented 1 year ago

adapter-static is not meant to be used with SSR. It best works with sites that can be fully pre-rendered, or with SPAs which of course only have client side code and no SSR. Someone please correct me if I'm missing anything.

Since you already use docker, I think the best solution for your case is to use the adapter-node instead. https://kit.svelte.dev/docs/adapter-node

I use it and it works great, although I don't need to pre-render any pages in my case. But I think it should still work fine with pre-rendering.

yahao87 commented 1 year ago

I think @SasaHrgovic is misunderstanding about prerender.

The uses of prerender and SSR are clearly different. SSR runs on nodejs. However, prerender is a different form of SPA that only wants to be provided as an html static file. (For example, to expose fixed information for search engine bots only on some pages) Therefore, the service can be provided only through static files.

In addition, sveltekit is not irrelevant to SSR because it runs SSR in the process of creating a prerender file and proceeds with crawling.

In addition, even services for which a prerender is suitable may require a hidden page that must operate as a fallback, such as an SPA. For example, you don't want pages that require sessions to be exposed to search engine bots.

SasaHrgovic commented 1 year ago

I still think you're trying to do something that's not meant to be done the way you want to do it. Ie. you need to use adapter-node instead of adapter-static if you want to have anything that should run server-side, like the +layout.server.ts file. You can try having the same file client side but name it +layout.ts instead, and see if that solves your problem...otherwise just use adapter-node.

elliott-with-the-longest-name-on-github commented 1 year ago

@SasaHrgovic is correct -- you're trying to do something that's just not supported. condition-page turns SSR and prerendering off, meaning it has to be rendered on the client at runtime. Because you're rendering it inside of a +layout.server.ts, it has to try to request that from the server while rendering, which it obviously can't do, because there's no server. You need to render it outside of the +layout.server.ts's tree or use a platform that allows server requests.