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

Serve index.html #232

Closed
cyco130 opened this issue Nov 3, 2022 · 6 comments · Fixed by #252
Closed

Serve index.html #232

cyco130 opened this issue Nov 3, 2022 · 6 comments · Fixed by #252
Labels

Comments

@cyco130
Copy link
Contributor

cyco130 commented Nov 3, 2022

Many frameworks (like Rakkas or Next.js) serve prerendered HTML files without an extension. For example the URL path /foo can refer to /foo.html or /foo/index.html but Lagon CLI serves static assets only when the URL path is an exact match which breaks static prerendering in Rakkas, and likely will have the same effect on other frameworks.

I implemented a simple environment variable based solution in dev.rs like this:

    let serve_html = environment_variables
        .get("SERVE_HTML")
        .unwrap_or(&"".to_string())
        == "1";
    let serve_index_html = environment_variables
        .get("SERVE_INDEX_HTML")
        .unwrap_or(&"".to_string())
        == "1";

    if let Some(asset) = assets.iter().find(|asset| {
        *asset.0 == url
            || serve_html && *asset.0 == format!("{}.html", url)
            || serve_index_html && *asset.0 == format!("{}/index.html", url)
    }) {

and it works for the dev CLI command.

But I don't know the details of the actual deployment environments so I don't know what to do to make it work there. In any case, I feel like this should be a bundler option, not an environment variable, because it's a property of the bundled assets, not of the environment.

Alternatively, I could duplicate the assets in the bundling phase but that seems wasteful.

Yet another alternative could be to let JS handler worry about it and call something like Lagon.serverAsset(filename) when it deems appropriate.

So I don't know what the exact solution should be but I can volunteer for implementing it if within my abilities.

@cyco130 cyco130 added the feature label Nov 3, 2022
@QuiiBz
Copy link
Member

QuiiBz commented Nov 3, 2022

Good questions. Some thoughts:

Lagon CLI serves static assets only when the URL path is an exact match

It's almost the same system for the serverless app (packages/serverless), so this issue affects both the CLI and serverless.

I feel like this should be a bundler option, not an environment variable

Not a fan of both solutions. Can we assume an URL only resolves to the following?

  1. A file if the URL matches an asset
  2. A file if the URL doesn't contain any extension and matches an asset where the extension is .html
  3. The handler function

Yet another alternative could be to let JS handler worry about it and call something like Lagon.serverAsset(filename) when it deems appropriate.

The goals with serving assets based on their path and name were the following:

  • You (as a developer) don't have to write the logic to handle assets
  • It's faster to access since we don't have to run your code to resolve assets

Looking at CF Workers and Deno Deploy, they both have a way to read assets (via KV or an FS API). This approach would add more overhead to the serverless app and latency for requests fetching assets, which I'm not a big fan of.

@cyco130
Copy link
Contributor Author

cyco130 commented Nov 6, 2022

A file if the URL doesn't contain any extension and matches an asset where the extension is .html

This doesn't resolve index.html though, which will make porting Rakkas, SvelteKit, and Next.js a lot harder.

Here's how it's handled on some deployment systems and static servers (for inspiration):

  • Netlify has configurations via a _redirect file or netlify.toml. Edge functions run before the static file server. It serves {name}.html and {name}/index.html by default.
  • Vercel has detailed configuration options. It serves {name}.html and {name}/index.html by default.
  • Deno Deploy is JS-controlled.
  • Cloudflare Workers is JS-controlled.
  • server-static has the index option.
  • sirv (used by Rakkas and SvelteKit) has the extensions option and always looks for {name}/index.{ext} in addition to {name}.{ext}.
  • PHP's builtin server looks for index.php and index.html.

@QuiiBz
Copy link
Member

QuiiBz commented Nov 12, 2022

This doesn't resolve index.html though, which will make porting Rakkas, SvelteKit, and Next.js a lot harder.

True, but I believe it should work if we also add a new check for index.html. The above checks would become:

  1. A file if the URL matches an asset
  2. A file if the URL doesn't contain any extension and matches an asset where the extension is .html
  3. A file if the URL doesn't contain any extension and matches a folder with an index.html file inside
  4. The handler function

These checks match the default behavior of Netlify/Vercel/PHP...

@cyco130
Copy link
Contributor Author

cyco130 commented Nov 13, 2022

⛵️ This latest proposal would make Rakkas's prerendering work. To the best of my knowledge, ditto for Next.js and SvelteKit.

@QuiiBz
Copy link
Member

QuiiBz commented Nov 13, 2022

Released in @lagon/cli@0.3.6 if you want to test!

@cyco130
Copy link
Contributor Author

cyco130 commented Nov 13, 2022

It works! Only two small problems remaining in Rakkas CI (I will report/fix soon) :)

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

Successfully merging a pull request may close this issue.

2 participants