newsmode
search
Меню
arrow_back Назад

Building the Same App Using Various Web Frameworks

auto_awesomeКраткое саммари

Eugene Yan сравнивает четыре веб-фреймворка — FastAPI, FastHTML, Next.js и SvelteKit — построив на каждом из них одно и то же CRUD-приложение для загрузки, просмотра, редактирования и удаления данных CSV. FastAPI и FastHTML позволяют обойтись минимумом файлов (Jeremy Howard продемонстрировал приложение на FastHTML всего в 50 строках кода), тогда как Next.js и SvelteKit требуют заметно больше кода, но предлагают более зрелую экосистему и встроенные инструменты вроде Tailwind CSS. Автор также затрагивает важный вопрос: LLM-ассистенты для кода лучше справляются с популярными фреймворками (React, Next.js), что может усиливать их доминирование и усложнять внедрение новых инструментов вроде FastHTML и Svelte. Создатели этих фреймворков уже начали публиковать специальную документацию, оптимизированную для LLM (llms.txt, llms-ctx.txt), чтобы решить проблему холодного старта.

Создание одного и того же приложения на разных веб-фреймворках

[ learning engineering python 🛠 ] · 8 мин. чтения

В последнее время я задумывался, не стоит ли мне мигрировать с текущего стека для веб-приложений (FastAPI, HTML, CSS и немного JavaScript) на современный веб-фреймворк. Особенно меня интересовали FastHTML, Next.js и Svelte.

FastHTML: Многие начали создавать на нём проекты с тех пор, как Jeremy Howard запустил его месяц назад. Его цель — дать возможность создавать современные веб-приложения на чистом Python. Next.js: Я встречал несколько приложений, построенных на нём, например cal.com и roomGPT. У него обширная экосистема, и он популярен для создания продакшен-приложений. SvelteKit: Этот легковесный фреймворк завоевал популярность среди разработчиков (Stack Overflow, TSH, State of JS) и моего друга Swyx (Why I Enjoy Svelte) за последние несколько лет.

Чтобы лучше разобраться в этих фреймворках, я создал одно и то же веб-приложение на каждом из них. Приложение, которое я назвал «Look at Your Data», позволяет пользователям:

Загрузить CSV-файл для инициализации таблицы в базе данных SQLite Просмотреть таблицу в браузере Обновить отдельные поля в таблице Удалить отдельные строки из таблицы Скачать обновлённые данные таблицы в виде нового CSV-файла

Реализовав эти операции CRUD (Create, Read, Update, Delete) в каждом фреймворке, я надеюсь получить представление об уникальных особенностях каждого из них и соответствующем опыте разработки. Для простоты в качестве базы данных я буду использовать SQLite. В качестве отправной точки я начну с того, что мне хорошо знакомо — FastAPI.

Я провёл опросы по трём фреймворкам в Twitter и LinkedIn

FastAPI + Jinja + HTML + CSS + JavaScript

Создание приложения на FastAPI — достаточно простая задача (код). Ключевые компоненты:

main.py: Маршруты для загрузки/скачивания данных, обновления полей, удаления строк index.html: HTML-документ, определяющий скрипты, таблицу и кнопки. style.css: Визуальное оформление: ширина столбцов, перенос слов, прокрутка. script.js: Клиентская логика для загрузки CSV, отображения данных, обновления/удаления строк и скачивания обновлённых данных в формате CSV.

Вот как выглядит веб-приложение. Хотя с эстетической точки зрения оно не впечатляет, оно соответствует нашим требованиям, перечисленным выше. Я намеренно свёл визуальное оформление к минимуму (как для текущего, так и для последующих приложений), чтобы сосредоточиться на фреймворках и функциональности, а не на дизайне.

FastHTML

Для изучения FastHTML я начал с документации и создания простого ToDo-приложения по этому руководству. Для помощи с незнакомыми компонентами я использовал Cursor, подключая в качестве контекста ссылки на соответствующую документацию: ft-компоненты, htmx, pico.css. С FastHTML я смог реализовать всё приложение в одном файле main.py и небольшом style.css (код).

Вот как выглядит приложение.

После первой итерации Hamel любезно предложил совместное парное программирование, чтобы собрать приложение с нуля. Он также пригласил Jeremy Howard — создателя FastHTML — присоединиться к нам. Они показали мне несколько приёмов, например, как предоставить Cursor LLM-оптимизированную документацию для FastHTML (llms-ctx.txt) и FastLite (html.md). Они также поделились отличным ресурсом по созданию более простых приложений с htmx и Hyperview. Jeremy даже нашёл время продемонстрировать, как собрать приложение всего в 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()

А вот как выглядит приложение Jeremy:

Next.JS

Для изучения Next.js я прошёл туториалы React Foundations и Next.js. Второй обучает основам Next.js через компактные практические уроки, из которых шаг за шагом складывается приложение-дашборд. С 16 главами в туториале Next.js на изучение и написание кода может уйти немало времени. Тем не менее, рекомендую дойти как минимум до 12-й главы о трансформации данных (в туториале Next.js) — мне понравилась плавная кривая обучения и практические проекты.

Вот как я создал шаблон приложения на Next.js:

npx create-next-app@latest

Создание того же приложения на Next.js требует значительно больше кода по сравнению с Python-версиями (код). Тем не менее, его организация показалась мне интуитивной:

