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

adapter-static doesn't work with dynamic routes #4278

Closed
pjebs opened this issue Mar 9, 2022 · 14 comments
Closed

adapter-static doesn't work with dynamic routes #4278

pjebs opened this issue Mar 9, 2022 · 14 comments

Comments

@pjebs
Copy link

pjebs commented Mar 9, 2022

Describe the bug

SvelteKit built using adapter-static with dynamic routes simply does not work on S3 (static hosting) and github pages.

When you start your site's journey from / and then navigate using links to a dynamic route (i.e. /s/x/y), it works.

However if you directly try and go to /s/x/y (or alternatively refresh the page), you get a 404 page.

Is there any way to make the site work on s3 or github pages?
Or is dynamic routing with static-adapter not feasible?
Perhaps an option to make sveltekit use #-based routing.

Reproduction

Create any site with dynamic routes and run it on s3.

Logs

No response

System Info

s3

Severity

blocking all usage of SvelteKit

Additional Information

No response

@PH4NTOMiki
Copy link
Contributor

PH4NTOMiki commented Mar 9, 2022

As for the Github Pages, natively they don't support SPAs, but there is hacky workaround https://github.com/rafgraph/spa-github-pages
essentially you create 404.html file inside static folder with this content:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Single Page Apps for GitHub Pages</title>
    <script type="text/javascript">
      // Single Page Apps for GitHub Pages
      // MIT License
      // https://github.com/rafgraph/spa-github-pages
      // This script takes the current url and converts the path and query
      // string into just a query string, and then redirects the browser
      // to the new url with only a query string and hash fragment,
      // e.g. https://www.foo.tld/one/two?a=b&c=d#qwe, becomes
      // https://www.foo.tld/?/one/two&a=b~and~c=d#qwe
      // Note: this 404.html file must be at least 512 bytes for it to work
      // with Internet Explorer (it is currently > 512 bytes)

      // If you're creating a Project Pages site and NOT using a custom domain,
      // then set pathSegmentsToKeep to 1 (enterprise users may need to set it to > 1).
      // This way the code will only replace the route part of the path, and not
      // the real directory in which the app resides, for example:
      // https://username.github.io/repo-name/one/two?a=b&c=d#qwe becomes
      // https://username.github.io/repo-name/?/one/two&a=b~and~c=d#qwe
      // Otherwise, leave pathSegmentsToKeep as 0.
      var pathSegmentsToKeep = 0;

      var l = window.location;
      l.replace(
        l.protocol + '//' + l.hostname + (l.port ? ':' + l.port : '') +
        l.pathname.split('/').slice(0, 1 + pathSegmentsToKeep).join('/') + '/?/' +
        l.pathname.slice(1).split('/').slice(pathSegmentsToKeep).join('/').replace(/&/g, '~and~') +
        (l.search ? '&' + l.search.slice(1).replace(/&/g, '~and~') : '') +
        l.hash
      );

    </script>
  </head>
  <body>
  </body>
</html>

and in the app.html you add this before %svelte.body% (that's really important):

<script>
      (function(l) {
        if (l.search[1] === '/' ) {
          var decoded = l.search.slice(1).split('&').map(function(s) { 
            return s.replace(/~and~/g, '&')
          }).join('?');
          window.history.replaceState(null, '',
              l.pathname.slice(0, -1) + decoded + l.hash
          );
        }
      }(window.location))
</script>

or simpler option is to JUST set fallback adapter option to 404.html
It actually is better, but obviously for both of these options every request will return status code of 404 for real request which is really bad for SEO

@PH4NTOMiki
Copy link
Contributor

PH4NTOMiki commented Mar 9, 2022

Github Pages solution is a really hacky one, so if you can help it, don't use it.
And you're probably better of with Cludflare Pages, Vercel, Netlify.
And if you want to have something like S3 (and cheaper) then you can use BunnyCDN Edge Storage (read this article https://bunny.net/blog/host-your-frontend-applications-on-the-edge/ on their blog)
(I don't have any affiliation with them, I just use them)

And for all of these you DO need to use fallback option for adapter config.
Hope that helps

@pjebs
Copy link
Author

pjebs commented Mar 9, 2022

Maybe sveltekit or static-adapter should have an option that will make it use #-based routing. That will solve the problem for most people..

@PH4NTOMiki
Copy link
Contributor

Maybe sveltekit or static-adapter should have an option that will make it use #-based routing. That will solve the problem for most people..

That's really really bad for SEO, because the normal SPA Google can actually render, but if it's using hash routing it can't figure out there are any other page except index/homepage.

@pjebs
Copy link
Author

pjebs commented Mar 9, 2022

@PH4NTOMiki How does the fallback option in static-adapter help, since if you go to a dynamic route, the /index.html page is not available to display the fallback option.

@pjebs
Copy link
Author

pjebs commented Mar 9, 2022

Maybe by now, Google understands #-based routing since it's so common, that they can successfully interpret it like they do for / based routing.

@PH4NTOMiki
Copy link
Contributor

Maybe by now, Google understands #-based routing since it's so common, that they can successfully interpret it like they do for / based routing.

No they don't and they never will, because servers don't understand hash, they completely discard it.

@PH4NTOMiki How does the fallback option in static-adapter help, since if you go to a dynamic route, the /index.html page is not available to display the fallback option.

That's why you're supposed to configure it at the server that if the server can't find the exact file/route people are asking for, to just server fallback file instead.

@pjebs
Copy link
Author

pjebs commented Mar 9, 2022

yes the server can be configured to fallback, but how does static-adapter do anything about it's fallback option?

@PH4NTOMiki
Copy link
Contributor

adapter-static (not static-adapter) creates file with a file name that was set in fallback option so that you can configure a server to fall back to that file if the specific route is unavailable.

@pjebs
Copy link
Author

pjebs commented Mar 9, 2022

Aha. Thanks for explaining.

@pjebs pjebs changed the title static-adapter doesn't work with dynamic routes adapter-static doesn't work with dynamic routes Mar 9, 2022
@benmccann
Copy link
Member

You need to set trailingSlash: 'never' if you're using S3. Closing as duplicate of #3852

@pjebs
Copy link
Author

pjebs commented Mar 9, 2022

@PH4NTOMiki can you explain the significance of trailingslash = never?

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

No branches or pull requests

3 participants