Search code examples
javascriptpythonflaskdeploymentproduction

Best approach to handle single page app front end and api backend on a server


I've built an API using flask and a single page app as the frontend. The backend ran on port 5000 and I used parcelJS to build the frontend and it has it's own webserver which ran on port 1234. The css,js and static files are all inside the dist folder which are accessible from 127.0.0.1:1234 using parcels webserver.

All the requests coming from the frontend are made to 127.0.0.1:5000.

Question

I want to deploy the project on a server, should I integrate both and have the front and back end work on the same webserver and enable CORS and what is the best approach to handle API based single page app implementations?

API Server

The API server is started on port 5000 with the settings below.

self.app = Flask(__name__, static_folder="../../front/dist",
                         template_folder="../../front/dist")
self.api = Api(self.app)
CORS(self.app)
if __name__ == '__main__':
    app_instance.app.run(debug=True, host='127.0.0.1', port=5000)

API Endpoint

An endpoint like /api/snippets makes a query to the database and return a json response.

app_instance.api.add_resource(Snippets, '/api/snippets')

Frontend

The javascript at the frontend makes a request to 127.0.0.1:5000/api/snippets.

When I try to use pythons webserver to serve index.html, I do get the HTML content but I can't access the js,css files in the dist folder.

@app_instance.app.route('/')
def index():
    return render_template("index.html")

When I configure NGINX to handle the routes I need to make the requests to the domain and have CORS disabled.

Folder structure

├── back
│   └── app
│       
└── front
    ├── assets
    ├── css
    ├── dist
    └── js
        ├── components
        └── lib

Solution

  • I needed to run both from the same webserver. I used python/flasks development server for testing purposes but the main idea is the same and should work with other scenarios.

    I added the routes and handled them using flasks template renderer

    from flask import render_template
    @app_instance.app.route('/')
    @app_instance.app.route('/create')
    @app_instance.app.route('/snippet/<path:path>') #dynamic route
    def index(path=None):
        return render_template("index.html")
    

    And configured Nginx to handle the requests.

    server {
            listen 80;
            listen [::]:80;
    
            server_name somedomain;
    
            root some/path/to_the/front/dist;
            index index.html;
    
            location / {
                    try_files $uri /index.html;
                    gzip_static on;
            }
    
    }
    

    Result

    I can now make requests from the front end to http://127.0.0.1:5000/api/snippets/api since flask is operating on that port and I also have access to my index.html without using the 5000 port.