介绍
期望什么
在这篇博客文章中,我将解释如何使用两种不同的技术创建用于学习意大利短语的Phrase Tutor应用程序。我将共享一些代码片段,以显示使用WASP和Supabase构建应用所需的内容。
作为一名高级全栈开发人员,在构建许多侧项目方面具有经验,我更喜欢一个快速的开发周期。我喜欢在短短几天甚至几个小时内将想法变成POC。
我们将研究每种技术在构建全栈应用程序以及Wasp和Supabase excel时如何提供帮助。
我想快速学习意大利语
每当我出国旅行时,我都喜欢想象住在那个地方的感觉。例如,我通常不喜欢进行拥挤的公共交通工具,但是由于某种原因,当我在国外做时,它会给我带来欢乐。这就是我住在那儿的感觉。对于我来说,充分体验文化的最重要的事情之一就是学习语言,或者至少能够一直不说英语。
我和我的女朋友计划去意大利旅行,我想学习一些意大利语。我想到的是,最少的努力将是最简单的学习方法。我认为学习前100条意大利语短语将是一个好的开始。我有一个星期要做,如果我每天练习,学习100句话似乎是可行的。
学习方法
在高中时,我有一个学习历史事实和日期的系统,迅速称为“专注于您不知道的事物”。
这是其工作原理:
- 收集您想学习的事实库(例如,第二次世界大战何时开始?” - “ 1914”)。
- 问自己在游泳池中的每个问题。
- 如果您知道答案,请从池中删除事实。
- 如果您不知道答案,请将其放在池中。
- 重复较小的池直到没有更多的事实。
我为此制作了一个小应用程序,并与我的同学共享了一个小应用程序,但并没有走得更远。
现在,我想使用相同的方法来学习旅行的意大利短语。因此,作为一个更好的开发人员,我将制作一个适当的应用程序并在某个地方托管它ð
构建短语导师应用程序
我们将创建一个遵循上述方法的应用程序。该应用程序将向您显示一个短语,如果您选择“我知道”或“我不知道”,则可以告诉您是否知道翻译。
该应用程序将跟踪您的答案,并建议您要学习哪些短语
我两次构建了该应用程序:首先使用supabase,然后是黄蜂。 Supabase是一款全面的开源后端作为服务(BAA)产品,可在您的前端应用中增加超级大国。另一方面,黄蜂是一个开源框架,用于构建有助于保持样板较低的全栈应用程序。让我们看看它们如何比较。
初始supabase版本
制作初始版本时,我与vue.js合作,我用来创建第一个版本的Thrase Tutor应用程序。我首先收集一些短语。我在Google上搜索了“最佳的意大利短语要学习”,并遇到了一篇名为“ 100个意大利语的文字”的文章。 (从HTML提取短语后,我发现只有96个短语,但这对我来说仍然足够好。)
初始应用程序包含前端加载的JSON file中的短语。这完全是静态的,但起作用。
{
"id": 1,
"group": "general",
"translations": {
"en": "Yes",
"it": "Si"
}
}
我将其放在Cloudflare页面上,然后上线。
我向我的女朋友展示了它,但她不喜欢我使用的一些短语。如果我有一个数据库的后端来编辑短语。然后我有了一个想法:让我们添加一个数据库,然后使用Supabase。
supabase是一种托管的后端解决方案,提供了许多免费的东西:PostgreSQL数据库和社交认证等。
我使用非常简单的supabase UI设置数据库表。
我需要的桌子只有几个字段:
CREATE TABLE phrases (
id bigint NOT NULL,
group character varying NULL,
translations_en text NOT NULL,
translations_it text NOT NULL
);
然后,我必须用一些SQL播种数据库。使用supabase s ui,执行SQL语句很容易。您只需登录,打开SQL编辑器并在代码中粘贴:
INSERT INTO phrases(id,"group",translations_en,translations_it) VALUES (1,'general','Yes','Si');
INSERT INTO phrases(id,"group",translations_en,translations_it) VALUES (2,'general','No','No');
...
使用其Javascript SDK将Supabase集成到我现有的前端应用程序中很简单。如果您熟悉Firebase,那应该感觉相似。本质上,您可以在前端构建SQL查询,并在应用程序中使用所得数据。
使用SDK感觉很简单,我可以在没有太多麻烦的情况下从数据库中得到想要的东西。
const { data, error } = await supabase.from("phrases").select("*");
和那样,我的static vue.js应用程序具有一个数据库来依靠ð
使用Google添加登录名是在Supabase UI中启用它并设置客户端ID和客户端秘密变量的问题。为了使用Google触发登录过程,我依靠其JavaScript SDK依靠。
supabase.auth.signInWithOAuth({ provider: "google" });
真棒!我很高兴现在可以编辑短语,并且有一个我计划以后使用的登录功能。
将来,我计划在应用程序中添加更多语言,还允许注册用户贡献新的短语和翻译。我相信这将使该应用程序对语言学习者更有用。
和那样,我的应用程序从纯静态应用程序转移到带有数据库的应用程序和Google登录ðÖ
查看使用vue.js和supabase编写的已部署应用程序:https://phrase-tutor.pages.dev
查看源here
加入黄蜂和狗食
第二部分之前的一些背景:我今年早些时候开始在黄蜂工作。我真的很高兴能解决一种解决我关心的问题的技术:当我进行侧面项目时,我不喜欢每次从头开始写相同的乏味部分。我从以前的附带项目中复制和粘贴,但最终,代码片段变得旧且过时。
自然,我想通过重写我的一个项目来测试黄蜂。我决定看看黄蜂如何与短语导师项目一起使用。
WASP通过拥有一个易于理解的配置文件来工作,该文件称为main.wasp
,该文件可以协调您的客户端和服务器功能。它的主要目的是使您富有成效,并专注于编写有趣的部分。感觉很像使用涵盖您整个应用的网络框架。
让我们从创建数据模型开始。黄蜂在引擎盖下使用Prisma与您的数据库进行通信,这使得在不担心详细信息的情况下可以轻松管理数据库。这只是框架为我做出的众多选择之一,我感谢使用有效的设置的感觉。
我必须首先声明WASP配置文件中Prisma PSL所需的所有实体。
entity Phrase {=psl
id Int @id @default(autoincrement())
group String
phrase String
translations Translation[]
psl=}
entity Language {=psl
id Int @id @default(autoincrement())
name String @unique
emoji String
translations Translation[]
psl=}
entity Translation {=psl
id Int @id @default(autoincrement())
phraseId Int
languageId Int
translation String
phrase Phrase @relation(fields: [phraseId], references: [id], onDelete: Cascade)
language Language @relation(fields: [languageId], references: [id], onDelete: Cascade)
psl=}
我再次使用PostgreSQL数据库,您可以看到字段定义相似。
我通过定义三个表而不是一张表,从而提高了数据架构。我将Phrase
的概念与Language
和Translation
的概念分开。这将使将来添加新语言变得更容易。
我使用prisma和Wasp action添加了一些短语:
export async function seedItalianPhrases(args, context) {
const data = [
{
id: 1,
group: "general",
translations_en: "Yes",
translations_it: "Si"
},
...
]
for (const phrase of seedPhrases) {
await context.entities.Phrase.create({
...
});
}
}
现在,让我们看一下我需要做的事情来使数据从后端流到我的React应用程序。
首先,我在WASP配置文件中声明了一个查询:
app phraseTutor {
...
}
...
query fetchAllPhrases {
fn: import { getAllPhrases } from "@server/queries.js",
entities: [Phrase]
}
然后,我为后端编写了代码以获取短语。您会注意到这与我为使用Supabase SDK获取短语的代码非常相似,但是我必须包括translations
关系,因为我们现在有多个表。
// My query got the Prisma entity through the context parameter
// which I just used to fetch all the phrases
export async function getAllPhrases(args, context) {
return context.entities.Phrase.findMany({
include: {
translations: true
}
});
}
最后,我可以将查询导入我的React应用程序。它以一种自动处理缓存无效的方式进行设置,少要担心的一件事,这是很棒的ð
// Wasp relies on React Query in the background
const { data: phrases, isLoading } = useQuery(fetchAllPhrases);
让我们还为我们的应用程序增加了对Google Auth的支持。它涉及在WASP文件中声明您想要它,添加一些ENV变量并在React应用程序中使用。
我们通过在auth
下添加google
键来将其声明为WASP文件:
app phraseTutor {
...
auth: {
userEntity: User,
externalAuthEntity: SocialUser,
methods: {
// Define we want the Google auth
google: {
// Optionally, we can adjust what is saved from the user's data
getUserFieldsFn: import { getUserFields } from "@server/auth/google.js"
}
},
onAuthFailedRedirectTo: "/"
},
...
}
// Some of the entities needed for auth
entity User {=psl
id Int @id @default(autoincrement())
username String @unique
password String
profilePicture String
externalAuthAssociations SocialUser[]
createdAt DateTime @default(now())
psl=}
entity SocialUser {=psl
id Int @id @default(autoincrement())
provider String
providerId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int
createdAt DateTime @default(now())
@@unique([provider, providerId, userId])
psl=}
和 - 这样。现在,我们可以在我们的前端使用Google Authð
import { signInUrl as googleSignInUrl } from "@wasp/auth/helpers/Google";
...
const { data: user } = useAuth();
用黄蜂写一个全栈React and Express.js,感觉就像是一次有指导的经历。我不必过分专注于开发工具,构建或部署。
相反,我可以专注于短语导师工作所需的逻辑,并且大多数时候只运行wasp start
。我确实需要编写一些额外的代码以使所有内容运行,但是我可以随意自定义此代码。
查看使用WASP构建的已部署项目:https://phrasetutor.com
查看源here
让我们比较一些功能
我想比较supabase和WASP的特征。思考做事及其优点和缺点的不同方式是一件好事。
功能 | supabase | wasp |
---|---|---|
从API | 获取数据使用supabase JS SDK查询数据库表 | 在WASP配置中声明查询,并使用Prisma JS SDK实现 |
自定义业务逻辑 | 编写自定义PostgreSQL过程或通过编写Edge功能 | 在WASP文件中声明操作并写入服务器端JS |
定义数据库架构 | 可视编辑器或通过创建表查询 | 代码 - 编辑Prisma架构并提交更改 |
auth | 在UI | 中启用在WASP文件中启用它 |
部署 | supabase托管实例或自我主持人 | 部署任何地方,支持https://fly.io一行部署 |
使用supabase,我喜欢SDK感觉的熟悉程度,并且他们的UI使配置后端的一部分变得容易。我不需要考虑部署Supabase,因为我使用了他们的托管版本,但是在免费层次上不活动1周后,它确实暂停了。
另一方面,WASP感觉就像是我的React + Express.js + Prisma应用程序的胶水,我需要编写更多代码来完成工作。感觉更加明确,因为我将代码更接近我通常写的内容。我用wasp命令wasp deploy fly launch
将其部署到fly.io,现在它在https://phrasetutor.com
结论
都是关于用例
为您的需求选择正确的解决方案可能很困难。这就是为什么重要的是尝试不同的选择并查看它们如何为您服务。在这种情况下,我比较了两个选项:supabase和Wasp。
supabase是一个不错的选择,如果您想要全面的开源BAAS产品,从而为您的前端应用增添了超级大国。它提供了很多免费的东西,例如PostgreSQL数据库和社交认证,这可以使开发更加轻松,更快。它还具有一个不错的SDK和UI,最终用户可以用来轻松定义其应用程序的配置。
WASP是用于构建全堆栈应用程序的开源框架,可帮助保持较低的样板。关于某些事情,例如定义您的身份实体,这更明确,但是当您拥有更高级用例时,这可能是一个加号。通过将黄蜂作为全堆栈应用程序的胶水,您可以拥有两全其美的最好的:开箱即用的开发和生产设置,同时仍允许您以自己喜欢的方式开发应用程序。
在短语导师的情况下,我喜欢使用Supabase和Wasp。但是,我确实与使用这两种技术有不同的感觉。有了Supabase,我觉得我的前端应用程序获得了即时的超级大国,现在它具有数据库和登录名,考虑到我必须付出的努力,这真是太好了。但是现在我有了一个黑盒依赖性,需要构建。
当我使用WASP重建短语辅导员时,感觉会有所不同,因为它是一个全栈应用程序。我对应用程序代码有了更多的控制权,因此我可以更改它并按照自己的意愿进行发展。我觉得我已经构建了一个可以朝任何方向增长的应用程序。尽管我不得不编写更多代码,但感觉就像未来需求的良好权衡。
要确定哪种选项最适合您,我建议您同时尝试并了解自己的感受。很容易设置这两个工具,看看它们是否对您有意义。
如果您尝试使用短语Tutor应用程序,请让我知道您的想法。您可以在Twitter上与我联系。我一直在寻找使它变得更好的方法。