api: Маршруты для таблицы данных (GET, PUT, DELETE) и загрузки/скачивания файлов pages.tsx и layout.tsx: Компоненты пользовательского интерфейса для конкретной страницы и общие компоненты components: Переиспользуемые React-компоненты, такие как таблица и кнопки загрузки/скачивания lib: Утилитные функции; в данном случае — единственная функция для SQLite

А вот как выглядит веб-приложение. Встроенная интеграция с Tailwind CSS придаёт приложению чуть более отполированный вид по сравнению с аскетичными версиями на FastAPI и FastHTML.

SvelteKit

Для изучения Svelte я частично прошёл их туториал, включающий онлайн-интерпретатор. Туториал состоит из четырёх частей: (i) Основы Svelte, (ii) Продвинутый Svelte, (iii) Основы SvelteKit и (iv) Продвинутый SvelteKit. Я прошёл разделы по основам Svelte и основам SvelteKit и приступил к созданию приложения (код).

Для создания шаблона приложения SvelteKit я выполнил следующее:

npm create svelte@latest my-app

Как и у Next.js, шаблон SvelteKit содержит несколько каталогов и составных частей:

components: Переиспользуемые Svelte-компоненты, такие как таблица данных и кнопки загрузки api.ts и db.ts: Функции API для получения, обновления и удаления данных (api.ts), а также запросы и обновления базы данных SQLite (db.ts) routes: Маршруты для таблицы (GET), строк (PUT, DELETE) и загрузки/скачивания +page.svelte: Главная страница приложения app.html: Точка входа и основной HTML-файл

Вот как выглядит приложение. Небольшое отклонение: я поэкспериментировал с объединением функций «выбрать файл» и «загрузить» в одну кнопку, убрав тем самым отдельную кнопку «Upload CSV».

FastAPI + Svelte

Я также попробовал создать приложение с FastAPI в качестве бэкенда и Svelte для фронтенда (код). Вся функциональность и API располагались в main.py, а пользовательский интерфейс и взаимодействие с API обрабатывались файлами +page.svelte и api.ts соответственно. Для запуска приложения нужно было поднять оба сервера — FastAPI и Svelte.

А вот как выглядит веб-приложение. (Я вернул функцию загрузки к исходному варианту FastAPI-приложения с отдельной кнопкой «Upload CSV».)

Основная сложность заключалась в координации взаимодействия между двумя серверами в процессе разработки. В продакшен-среде приложение Svelte компилировалось бы и отдавалось статически, а API-запросы направлялись бы к бэкенду FastAPI.

• • •

Отступление: как ассистенты для написания кода повлияют на разработчиков?

Это упражнение заставило меня задуматься о том, как ассистенты для написания кода — основанные на LLM, обученных на данных из интернета — могут влиять на выбор, который мы делаем как разработчики. Например, будут ли LLM-ассистенты столь же эффективны с нишевыми или новыми фреймворками, такими как Svelte и FastHTML? Хотя приведённый ниже твит может быть преувеличением, он поднимает обоснованную проблему.

Мне не доставляет удовольствия это говорить, но Svelte мёртв, потому что базовые LLM-модели лучше пишут на React. — Jess Martin

Учитывая более широкое распространение и более долгую историю React и Next, скорее всего большинство LLM обучены на большем количестве кода React и Next, чем кода Svelte. То же касается и FastHTML. Это может приводить к тому, что ассистенты для написания кода будут эффективнее работать с устоявшимися фреймворками, такими как FastAPI, React и Next.js, и предлагать для них более качественный код.

Из личного опыта: мне было проще использовать Cursor + Claude для создания приложения на FastAPI и Next.js и сложнее — с FastHTML и SvelteKit. Поскольку FastHTML существует всего пару недель (на момент написания), его код и документация, вероятно, ещё не попали в обучающие данные большинства LLM, что объясняет их ограниченное владение FastHTML.

Чтобы решить эту проблему, Jeremy Howard (создатель FastHTML) подготовил файлы llms.txt и llms-ctx.txt, оптимизированные для обучения в контексте. Аналогично, Rich Harris (работающий над Svelte в Vercel) планирует публиковать более дружественную для LLM документацию по Svelte. Victor Dibia также писал о том, как ассистенты для написания кода могут влиять на привычки и предпочтения разработчиков и почему необходимо создавать документацию как для людей, так и для машин.

Время покажет, насколько эффективны эти усилия в решении проблемы холодного старта для новых или нишевых фреймворков в ассистентах для написания кода.

• • •

Это было увлекательное упражнение для знакомства с FastHTML, Next.js и SvelteKit. Весь код можно найти здесь. (Я новичок во фронтенде, так что простите за возможные ошибки!) Лично я с нетерпением жду возможности больше работать с TypeScript, который я активно не использовал с тех пор, как создавал ApplyingML.com несколько лет назад.

Какие ресурсы оказались вам полезны при изучении Next.js или Svelte? Пишите в комментариях или в личные сообщения!

Если этот материал оказался вам полезен, пожалуйста, цитируйте его следующим образом:

Yan, Ziyou. (Sep 2024). Building the Same App Using Various Web Frameworks. eugeneyan.com. https://eugeneyan.com/writing/web-frameworks/.

или

@article{yan2024frameworks, title = {Building the Same App Using Various Web Frameworks}, author = {Yan, Ziyou}, journal = {eugeneyan.com}, year = {2024}, month = {Sep}, url = {https://eugeneyan.com/writing/web-frameworks/} }



Присоединяйтесь к 11 800+ читателям, получающим обновления о машинном обучении, рекомендательных системах, LLM и инженерии.