Construire la même application en utilisant différents frameworks Web : FastHTML, Next.js, SvelteKit, par Eugene Yan

Récemment, je me suis demandé si je devais migrer de ma pile d'applications web actuelle (FastAPI, HTML, CSS, et un peu de JavaScript) vers un framework web moderne. J'ai été particulièrement intéressé par FastHTML, Next.js et Svelte.

  • FastHTML : De nombreuses personnes ont commencé à construire avec ce framework depuis que Jeremy Howard l'a lancé il y a un peu plus d'un mois. Son objectif est de permettre la création d'applications web modernes en Python pur.
  • Next.js : J'ai rencontré plusieurs applications construites avec ce framework, comme cal.com et roomGPT. Il dispose d'un large écosystème et est populaire pour la construction d'applications web de niveau production.
  • SvelteKit : Ce framework léger a été populaire auprès des développeurs (Stack Overflow, TSH, State of JS) et de mon ami Swyx (Why I Enjoy Svelte) au cours des dernières années.

Pour en savoir plus sur ces frameworks, j'ai construit la même application web en utilisant chacun d'entre eux. L'application, que j'appelle « Look at Your Data », permet aux utilisateurs de :

  • Charger un fichier CSV pour initialiser une table de base de données SQLite
  • Visualiser la table dans le navigateur web
  • Mettre à jour des champs individuels dans la table
  • Supprimer des lignes individuelles dans la table
  • Télécharger les données mises à jour de la table sous la forme d'un nouveau fichier CSV

En mettant en œuvre ces opérations CRUD (Create, Read, Update, Delete) dans chaque framework, j'espère me faire une idée des caractéristiques uniques de chaque framework et de l'expérience du développeur qui en découle. Pour simplifier les choses, j'utiliserai SQLite comme base de données. En guise de référence, je commencerai par construire l'application avec ce qui m'est familier - FastAPI.

Nom : poll.jpg
Affichages : 7895
Taille : 45,6 Ko
J'ai organisé des sondages sur les trois frameworks sur Twitter et LinkedIn

FastAPI + Jinja + HTML + CSS + JavaScript

La construction de l'application avec FastAPI est assez simple (code). Les composants clés sont les suivants :

  • main.py : Routes pour charger/télécharger des données, mettre à jour des champs, supprimer des lignes.
  • index.html : Le document HTML qui définit les scripts, la table et les boutons.
  • style.css : Style visuel tel que la largeur des colonnes, l'habillage des mots, le défilement.
  • script.js : Fonctionnalité côté client pour le téléchargement du fichier CSV, le chargement des données pour l'affichage, la mise à jour/suppression des lignes et le téléchargement des données mises à jour sous forme de fichier CSV.

Nom : fastapi.jpg
Affichages : 349
Taille : 18,3 Ko

