Skip to content

Instantly share code, notes, and snippets.

@vrslev
Last active March 11, 2024 09:23
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save vrslev/6d0602bfa939a01844f645c608afb85a to your computer and use it in GitHub Desktop.
Save vrslev/6d0602bfa939a01844f645c608afb85a to your computer and use it in GitHub Desktop.
Automatic browser reloading in FastAPI
import os
import arel
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
app = FastAPI()
templates = Jinja2Templates("templates")
if _debug := os.getenv("DEBUG"):
hot_reload = arel.HotReload(paths=[arel.Path(".")])
app.add_websocket_route("/hot-reload", route=hot_reload, name="hot-reload")
app.add_event_handler("startup", hot_reload.startup)
app.add_event_handler("shutdown", hot_reload.shutdown)
templates.env.globals["DEBUG"] = _debug
templates.env.globals["hot_reload"] = hot_reload
@app.get("/")
def index(request: Request):
return templates.TemplateResponse("index.html", context={"request": request})
# run:
# DEBUG=true uvicorn main:app --reload
fastapi
uvicorn[standard]
arel
jinja2
<body>
{% block content %}{% endblock %}
<!-- Hot reload script -->
{% if DEBUG %} {{ hot_reload.script(url_for('hot-reload')) | safe }} {% endif
%}
</body>
{% extends "base.html" %} {% block content %} Hello, world! {% endblock %}
@j4hangir
Copy link

j4hangir commented Jul 9, 2022

Pretty neat 👍

@philmade
Copy link

Great! This kind of tool should be included as standard in frameworks like FastAPI and Jinja. Wonderful!

@vrslev
Copy link
Author

vrslev commented Nov 19, 2022

Great! This kind of tool should be included as standard in frameworks like FastAPI and Jinja. Wonderful!

@philmade Definitely! I like the vibe of frontend frameworks and tooling: they have such things by default, and it is amazing.

@jacksongoode
Copy link

Huh, this didn't work in my instance, were there other steps you took to get this working? How did you load the FastAPI server, uvicorn?

@philmade
Copy link

philmade commented Nov 30, 2022 via email

@vrslev
Copy link
Author

vrslev commented Nov 30, 2022

@philmade I added a comment with running instruction, thanks!

@dicolasi
Copy link

dicolasi commented Sep 1, 2023

I can see a WS connection open from the logs:

Done in 79ms.
INFO:     Application startup complete.
INFO:     127.0.0.1:53242 - "GET / HTTP/1.1" 200 OK
INFO:     ('127.0.0.1', 53244) - "WebSocket /hot-reload" [accepted]
INFO:     connection open

and I can see the script in html:

<html lang="en">
<head>
    <link rel="stylesheet" href="http://127.0.0.1:8000/static/css/main.css" type="text/css" />
    <meta name="description" content="Home page description FUCKER!" />
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width" />
    <title>Home</title>
</head>
<body>
     
    <section id="body" class="flex flex-col bg-slate-50 justify-center items-center max-w-screen-lg m-auto">
        <div class="flex flex-col justify-center items-center py-10">
            <h2 class="text-2xl leading-relaxed text-slate-800 uppercase">Welcomsdsdsdsddsdsdsdsdsdsdsdsa</h2>
            <div class="flex flex-col justify-center content-center text-center">
                <img src="https://i.discogs.com/mXy5VCH7vfETEiVVrn4Slw_wKARXL7zYBcvEzQWwb7k/rs:fit/g:sm/q:90/h:544/w:600/czM6Ly9kaXNjb2dz/LWRhdGFiYXNlLWlt/YWdlcy9BLTUyMzEy/My0xNTcwMTc4NjE4/LTE2MTQuanBlZw.jpeg"/>
                <span class="py-4 uppercase font-bold">Beirut</span>
            </div>
        </div>
    </section>

      <script>const ws = new WebSocket("ws://127.0.0.1:8000/hot-reload");
ws.onmessage = () => window.location.reload();
</script> 
</body>
</html>

however the page does not get reloaded on save. Am I missing something?

@thisisthemurph
Copy link

This works for me, but only on the routes defined within the main file where app is defined. Any ideas on how to get this to work on other routes? I have separate routes defined within a routers directory and then apply them in the main file with app.include_router(my_router).

@vrslev
Copy link
Author

vrslev commented Oct 24, 2023

@dicolasi Please share your code 😊

@vrslev
Copy link
Author

vrslev commented Oct 24, 2023

@thisisthemurph I don't understand exactly your setup. Can you share a minimal reproducible example of what you're saying?

@yanky2000
Copy link

It works in Safari (Version 17.2 (19617.1.17.11.9)) just fine.

@vrslev
Copy link
Author

vrslev commented Dec 20, 2023

It works in Safari (Version 17.2 (19617.1.17.11.9)) just fine.

@yanky2000 Just tested it in Safari 17.1—it also works. Removed the comment, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment