How to create a SPA using SvelteKit with no Node or Server Side Routing

I have a backend REST API written in Python, and I want to make a simple front end in Svelte. The front end should be a Single Page Application and not have to rely on a Node.js server, or any kind of server side routing. I want to serve this over Nginx and rely on client side routing. The front end is "dynamic" in the sense that it needs pages with unknown parameters, for example:

/blog/1
/blog/2

However, it is not quite intuitive as to whether you need to prerender and which build adapter to use. Without the correct settings, the build will most likely fail. Even if you get the build to run successfully, it is hard to test it on your local host.

Add a fallback page to Adapter Static

The key to making this work is to add a fallback page in svelte.config.js; without this you won't be able to build successfully:

import adapter from '@sveltejs/adapter-static';

const config = {
kit: {
    adapter: adapter({
      fallback: 'index.html'
    })
  }
};

Disable Prerendering

Next you need to disable server side routing and prerendering, as well as enable client side routing. In your src/routes/layout.js, add the following:

export const ssr = false;
export const csr = true;
export const prerender = false;

You can actually prerender certain content. But any page with [parameters] must not be prerendered.

Build your SPA

Now you can run npm run build.

In your build directory, you should now see an index.html file:

matthew_moisen_svelte_build_index.jpg

Test the Build

To test it, you would ideally set up an Nginx on docker. However to quickly test it you can use Python's simple server.

On the command line navigate to the build directory and run:

python -m http.server

Now in your browser, go to http://localhost:8000/. Python's web server will default this / to your index.html.

However, if you try to directly load another route, like http://localhost:8000/foo, you will see a 404. To rectify this, run the following Python code from within the build file and try again:

import os
from http.server import SimpleHTTPRequestHandler, HTTPServer


class FallbackHTTPRequestHandler(SimpleHTTPRequestHandler):
    def send_error(self, code, message=None, explain=None):
        if code == 404:
            self.path = "/index.html"
            super().do_GET()
        else:
            super().send_error(code, message, explain)


httpd = HTTPServer(("localhost", 8000), FallbackHTTPRequestHandler)

httpd.serve_forever()

What this will do is always serve the /index.html file as a fallback.


Errors when not using fallback

Without the fallback option in svelte.config.js, you can see errors when you run npm run build such as:

> Using @sveltejs/adapter-static
  @sveltejs/adapter-static: all routes must be fully prerenderable, but found the following routes that are dynamic:
    - src\routes/
    - src\routes/bar
    - src\routes/bar/[lol]
    - src\routes/foo

This error is because adapter-static will require all routes to be prerenderable, unless you add a fallback.

Another error you may see if you mark your routes as prerenderable:

Error: The following routes were marked as prerenderable, but were not prerendered because they were not found while crawling your app:
  - /bar/[lol]

In this case, you have a dynamic route, so prerendering won't work.

The solution for SPAs is to use a fallback in svelte.config.js.


Comments

Add Comment

Name

Email

Comment

Are you human? - one = 8