{"id":854,"date":"2020-06-01T04:56:49","date_gmt":"2020-06-01T04:56:49","guid":{"rendered":"https:\/\/www.crccheck.com\/blog\/?p=854"},"modified":"2020-06-01T05:02:48","modified_gmt":"2020-06-01T05:02:48","slug":"serving-spas-from-starlette","status":"publish","type":"post","link":"https:\/\/www.crccheck.com\/blog\/serving-spas-from-starlette\/","title":{"rendered":"Serving SPAs from Starlette"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">I&#8217;m using <a href=\"https:\/\/github.com\/encode\/starlette\">Starlette<\/a> for a pet project because it&#8217;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.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">My client-side app gets built in the <code>build\/<\/code> directory, so just adding <code>StaticFiles<\/code> gets you off the ground:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>route = &#91;\n    ...,\n    Mount(\"\", app=StaticFiles(directory=\"build\", html=True)),\n]<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The History API makes it look like your URL is changing, but if you ever reload, you&#8217;ll get a 404. How can we get all URLs to route to the root <code>index.html<\/code>?<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>class SpaStaticFiles(StaticFiles):\n    \"\"\"\n    Staticfiles for single-page-apps\n\n    Wraps the base `lookup_path` to fallback to the root `index.html` so\n    the JavaScript router takes over.\n    https:&#47;&#47;github.com\/encode\/starlette\/blob\/d6d0f83d3fae766cee79aa444986e83c267a3a05\/starlette\/staticfiles.py#L145\n    \"\"\"\n\n    async def lookup_path(self, path):\n        full_path, stat_result = await super().lookup_path(path)\n        if stat_result is None:\n            return await super().lookup_path(\".\/index.html\")\n\n        return full_path, stat_result\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now you just have to change the route to use our version of <code>StaticFiles<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>route = &#91;\n    ...,\n    Mount(\"\", app=SpaStaticFiles(directory=\"build\", html=True)),\n]<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Appendix<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Starlette&#8217;s static files docs: <a href=\"https:\/\/www.starlette.io\/staticfiles\/\">https:\/\/www.starlette.io\/staticfiles\/<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;m using Starlette for a pet project because it&#8217;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: The History API makes&hellip;<\/p>\n <a href=\"https:\/\/www.crccheck.com\/blog\/serving-spas-from-starlette\/\" title=\"Serving SPAs from Starlette\" class=\"entry-more-link\"><span>Read More<\/span> <span class=\"screen-reader-text\">Serving SPAs from Starlette<\/span><\/a>","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"Layout":"","footnotes":""},"categories":[4],"tags":[48],"class_list":["entry","author-showmewhatyougot","post-854","post","type-post","status-publish","format-standard","category-technical","tag-python"],"_links":{"self":[{"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/posts\/854","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/comments?post=854"}],"version-history":[{"count":3,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/posts\/854\/revisions"}],"predecessor-version":[{"id":859,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/posts\/854\/revisions\/859"}],"wp:attachment":[{"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/media?parent=854"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/categories?post=854"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/tags?post=854"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}