I have an existing app written in Flask, deployed to Heroku, It works great, but I decided to convert it to an Angular frontend, using Flask just for the API. This also works great locally, but I'm almost done and I'd like deploy it to Heroku from the same repository. This site is an internal set of tools and is SUPER low traffic...think 20-40 hits a day MAX.
This is the current file system structure:
├── Procfile
├── README.md
├── backend
│ ├── app.py
│ ├── requirements.txt
│ ├── static **(will not be used by Flask)**
│ └── templates **(will not be used by Flask)**
├── frontend
│ ├── angular.json
│ ├── dist
│ │ ├── mmscripts
│ │ │ ├── 3rdpartylicenses.txt
│ │ │ └── browser
│ │ │ │ ├── favicon.ico
│ │ │ │ ├── index.html
│ │ │ │ ├── main-HX6HQ3LL.js
│ │ │ │ ├── polyfills-S3BTP7ME.js
│ │ │ │ └── styles-HCXVZOOP.css
│ ├── package-lock.json
│ ├── package.json
│ ├── src
│ │ ├── app
│ │ │ ├── env.ts
│ │ ├── assets
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── main.ts
│ │ └── styles.scss
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ └── tsconfig.spec.json
└── runtime.txt
At the moment I cd into backend and run the Flask app: FLASK_ENV=development flask run
Then in a separate shell I cd into frontend and run ng serve
. I have Flask-Cors installed in the Flask app so that Angular can access the API, then in frontend/src/app/env.ts
I've got this constant:
export const API_URL = 'http://localhost:5000/api';
Here's some versioning:
Angular 17
Flask 3
Flask-Cors 4
Heroku stack is 22
Procfile:
web: gunicorn app:app
runtime.txt
python-3.9.19
I don't mind rearranging the file system if need be. I just used this particular setup because it seemed to make things easier from an organizational standpoint.
I was able to get this working almost exactly like I was hoping.
For anyone coming behind me, here's how I accomplished it.
backend
and a frontend
directories.
Procfile
which contains the below code.
web: gunicorn --chdir ./backend app:app
frontend
directory, prior to deploying to Heroku, run the following command:
ng build --configuration production
dist
folder should either be created, or updated, with your minimized Angular code.In order to allow Flask to serve the proper files, I also had to make changes to my app.py
file as follows:
from flask import (
Flask,
send_from_directory,
)
app = Flask(__name__, static_folder='../frontend/dist/<my Angular app name>/browser/', static_url_path='')
@app.errorhandler(404)
@app.route('/',defaults={"e": ""})
def index(e):
return send_from_directory(app.static_folder, 'index.html')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=81)