Vue SPA and Flask together
Posted on
by Kevin FoongIn this blog post I will provide an overview of how to get Flask to serve a Vue Single Page Application (SPA). I assume you already have the prerequisites installed - namely node.js, Vue and Python.
Vue
1. Use Vue to create your project.
vue create myproject
2. In the Vue CLI select "Manually select features"
For a SPA make sure you choose Router. The rest is your preference.
3. When finished you will have a "myproject" folder containing all the Vue files.
4. Run a production build which will create a "dist" sub-folder. This will be where your single page application will be located.
npm run build
Flask
1. Create an "api" sub-folder within "myproject" for your Flask files. Navigate to your folder and create a Python virtual environment. If you are on Python 3 you can use the below command to create a virtual environment called "env", otherwise if you are on Python 2 use "virtualenv env". (virtualenv was integrated into Python 3 since version 3.3)
python -m venv env
2. Activate your virtual environnment. If you are using Window's CMD terminal you can also create a Windows .bat file like "runenv.bat" with the command to save you from having to type out the full command each time.
env\scripts\activate
3. Pip install the below packages.
- Flask for obvious reasons.
- Python-dotenv to manage your environment variables.
- Flask-CORS to enable your Vue app to access your Flask app's API otherwise you will normally be blocked. This is only needed for testing if you are running the Vue server and Flask server separately as both are on different ports. In production this will not be needed because the "dist" folder will be part of the Flask directory. On the subject of CORS, this article provides some good information.
pip install flask
pip install python-dotenv
pip install flask-cors
4. In the "api" folder create 2 files
".env" for your environment variables
This is where you keep all your keys. Remember never make this file publicly available (such as in Github).
I used SECRET_KEY just to provide an example. SECRET_KEY is used by Flask for various things like encrypting session variables.
FLASK_APP=app.py
# For development it should be FLASK_ENV=development
# For production it should be FLASK_ENV=production
FLASK_ENV=development
SECRET_KEY=Somesecretkey999
"config.py" for your apllication configuration
This is where you load the environment variables and also provide any Flask configuration
import os
from dotenv import load_dotenv
from pathlib import Path
# handy to have - makes referencing files on local system each
basedir = Path(__file__).parent
load_dotenv(basedir / '.env')
class Config(object):
SECRET_KEY = os.environ.get('SECRET_KEY') or 'you-will-never-guess'
5. Create a sub-folder "app" under "api" and create 2 files.
"app" is your main application package. The 2 files are:
"__init__.py"
This is where you instantiate Flask and read in the config file.
It also contains 2 important elements:
- When you instantiate Flask include the 2 parameters "static_folder" and "static_url_path". We will make "static_folder" point to our Vue production build folder (the "dist" folder). "static_url_path" makes the url more friendly by removing "static" from the url, so instead of http://example.com/static/index.html you will have http://example.com/index.html
- We will need CORS (Cross Origin Resource Sharing) to enable Vue to access Flask's API's during testing (assuming you are running both Vue server and Flask server). You do not need CORS for production, so you will need to comment this out prior to uploading to production.
from flask import Flask
from config import Config
from flask_cors import CORS
app = Flask(__name__, static_folder='../../dist', static_url_path='/')
app.config.from_object(Config)
CORS(app)
from app import routes
"routes.py"
We create a Flask route to point to Vue's index.html
from app import app
@app.route('/')
def index():
return app.send_static_file('index.html')
6. Lastly back in the "myproject" folder create "app.py" which is the entry point to your Flask application.
This simply imports the app package we created in step 5
from app import app
7. If all went well you can now start Flask. Go to the "api" folder and make sure your virtual environment is activated.
flask run
9. In your browser go to http://localhost:5000 . You should see Vue's starting page:
10. Congratulations! Your Flask server is now serving your Vue single page application.
You can now host both Flask and Vue on one server. You can also use your Flask application to provide API endpoints to serve your Vue app.
Now just develop in Vue as normal. You can use "npm run serve" to use Vue's web server while developing in Vue. When ready just run "npm run build" and it will build to the "dist" folder which Flask will automatically pick up.
11. The final folder directory should look something like below:
Lastly don't forget to update ".gitignore" in the root folder to ensure the below Flask files are not uploaded to your Github.
# flask files
env
.env
__pycache__
And another thing. For error handling like page not found (404 error) where user types in a URL that doesn't exist, you might have an error handler like below in Flask. If this happens you can just redirect the user back to your Vue homepage.
@app.errorhandler(404)
def page_not_found(e):
return redirect('/')