Python (Flask) serving Angular project's index.html file
To simplify the setup, consider using Angular CLI to place all of the files in a distribution directory during the build process, i.e., by specifying the outputPath
in angular.json. You can use the angular.json assets
section to move your Python files during the build.
angular.json
"your-project": { "root": "your-project-directory", "sourceRoot": "your-project-directory/src", "projectType": "application", "architect": { "build": { "builder": "@angular-devkit/build-angular:browser", "options": { "outputPath": "dist", "index": "your-project-directory/src/index.html", "main": "your-project-directory/src/main.ts", ... "assets": [ { "glob": "**/*", "input": "your-project-directory/src/assets/", "output": "assets" }, { "glob": "**/*", "input": "your-project-directory/src/python/", "output": "." }
In the top level of the dist
directory, place your main.py
with the basic Flask setup along with index.html
. Note the static_proxy to ensure that supporting files are served.
main.py
from flask import Flask, send_from_directoryapp = Flask(__name__)@app.route('/<path:path>', methods=['GET'])def static_proxy(path): return send_from_directory('./', path)@app.route('/')def root(): return send_from_directory('./', 'index.html')if __name__ == '__main__': # This is used when running locally only. When deploying use a webserver process # such as Gunicorn to serve the app. app.run(host='127.0.0.1', port=8080, debug=True)@app.errorhandler(500)def server_error(e): return 'An internal error occurred [main.py] %s' % e, 500
This is an old question but accepted answer did not work for me. So here is my solution that works with angular routing:
My folder structure:
/angular /src angular.json ... angular project files/public index.html ... angular build files/venvserver.py
In my angular.json I changed outputPath to achive above structure:
"outputPath": "../public"
And in server.py:
import os.path@app.route("/custom-endpoint")def custom_endpoint_handler(): return jsonify(myKey="myValue")# Serving static files@app.route('/', defaults={'path': ''})@app.route('/<string:path>')@app.route('/<path:path>')def static_proxy(path): if os.path.isfile('public/' + path): # If request is made for a file by angular for example main.js # condition will be true, file will be served from the public directory return send_from_directory('public', path) else: # Otherwise index.html will be served, # angular router will handle the rest return app.send_static_file("index.html")
Footnote: I am new to flask. So any improvements or fixes if there are any errors are welcomed.
As mentioned in Flask docs:
Just create a folder called static in your package or next to your module and it will be available at /static on the application.
So, if you use the template in:
templates/dist/templates/index.htmlstatic/ # set static folder there
Or, depending how you have your application sorted:
templates/dist/static/ # set static folder there
Have a look at how they sort the application in the docs:
/application.py/templates /hello.html
or if you use module folders:
/application /__init__.py /templates /hello.html