lagonapp / lagon

Deploy Serverless Functions at the Edge. Current status: Alpha
https://lagon.app
GNU Affero General Public License v3.0
1.32k stars 62 forks source link

Serve index.html #232

Closed cyco130 closed 1 year ago

cyco130 commented 1 year ago

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.

QuiiBz commented 1 year ago

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:

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 commented 1 year ago

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):

QuiiBz commented 1 year ago

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 commented 1 year ago

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

QuiiBz commented 1 year ago

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

cyco130 commented 1 year ago

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