微信扫码
与创始人交个朋友
我要投稿
最近,我一直在思考是否应该从我当前的 Web 应用栈(FastAPI、HTML、CSS 和少量 JavaScript)迁移到现代 Web 框架。
我特别对 FastHTML、Next.js 和 Svelte 感兴趣。
为了深入了解这些框架,我使用每个框架构建了同一个 Web 应用。我称之为“查看你的数据”,它允许用户:
通过在每个框架中实现这些 CRUD[9](创建、读取、更新、删除)操作,我希望了解每个框架的独特特性和开发体验。为简化起见,我将使用 SQLite 作为数据库。作为基准,我将从我熟悉的 FastAPI 开始构建应用。
我在 Twitter[10] 和 LinkedIn[11] 上对这三个框架进行了投票。
使用 FastAPI 构建应用相当直接(代码[12])。主要组件包括:
main.py
:处理上传/下载数据、更新字段、删除行的路由。index.html
:定义脚本、表格和按钮的 HTML 文档。style.css
:视觉样式设置,如列宽、文本换行、滚动等。script.js
:客户端功能,包括上传 CSV、加载和显示数据、更新/删除行,以及下载更新后的数据为 CSV。以下是该 Web 应用的界面。虽然在美观度上不算出色,但它满足了我们的功能需求。为了专注于框架和功能,而非设计,我特意在当前和后续的应用中保持了最简化的视觉样式。
为了学习 FastHTML,我首先查阅了文档[13],并通过这个示例[14]构建了一个简单的 ToDo 应用[15]。对于不熟悉的组件,我向 Cursor 提供了相关文档的链接,如 ft components[16]、htmx[17]、pico.css[18] 作为参考。使用 FastHTML,我可以在一个 main.py
和一个小的 style.css
中实现整个应用(代码[19])。
以下是应用界面。
在我完成初版后,Hamel 热心地与我进行结对编程,从头开始构建应用。他还邀请了 FastHTML 的创造者 Jeremy Howard 加入。他们教了我一些技巧,例如为 Cursor 提供 LLM 友好的 FastHTML(llms-ctx.txt[20])和 FastLite(html.md[21])文档。他们还分享了一个关于使用 htmx 和 Hyperview 构建简单应用的优秀资源[22]。Jeremy 甚至展示了如何在仅 50 行代码[23]内构建该应用!
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,我完成了 React 基础[24]和 Next.js[25] 教程。后者通过循序渐进的实践课程教授 Next.js 的基础知识,最终构建一个仪表盘应用。教程共有 16 章,可能需要一些时间来学习和编码。然而,我建议至少学习到第 12 章关于数据转换的部分,并享受平稳的学习曲线和实用的项目。
创建 Next.js 应用模板的方法:
npx create-next-app@latest
在 Next.js 中构建相同的应用需要更多的代码(代码[26]),但其组织结构相当直观:
api
:处理数据表(GET、PUT、DELETE)和文件上传/下载的路由。pages.tsx
和 layout.tsx
:特定页面和通用的用户界面组件。components
:可重用的 React 组件,如表格和上传/下载按钮。lib
:实用函数;在本例中,包含一个用于 SQLite 的函数。以下是 Web 应用界面。内置的 Tailwind CSS[27] 集成使应用看起来比简约的 FastAPI 和 FastHTML 应用更为精致。
为了学习 Svelte,我完成了其在线教程[28]的一部分。教程分为四部分:(i)Svelte 基础、(ii)Svelte 高级、(iii)SvelteKit 基础和(iv)SvelteKit 高级。我完成了 Svelte 基础和 SvelteKit 基础部分,然后开始构建应用(代码[29])。
创建 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 文件。以下是应用界面。我稍作调整,将“选择文件”和“上传”功能合并到一个按钮中,去除了“上传 CSV”按钮。
我还尝试了使用 FastAPI 作为后端、Svelte 作为前端构建应用(代码[30])。所有功能和 API 都在 main.py
中,而前端 UI 和 API 交互由 +page.svelte
和 api.ts
处理。要运行应用,我需要同时启动 FastAPI 服务器和 Svelte 开发服务器。
以下是 Web 应用界面。(我将上传功能恢复到原始的 FastAPI 应用,即有一个单独的“上传 CSV”按钮。)
主要挑战是在开发过程中协调两个服务器的通信。在生产环境中,Svelte 应用将被编译为静态文件,API 请求将发送到 FastAPI 后端。
这个练习让我思考,基于互联网数据训练的 LLM 提供的编码助手将如何影响我们的开发选择。例如,对于像 Svelte 和 FastHTML 这样的小众或新兴框架,LLM 驱动的编码助手在编写和建议代码时是否同样有效?下面的推文或许有些夸张,但确实提出了一个值得关注的问题。
我并不乐意地说,但 Svelte 已经过时了,因为 LLM 基础模型更擅长编写 React。——Jess Martin[31]
由于 React 和 Next 的广泛使用和较长历史,大多数 LLM 的训练数据中可能包含更多的 React 和 Next 代码,Svelte 的代码则相对较少。FastHTML 也是如此。这可能导致编码助手在处理和建议已成熟的框架(如 FastAPI、React 和 Next.js)时更为高效。
根据我的经验,在使用 Cursor + Claude 构建 FastAPI 和 Next.js 应用时更为顺利,而在 FastHTML 和 SvelteKit 上则遇到了更多困难。由于 FastHTML 在撰写本文时仅存在几周,其代码和文档可能尚未进入大多数 LLM 的训练数据中,这解释了它们在 FastHTML 上的有限能力。
为了解决这个问题,FastHTML 的创建者 Jeremy Howard 提供了针对上下文学习优化的 llms.txt[32] 和 llms-ctx.txt[33]。同样,Rich Harris(在 Vercel 负责 Svelte 开发)计划[34]为 Svelte 发布更多 LLM 友好的文档。Victor Dibia 也撰文[35]讨论了编码助手可能如何影响开发者的习惯和选择,以及我们需要为人类和机器编写文档。
时间将证明这些努力在解决新兴或小众框架在编码助手中的冷启动问题上能取得多大成效。
53AI,企业落地应用大模型首选服务商
产品:大模型应用平台+智能体定制开发+落地咨询服务
承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业
2024-07-11
2024-07-11
2024-07-09
2024-09-18
2024-06-11
2024-07-23
2024-07-20
2024-07-12
2024-07-26
2024-07-23
2024-11-18
2024-11-16
2024-11-16
2024-10-31
2024-10-31
2024-10-27
2024-10-26
2024-10-25