How to hot reload FastAPI and Flask apps on HTML, CSS, and Javascript changes
November 16, 2023 / 5 min read / 7,298 , 1 , 1
Last updated: November 19, 2023
Tags: python, fastapi, flask, html, css, javascript, uvicorn, gunicorn, jinja2, browser-sync
Getting instant feedback for code changes is essential when developing a web application. Typical workflows for Python web applications involve a hot-reload functionality for the development web server that will automatically restart the server when changes to python files are detected. However, the server will not automatically restart when changes to HTML, CSS, or JavaScript files are detected. When those files are updated, you must manually restart the server for the changes to occur. Moreover, this typical workflow will not automatically refresh your web browser when you update files, so you must manually refresh the web page to see the changes.
In this tutorial, I'll show you how to automatically hot-reload your FastAPI and Flask projects that use template engines like Jinja with web servers like uvicorn or gunicorn. After reading, you will be able to automatically restart your server and refresh your browser when Python, HTML, CSS, and other files change—no manual intervention required.
Example
You can find bare-bones example code for this tutorial in my GitHub repository named "hot-reload-examples", here. The following video shows the hot reloading in action, using that repository's fastapi
example.
Installations
You'll need to perform these installations to get hot reloading working.
For both FastAPI and Flask
- Node.js
- npm (usually included with node.js)
- browser-sync. The following command will install it globally:
npm install -g browser-sync
For FastAPI
You can install these with pip install fastapi "uvicorn[standard]" jinja2
.
For Flask
You can install these with pip install flask gunicorn
.
The steps
Here are the steps to get hot reloads working for your FastAPI or Flask project.
-
Run the server with
--reload
, specifying the files to look for when reloading.-
uvicorn main:app --reload --reload-include="*.html" --reload-include="*.css" --reload-include="*.js"
The above command will run a server on
http://localhost:8000
and watch for changes to Python files (default) and CSS, HTML, and JS files (according to the glob patterns we provided). -
gunicorn main:app --reload --reload-extra-file="templates/index.html" --reload-extra-file="static/styles.css"
The above command will run a server on
http://localhost:8000
and watch for changes to Python files (default),templates/index.html
, andstatic/styles.css
. Annoyingly,gunicorn
currently does not allow you to specify glob patterns, so you must specify each non-python file to watch for changes. -
Alternatively, you could run Flask with the Flask development server:
flask --app main:app run --debug --extra-files templates/index.html:static/styles.css
Use
;
on Windows to separate the--extra-files
instead of:
. The above command will run a server onhttp://localhost:5000
and watch for changes to Python files (default),templates/index.html
, andstatic/styles.css
. Annoyingly, like with gunicorn,flask
does not allow you to specify glob patterns, so you must specify each non-python file to watch for changes.
-
-
In a separate terminal, run browser-sync in watch mode, specifying the address to proxy and the static files path.
browser-sync 'http://localhost:8000' 'static' --watch --files .
Change the
localhost
port to the port your server is running on if it differs from8000
. The above command will run a server onhttp://localhost:3000
and proxy requests tohttp://localhost:8000
(your server running FastAPI or Flask). It will also forward static files from thestatic
directory (you can change the static files directory with the second argument to browser-sync). Finally, it will watch for changes to all files relative to the working directory and reload the browser when those files change.Go to
http://localhost:3000
. -
Turn off caching in your browser
NOTE: This third step might not be necessary for you. Playing around with browser-sync, it appears to usually not cache static files. However, it doesn't seem like cache-prevention works 100% of the time, so I'll include this option just in case.
By default, browsers will cache static files. Therefore, you might not see changes to CSS and JavaScript files reflected in the browser, as the browser will use the stale, cached version after the first load. To fix this, you might need to turn off caching in your browser. For Chrome, you can do this with the following steps:
- Open the browser to
http://localhost:3000
- Right-click on the browser page
- Click "Inspect" to open dev tools
- Navigate to the "Network" tab
- Check "Disable cache"
NOTE: If you do need this step, disabling the cache this way only applies while dev tools remains open.
- Open the browser to
-
Update your files as needed and see the changes automatically reflected in the browser—no manual intervention required.
Conclusion
Now, when developing your FastAPI or Flask application, you have the tools to change your Python, HTML, CSS, and Javascript files and see those changes automatically reflected in the browser (http://localhost:3000
) without refreshing the page. Furthermore, the techniques shown here should work for any web application with built-in hot-reload functionality—not just the two I showed examples for in this tutorial. Enjoy your easier, more iterative web development experience!