Skip to content

Instantly share code, notes, and snippets.

@CheeseCake87
Last active November 6, 2023 14:33
Show Gist options
  • Save CheeseCake87/3e0382afe8b36cd07f73f537963d5f97 to your computer and use it in GitHub Desktop.
Save CheeseCake87/3e0382afe8b36cd07f73f537963d5f97 to your computer and use it in GitHub Desktop.
Multiloader: Flask, Vite, SocketIO, Gunicorn
project_folder/
├── app/
│   ├── static/
│   │   └── ...
│   ├── templates/
│   │   └── ...
│   ├── extensions/
│   │   └── __init__.py
│   └── __init__.py
│
├── app_vite/
│   ├── src/
│   ├── index.html
│   └── index.css
│
├── ...
│
├── Dockerfile
│
├── ...
│
├── project.config.json
├── project.docker.builds.json
├── project.py
│
├── ...
│
└── vite.config.js
{
"build_tag": "my_project",
"vite_dist_folder": "app_vite/dist",
"flask_static_folder": "app/static",
"flask_templates_folder": "app/templates"
}
{
"builds": [
"my_project:b1"
]
}
import json
import subprocess
from multiprocessing import Process
from pathlib import Path
import click
from dotenv import load_dotenv
load_dotenv()
def _vite_run():
pro_ = subprocess.Popen(["npm", "run", "dev"])
pro_.wait()
def _flask_run():
pro_ = subprocess.Popen(["flask", "run", "--debug"])
pro_.wait()
def _socketio_dev():
from app import create_app
from app.extensions import socketio
socketio.run(create_app(), debug=True)
def _socketio_pro():
from app import create_app
from app.extensions import socketio
socketio.run(create_app(), host="0.0.0.0", port=5000)
def _gunicorn():
pro_ = subprocess.Popen(["gunicorn"])
pro_.wait()
@click.group()
@click.pass_context
def cli(ctx):
ctx.ensure_object(dict)
config_file = Path(Path.cwd() / "project.config.json")
if not config_file.exists():
raise FileExistsError("project.config.json cannot be found.")
ctx.obj.update(json.loads(config_file.read_text()))
@cli.command()
@click.option("--docker", help="Build Dockerfile", is_flag=True)
@click.option("--tag", help="Docker build tag", default=None)
@click.pass_context
def build(ctx, docker, tag):
_cwd = Path.cwd()
click.echo("Building with Vite...")
_build = subprocess.Popen(["npm", "run", "build"])
_build.wait()
_vite_dist_folder = Path(_cwd / ctx.obj['vite_dist_folder'])
_flask_static_folder = Path(_cwd / ctx.obj['flask_static_folder'])
_flask_templates_folder = Path(_cwd / ctx.obj['flask_templates_folder'])
assets = _vite_dist_folder / "assets"
index = _vite_dist_folder / "index.html"
click.echo("Vite build successful")
click.echo("Copying assets to Flask static folder")
subprocess.run(["cp", "-r", assets, _flask_static_folder])
click.echo("Copying index.html to Flask templates folder")
subprocess.run(["cp", index, _flask_templates_folder])
if docker:
print("Building Dockerfile...")
if tag:
_build_tag = tag
else:
_build_tag = ctx.obj['build_tag']
docker_builds_file = _cwd / "project.docker.builds.json"
if not docker_builds_file.exists():
docker_builds_file.write_text(json.dumps({"builds": []}, indent=4))
docker_builds = json.loads(docker_builds_file.read_text()).get("builds")
new_tag = f"{_build_tag}:b{len(docker_builds) + 1}"
docker_builds.append(f"{new_tag}")
docker_build = subprocess.Popen(
["docker", "build", "-t", f"{new_tag}", "."]
)
docker_build.wait()
docker_builds_file.write_text(json.dumps({"builds": docker_builds}, indent=4))
@cli.command()
@click.option("--flask-dev", help="Run `Flask run --debug`", is_flag=True)
@click.option("--vite-dev", help="Run `npm run dev`", is_flag=True)
@click.option("--socketio", help="Run socketio in production", is_flag=True)
@click.option("--socketio-dev", help="Run socketio in development", is_flag=True)
@click.option("--gunicorn", help="Run gunicorn", is_flag=True)
@click.pass_context
def run(ctx, flask_dev, vite_dev, gunicorn, socketio, socketio_dev):
_ = ctx.obj
if vite_dev:
pro_ = Process(target=_vite_run)
pro_.start()
if gunicorn:
pro_ = Process(target=_gunicorn)
pro_.start()
return
if socketio:
pro_ = Process(target=_socketio_pro)
pro_.start()
return
if socketio_dev:
pro_ = Process(target=_socketio_dev)
pro_.start()
return
if flask_dev:
pro_ = Process(target=_flask_run)
pro_.start()
return
if __name__ == '__main__':
cli()
import { defineConfig } from 'vite';
import solidPlugin from 'vite-plugin-solid';
export default defineConfig({
plugins: [
solidPlugin(),
],
root: 'app_vite',
server: {
port: 3000,
},
build: {
target: 'esnext',
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment