I've spent a fair amount of time reading through Stack Overflow questions and can't find what I'm looking for.
I'm creating a Flask API and React frontend to be deployed on GAE. My directory structure looks like this:
application_folder
-> api
-> -> app.yaml
-> -> main.py
-> react_frontend
-> -> app.yaml
-> -> {directories after using create-react-app}
For development
1.) The package.json
of the React app, I've set a proxy:
"proxy": "http://localhost:5000/"
My React frontend is running on port 3000.
2.) I fetch within the React frontend's App.js
file as such:
fetch('api/endpoint')
Works like a dream.
For Production
However, when deploying to GAE, I have to make the following changes:
1.) Remove proxy from package.json
. I couldn't find a way for this to work with a proxy as I received a 404 error on the React frontend on production.
2.) Add Access-Control-Allow-Origin to Flask API in main.py
.
@app.route("/api/endpoint", methods=["GET"])
def endpoint():
resp = make_response({"cat": 15})
resp.headers["Access-Control-Allow-Origin"] = "*"
return resp
3.) Now, I have to fetch with absolute path from App.js
.
fetch('flask-production-domain.com/api/endpoint')
My question is, would you recommend a way of deploying to production/setting up local development such that I don't have to rewrite the code base when I deploy to production?
By the way my app.yaml files read as such:
# api app.yaml
runtime: python38
env_variables:
none_of: "your_business"
# frontend app.yaml
runtime: nodejs12
service: banana
handlers:
- url: /static
static_dir: build/static
- url: /(.*\.(json|ico|js))$
static_files: build/\1
upload: build/.*\.(json|ico|js)$
- url: .*
static_files: build/index.html
upload: build/index.html
Thanks in advance.
EDIT
I've accepted dishant's answer, but I've done it slightly differently than they've suggested.
Firstly, these two resources are incredible. This guy wrote "the book" on Flask:
In the second video, he describes two methods of deploying. The first one is similar to what dishant suggested. In the video Miguel describes this option as his lesser favorite of the two he describes, as serving the files from python is slow. For me, it works well for now, as it's the "easier" of the two, and it seems like you can easily switch down the road.
So, I've made the following changes:
- I changed the directory structure to:
Top Level
-> directories after using create-react-app
application_folder
-> api
-> -> app.yaml
-> -> main.py
- Instead of creating the routing in the
app.yaml
file, I added the following to themain.py
fie:
app = Flask(__name__, static_folder="build", static_url_path="/")
@app.route("/")
def index():
return app.send_static_file("index.html")
- I added the following line to the package.json to create a script to build and move the static files to the api directory.
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"create-app": "yarn build && rm -r api/build && cp -r build api/build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
So now I run yarn create-app
to build.
I'm going to look into Travis for CI/CD, since I've used that before.