I’m using Starlette for a pet project because it’s a modern Python framework that has GraphQL support. I had trouble integrating it with a Single Page App, but I found an easy fix.
My client-side app gets built in the build/
directory, so just adding StaticFiles
gets you off the ground:
route = [
...,
Mount("", app=StaticFiles(directory="build", html=True)),
]
The History API makes it look like your URL is changing, but if you ever reload, you’ll get a 404. How can we get all URLs to route to the root index.html
?
class SpaStaticFiles(StaticFiles):
"""
Staticfiles for single-page-apps
Wraps the base `lookup_path` to fallback to the root `index.html` so
the JavaScript router takes over.
https://github.com/encode/starlette/blob/d6d0f83d3fae766cee79aa444986e83c267a3a05/starlette/staticfiles.py#L145
"""
async def lookup_path(self, path):
full_path, stat_result = await super().lookup_path(path)
if stat_result is None:
return await super().lookup_path("./index.html")
return full_path, stat_result
Now you just have to change the route to use our version of StaticFiles
:
route = [
...,
Mount("", app=SpaStaticFiles(directory="build", html=True)),
]
Appendix
Starlette’s static files docs: https://www.starlette.io/staticfiles/