Web Development with Vite, Vue, and Flask

web-development-with-vite,-vue,-and-flask

Introduction

we’ll explore how to use Vue.js and Flask together to create an application. We’ll cover the process of creating a front-end template using the development tool Vite and subsequently integrating a Flask back-end. This process is quite engaging, and I believe you’ll find it intriguing!

Benefits
Combining Vue.js for the front-end and Flask for the back-end in web application development offers several advantages, especially when leveraging their respective strengths.

Python excels in handling backend operations, data manipulation, and complex mathematical calculations. Its vast ecosystem of libraries allows for easy integration with databases, data processing tools, and machine learning frameworks.

Vue.js, a progressive JavaScript framework, is designed to build modern, interactive user interfaces. JavaScript, being the language of the web, is well-suited for client-side development. Vue.js simplifies the creation of dynamic, responsive, and visually appealing UIs.

Overview

  1. Creating a Vue front-end app template with Vite
  2. Integrating with Flask
  3. Creating a Docker image

Creating Vue app template

Navigate to your development directory (e.g., Projects) and execute the following command:

yarn create vite

During the setup, you’ll be prompted to answer several questions:

Project name: vite-project (can be any name, for example: 'vite-project')
Select a framework: Vue
Select a variant: JavaScript

A directory named vite-project will be created. Navigate into it and run the yarn command:

cd vite-project
yarn

At this point, you can already run the template application with:

yarn dev

When you visit http://localhost:5173 in a web browser, you’ll see the application’s interface. There’s a button in the center of the screen labeled “count is 0.” Clicking this button will increment the count.

Next, build the app.

yarn build

The source will be compiled, and the artifacts will be placed in the dist distribution directory. To perform a final check of the application, execute:

yarn preview

Accessing http://localhost:4173 in a browser, you should see the application interface. The app’s behavior will be identical to what was seen with ‘yarn dev’, but with the compiled JavaScript running the show.

The typical front-end creation process involves modifying the source code, checking its functionality with yarn dev, and if there are no issues, executing yarn build. The final operation is verified with yarn preview, and this cycle continues.

Working with Flask

Initially, let’s use Flask simply to display the application’s interface. Flask defines where to place different types of resources, necessitating file placement according to these rules:

Parameter Name Description Default
static_folder JS, CSS, Location of static resources such as images static
template_folder Location of HTML files to be rendered by Flask templates
static_url_path Path name for accessing the static folder /static

Comparing the actual artifacts in the dist folder layout with the default values, some differences are apparent. Specifically, JS and CSS files are placed in the dist/assets folder, but we aim to align the layout with Flask’s requirements by renaming assets to static in the configuration.

To do this, open the vite.config.js file and add the following setting to build.assetsDir:

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],

  build: {
    assetsDir: "static",
  },
});

After running yarn build, confirm that the output has changed to dist/static.

Now, Flask takes the stage:

from flask import Flask, render_template

app = Flask(__name__, static_folder="dist/static", template_folder="dist", static_url_path="https://dev.to/static")


@app.route("https://dev.to/", defaults={"path": ""})
@app.route("https://dev.to/")
def index(path):
    return render_template("index.html")

Due to the layout generated by Vite differing from Flask’s default, parameters like static_folder are explicitly specified with actual values.

Run the Flask server with:

flask run

Accessing http://localhost:5000 in a browser should display the application interface. The Vite logo might not appear, but the count-up functionality should work fine.

The logo’s absence is due to the image file’s location. If you check the dist folder, vite.svg is found directly under dist, but as per the table, it needs to be in the static_folder (=dist/static).

To address this, move vite.svg from the public directory to static:

cd public
mkdir static
mv vite.svg static

The reason for not manually handling files under dist is to ensure they are automatically placed during yarn build.

Files in the public directory are copied to the dist directory, maintaining the tree structure during the build.

Additionally, the source referencing vite.svg must be updated. Relevant locations include:



After running yarn build, vite.svg should be in dist/static. Re-run flask run and visit http://localhost:5000. This time, the logo should display correctly!