Voici à quoi ressemble l'application web. Bien qu'elle ne soit pas très attrayante d'un point de vue esthétique, elle répond à nos exigences. J'ai délibérément réduit le style visuel au minimum (pour l'application actuelle et les suivantes) afin que l'accent soit mis sur les frameworks et les fonctionnalités plutôt que sur le design.

Nom : fastapi-app.jpg
Affichages : 351
Taille : 94,2 Ko

FastHTML

Pour apprendre FastHTML, j'ai commencé par consulter la documentation et à construire une simple application ToDo via ce walkthrough. Pour obtenir de l'aide sur des composants peu familiers, je me suis appuyé sur Cursor en fournissant des liens vers des documents pertinents tels que ft components, htmx, pico.css en tant que contexte. Avec FastHTML, j'ai pu implémenter l'ensemble de l'application dans un seul main.py et un petit style.css (code).

Nom : fasthtml.jpg
Affichages : 348
Taille : 12,2 Ko

Voici à quoi ressemble l'application.

Nom : fasthtml-app.jpg
Affichages : 348
Taille : 76,0 Ko

Après ma première itération ci-dessus, Hamel a gracieusement proposé de faire de la programmation en binôme avec moi pour construire l'application à partir de zéro. Il a également invité Jeremy Howard, le créateur de FastHTML, à se joindre à nous. Ils m'ont enseigné plusieurs astuces, notamment en fournissant à Cursor une documentation LLM conviviale pour FastHTML (llms-ctx.txt) et FastLite (html.md). Ils ont également partagé une excellente ressource sur la construction d'applications plus simples avec htmx et Hyperview. Jeremy a même pris le temps de montrer comment construire l'application en seulement 50 lignes de code !

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
from fasthtml.common import *

db = database(':memory:')
tbl = None
hdrs = (Style('''
button,input { margin: 0 1rem; }
[role="group"] { border: 1px solid #ccc; }
'''), )
app, rt = fast_app(live=True, hdrs=hdrs)

@rt("/")
async def get():
    return Titled("CSV Uploader",
        Group(
            Input(type="file", name="csv_file", accept=".csv"),
            Button("Upload", hx_post="/upload", hx_target="#results",
                   hx_encoding="multipart/form-data", hx_include='previous input'),
            A('Download', href='/download', type="button")
        ),
        Div(id="results"))

def render_row(row):
    vals = [Td(Input(value=v, name=k)) for k,v in row.items()]
    vals.append(Td(Group(Button('delete', hx_get=remove.rt(id=row['id'])),
                   Button('update', hx_post='/update', hx_include="closest tr"))))
    return Tr(*vals, hx_target='closest tr', hx_swap='outerHTML')

@rt
async def download():
    csv_data = [",".join(map(str, tbl.columns_dict))]
    csv_data += [",".join(map(str, row.values())) for row in tbl()]
    headers = {'Content-Disposition': 'attachment; filename="data.csv"'}
    return Response("\n".join(csv_data), media_type="text/csv", headers=headers)

@rt('/update')
def post(d:dict): return render_row(tbl.update(d))

@rt
def remove(id:int): tbl.delete(id)

@rt("/upload")
async def post(csv_file: UploadFile):
    global tbl
    if not csv_file.filename.endswith('.csv'): return "Please upload a CSV file"
    tbl = db.import_file('test', await csv_file.read(), pk='id')
    header = Tr(*map(Th, tbl.columns_dict))
    vals = [render_row(row) for row in tbl()]
    return Table(Thead(header), Tbody(*vals))

serve()

Et voici à quoi ressemble l'application de Jeremy :

Nom : fasthtml-app-jeremy.jpg
Affichages : 348
Taille : 49,3 Ko

Next.JS

Pour apprendre Next.js, j'ai suivi les tutoriels React Foundations et Next.js. Ce dernier enseigne les bases de Next.js par le biais de petites leçons pratiques qui permettent de créer une application de tableau de bord. Avec 16 chapitres dans le tutoriel Next.js, l'apprentissage et le codage peuvent prendre un certain temps. Néanmoins, je recommande de persister au moins jusqu'au chapitre 12 sur la transformation des données (dans le tutoriel Next.js), et j'ai apprécié la courbe d'apprentissage douce et les projets pratiques.

Voici comment j'ai créé le modèle d'application Next.js :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
npx create-next-app@latest

Construire la même application dans Next.js nécessite beaucoup plus de code que les versions Python (code). Néanmoins, j'ai trouvé son organisation intuitive :

  • api : Routes pour la table de données (GET, PUT, DELETE) et le chargement/téléchargement de fichiers
  • pages.tsx et layout.tsx : Composants de l'interface utilisateur communs et spécifiques à la page
  • components : Composants React réutilisables tels que les tables et les boutons de chargement/téléchargement.
  • lib : fonctions utilitaires ; dans ce cas, il y avait une seule fonction pour SQLite

Nom : next.jpg
Affichages : 345
Taille : 44,1 Ko

Et voici à quoi ressemble l'application web. L'intégration de Tailwind CSS rend l'application un peu plus soignée par rapport aux applications FastAPI et FastHTML dépouillées.

Nom : next-app.jpg
Affichages : 347
Taille : 95,4 Ko

SvelteKit

Pour apprendre Svelte, j'ai suivi une partie de leur tutoriel qui est fourni avec un interpréteur en ligne. Le tutoriel comporte quatre parties : (i) Svelte de base, (ii) Svelte avancé, (iii) SvelteKit de base, et (iv) SvelteKit avancé. J'ai terminé les sections sur Svelte de base et SvelteKit de base et j'ai commencé à construire l'application (code).

Pour créer le modèle d'application SvelteKit, j'ai exécuté ce qui suit :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
npm create svelte@latest my-app

Comme Next.js, le modèle pour SvelteKit a plusieurs répertoires et parties mobiles :

  • components : Composants réutilisables de Svelte tels que la table de données et les boutons de téléchargement
  • api.ts et db.ts : Fonctions pour l'API pour récupérer, mettre à jour et supprimer des données (api.ts) ainsi que pour interroger et exécuter des mises à jour sur la base de données SQLite (db.ts)
  • routes : Routes pour les tables (GET), les lignes (PUT, DELETE) et le téléchargement (upload/download).
  • +page.svelte : Page principale de l'application
  • app.html : Point d'entrée et fichier HTML principal

Nom : svelte.jpg
Affichages : 351
Taille : 45,1 Ko

Voici à quoi ressemble l'application. Une petite déviation : J'ai essayé de combiner les fonctionnalités « choisir un fichier “ et ” charger “ en un seul bouton, supprimant ainsi le bouton ” Upload CSV ».

Nom : svelte-app.jpg
Affichages : 348
Taille : 107,2 Ko

FastAPI + Svelte

J'ai également essayé de construire une application avec FastAPI comme backend et Svelte pour le frontend (code). Toutes les fonctionnalités et API résident dans main.py alors que l'interface utilisateur et les interactions avec les API sont gérées par +page.svelte et api.ts respectivement. Pour lancer l'application, je devais démarrer à la fois le serveur FastAPI et le serveur de développement Svelte.

Nom : fastapi-svelte.jpg
Affichages : 348
Taille : 36,4 Ko

Et voici à quoi ressemble l'application web. (J'ai inversé la fonctionnalité d'upload pour qu'elle corresponde à l'application FastAPI originale qui avait un bouton séparé « Upload CSV »).

Nom : fastapi-svelte-app.jpg
Affichages : 348
Taille : 74,7 Ko

Le principal défi consistait à coordonner la communication entre les deux serveurs pendant le développement. Dans un environnement de production, l'application Svelte serait compilée et servie statiquement avec des requêtes API envoyées au backend FastAPI.

Mis à part : Comment les assistants de codage influenceront-ils les développeurs ?

Cet exercice m'a fait réfléchir à la manière dont les assistants de codage, alimentés par des LLM formés sur les données Internet, pourraient influencer les choix que nous faisons en tant que développeurs. Par exemple, les assistants de codage basés sur les LLM seraient-ils aussi efficaces avec des frameworks de niche ou plus récents tels que Svelte et FastHTML ? Bien que le tweet ci-dessous soit peut-être exagéré, il soulève une préoccupation valable.

« Cela ne me fait pas plaisir de le dire, mais Svelte est mort parce que les modèles de base LLM sont meilleurs pour écrire React. » - Jess Martin.

Étant donné l'utilisation plus large et l'histoire plus longue de React et Next, il est probable que la plupart des LLM soient formés sur plus de code React et Next que de code Svelte. Idem pour FastHTML. Cela pourrait conduire à ce que les assistants de codage soient plus efficaces lorsqu'ils travaillent avec et suggèrent du code pour des frameworks établis tels que FastAPI, React et Next.js.

Pour l'anecdote, j'ai eu plus de facilité à utiliser Cursor + Claude pour construire l'application en FastAPI et Next.js, et plus de difficulté avec FastHTML et SvelteKit. Comme FastHTML a à peine quelques semaines (au moment où ces lignes sont écrites), son code et sa documentation n'ont probablement pas encore été intégrés dans les données de formation de la plupart des LLM, ce qui explique leur maîtrise limitée de FastHTML.

Pour résoudre ce problème, Jeremy Howard (créateur de FastHTML) a fait l'effort de fournir llms.txt et llms-ctx.txt qui ont été optimisés pour l'apprentissage en contexte. De même, Rich Harris (qui travaille sur Svelte à Vercel) prévoit de publier une documentation plus adaptée à LLM pour Svelte. Victor Dibia a également écrit sur la façon dont les assistants de codage peuvent affecter les habitudes et les choix des développeurs, et sur la nécessité d'écrire des documents pour les humains et les machines.

L'avenir nous dira si ces efforts sont efficaces pour résoudre le problème du démarrage à froid des nouveaux frameworks ou des frameworks de niche dans les assistants de codage.

...

C'était un exercice amusant pour se familiariser avec FastHTML, Next.js, et SvelteKit. Tout le code peut être trouvé ici. (Je suis un débutant en frontend donc pardonnez les mauvaises pratiques !) Personnellement, j'ai hâte de construire plus avec TypeScript, que je n'ai pas utilisé intensivement depuis que j'ai construit ApplyingML.com il y a des années.

Quelles sont les ressources que vous avez trouvées utiles pour apprendre à construire avec Next.js ou Svelte ? Envoyez-moi un message !

Source : "Building the Same App Using Various Web Frameworks" (par Eugene Yan)

Et vous ?

Quel est votre avis sur le sujet ?
Avez-vous utilisé ces frameworks ou des outils similaires pour votre usage ou le développement d'applications, et si oui, qu'en pensez-vous ?

Voir aussi :

Comment mettre à l'échelle les applications Node.js, par Mensur Durakovic

Flutter, le framework de développement d'applications multiplateformes, est-il sur le point de disparaître ? Flutter remplit-il toujours son rôle chez Google ?

Rio : un framework facile à utiliser pour créer des sites web et des applications modernes entièrement basés sur Python, sans avoir besoin d'une seule ligne de HTML, CSS ou JavaScript