Join Flask and Angular into one project

In last post Flask + Angular base project we created two separate subprojects for Frontend and Backend. Now we need to make it work as one solid application. Frontent should work with Flask context and Flask should be able manage frontend as part of views. At this moment we go away from official documentation and start to build nice developer environment.

1. First we need to create Flask home view with frontend management magic. This view is our application entry point - https://flask.palletsprojects.com/en/1.1.x/quickstart/#rendering-templates

- Create new folder ./templates with home.html within.
<h1>Hello!</h1>
<p>This is test variable: {{var_1}}</p>

- Modify app.py to look it this way:
from flask import Flask, render_template

app = Flask(__name__)


@app.route('/hello')
def hello_world():
    return 'Hello, World!'


@app.route('/')
def home():
    var_1 = 'Test Me!'
    return render_template('home.html', var_1=var_1)

- Run Flask with flask run command and test Home View in http://127.0.0.1:5000/ It should show you these magic words

Hello!

This is test variable: Test Me!


Now let's do some hacks to add Angular DevServer to our python project.

1. Update start script in package.json
"start": "cd ./frontend && ng serve --public-host \"http://localhost:4200\" --disable-host-check"
This enable Live Reload from outside of standard Angular ng serve url.

2. Update Home template with this code:
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Frontend</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
    <app-root></app-root>
    <script src="http://localhost:4200/runtime.js" type="module"></script>
    <script src="http://localhost:4200/polyfills.js" type="module"></script>
    <script src="http://localhost:4200/styles.js" type="module"></script>
    <script src="http://localhost:4200/vendor.js" type="module"></script>
    <script src="http://localhost:4200/main.js" type="module"></script>
</body>
</html>

Actually this content comes from index.html that Angular generate on ng serve command. Now start Flask and Angular projects and open http://localhost:5000. You should see Angular blank project started from Flask url. It means now frontend works with backend context.

Let's go further and improve our Home template to be dependent on environment and render different frontend sources in development and production modes.

home.html
<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Frontend from Flask</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="icon" type="image/x-icon" href="favicon.ico">
    {% if is_development_mode %}
        <base href="/">
    {% else %}

    {% endif %}
</head>
<body>
    {% if is_development_mode %}
        <div>
            <script>
                console.log('************************************');
                console.log('************************************');
                console.log('         DEVELOPMENT MODE');
                console.log('************************************');
                console.log('************************************');
            </script>
            <div style="position: fixed; top: 0; right: 0; background-color: #ef4646; color: #fff; padding: 0 7px; z-index: 99999;">DEVELOPMENT MODE</div>
        </div>
        <app-root></app-root>
        <script src="http://localhost:4200/runtime.js" type="module"></script>
        <script src="http://localhost:4200/polyfills.js" type="module"></script>
        <script src="http://localhost:4200/styles.js" type="module"></script>
        <script src="http://localhost:4200/vendor.js" type="module"></script>
        <script src="http://localhost:4200/main.js" type="module"></script>
    {% else %}
        <h2>PRODUCTION MODE</h2>
        ...
    {% endif %}
</body>
</html>

app.py
@app.route('/')
def home():
    is_development_mode = os.environ.get('FLASK_ENV', 'production') == 'development'
    return render_template('home.html', is_development_mode=is_development_mode)

Do you remember we set FLASK_ENV="development" in .env file that is used by pipenv shell. In this case if project is running in local machine it should know it is development mode and it should use frontend from angular dev server (ng serve). In opposite if mode is production flask should use compiled frontend bundle from static resources (I will describe it in the next post).

As a nice option I've added label in the top right corner of the page that help to know development mode is active (you can remove it - it is just one line of code in home.html)

Let's test it.

In DEVELOPMENT MODE:

In PRODUCTION MODE:
export FLASK_ENV=production
flask run


Next time I will describe how to patch package.json and create one hack to compile frontend to static resource and make it available from Flask.


Comments

Popular posts from this blog

HTTPS in local environment for Angular + Flask project.

Salesforce Authentication 2 (Token Validation and Refresh)

User authentification with Flask-Login