To further utilize Flask, let’s have it handle the incrementing process. Add to app.py:

@app.route("https://dev.to/increment/")
def increment(count):
    return f"{count + 1}"

Modify the Vue side to request Flask to increment when the button is pressed. The relevant code is in
src/components/HelloWorld.vue

Edit components/HelloWorld.vue to test HMR

Replace @click=... with a function that requests Flask. Implement ‘incrementCount’ as follows:

const count = ref(0);

const incrementCount = () => {
  fetch(`/increment/${count.value}`)
    .then((response) => {
      if (response.ok) {
        return response.text();
      } else {
        throw new Error(`${response.status} ${response.statusText}`);
      }
    })
    .then((val) => {
      count.value = parseInt(val);
    })
    .catch((error) => {
      console.error(`Error: ${error.message}`);
    });
};

Substitute the button press action with this function name:

Edit components/HelloWorld.vue to test HMR

Verify operation with:

yarn build
flask run

Creating a Docker Image

Having completed most of our objectives, let’s also try creating a Docker image.

Use VSCode convenient feature to create a Dockerfile:

Open the folder vite-project in VScode.
(I assume you already have it open…)

Access the command palette (Ctrl+Shift+P) and search for ‘Add Docker Files’.

Select Docker: Add Docker Files to Workspace.... (If it doesn’t appear, you might need to install the Docker extension).

Select Application Platform.
Python Flask.

Choose the app's entry point(e.g. manage.py, app.py)
→ Choose app.py.

What port(s) does your app listen on? Enter a comma-separated list, or empty for no exposed port.
→ Enter a comma-separated list, or empty for no exposed port. Select the displayed number as it is. It is probably 5002, but you can change it to any number you like.

Include optional Docker Compose files.
Do you want to create docker-compose.yml as well? Select Yes.

Dockerfile Editing

Make the following changes to the Dockerfile:

Originally, we have:

WORKDIR /app
COPY . /app

Change the COPY source to ./dist since we want the dist directory in the container. Also, move index.html from the dist directory to the templates directory to adhere to the standard Flask structure:

WORKDIR /app
COPY ./dist/ .
RUN mkdir -p templates && mv index.html templates

Modifying and Placing app.py

In the Docker version, the Flask layout has been reverted to default, so the optional parameters specified in app.py should be removed:

app = Flask(__name__, static_folder="dist/static", template_folder="dist", static_url_path="https://dev.to/static")

In Docker, this can be simplified to:

app = Flask(__name__)

Copy app.py to the public directory and run yarn build:

cp app.py public
yarn build

Build the Docker image again with:

docker-compose build

Launch the container with:

docker-compose up -d

Go to http://localhost:5002.

Did it work?

Visit http://localhost:5002 and check if the app works correctly!

Finally, to avoid managing separate versions of app.py for Docker and non-Docker environments, consider using a configuration file to set parameters like static_folder based on the environment. This approach is simple yet effective.

The final app.py could look like this:

import json
from flask import Flask, render_template

args = dict()
try:
    with open("args.json") as f:
        args = json.load(f)
except FileNotFoundError:
    pass

app = Flask(__name__, **args)


@app.route("https://dev.to/", defaults={"path": ""})
@app.route("https://dev.to/")
def index(path):
    return render_template("index.html")


@app.route("https://dev.to/increment/")
def increment(count):
    return f"{count + 1}"

Create an args.json file with the following contents:

args.json

{
  "static_folder": "dist/static",
  "template_folder": "dist",
  "static_url_path": "https://dev.to/static"
}

By doing this, parameters can be environment-specific, and app.py can be centrally managed. If args.json is missing, Flask will catch the FileNotFoundError and default values will be used.

Total
0
Shares
Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Post
effective-b2b-sales-coaching-via-situational-fluency

Effective B2B Sales Coaching Via Situational Fluency

Next Post
dfgv:-self-contained-full-stack-web-apps

DFGV: Self-Contained Full-Stack Web Apps

Related Posts