
Jamstack是一种现代架构,用于创建关注性能和开发人员体验的网站。它可以用于从个人静态博客到大型企业动态店面的任何内容。的果酱在Jamstack中代表JavaScript、API和标记。不同的是,静态标记由JavaScript转换,并在构建时和运行时利用第三方API。Jamstack的全面定义和历史可以在这里找到在这里。
尽管经常与静态站点生成器相关联,但Jamstack站点并不需要保留静态的。在仅使用预渲染标记还不够的情况下,可以在客户端逐步加载动态内容。在线店面可能会静态地为其目录中的所有产品生成清单,然后在页面首次呈现后更新库存或价格等详细信息。Web组件非常适合这种工作流程,因为它们允许在静态HTML中添加交互区域。
让我们将用户生成的评论添加到带有web组件的Jamstack站点钢网,利用Supabase存储动态数据。Supabase是Firebase的开源替代品,它提供了一个接口和API,使数据库CRUD操作(创建、读取、更新和删除)无需编写后端代码即可实现。我一直在我的个人项目中广泛使用它,我认为将它与Stencil的web组件相结合是一个很好的创作方式micro-frontends:动态的、独立的、包含的小部件,可以放在大型项目中的任何位置(无论是SPA还是静态HTML文件)。
这里是我们将创建的最终组件的预览:
完整的源代码也可以在GitHub。
使用
当我构建一个组件时,我喜欢从编写一个最终用法的示例开始。对于我们的comments组件,我希望它具有一个非常低配置的API:使用该组件所需要的只是一个惟一的ID、到后端的URL和Supabase的访问令牌。
<我的意见id = "…" supabase-url = "…" supabase-key =“……”> < /我的意见>
模板实现
让我们脚手架出一个Stencil组件NPM运行generate my-comments
在一个新的模板项目。这将为我们设置一个样板,我们可以向其添加公共属性@Prop
装饰器和内部状态@State
装饰。有关道具和状态的更深入介绍,请查看模板文档.
{tag: 'my-comments', styleUrl: 'my-comments.css', shadow: true,})导出类MyComments {/** * ' id '不需要Prop,因为它是一个全局HTML属性。相反,我们可以使用@Element装饰器从HTML元素中获取它。* / @Element()元素;/** *到Supabase后端的公共URL。*/ @Prop() supabaseUrl: string;/** * Supabase后端的公共访问令牌。*/ @Prop() supabaseKey: string;/** *与该块的' id '相关的注释。*/ @State()注释:MyComment[] = [];/** *新注释文本输入的值。 */ @State() newCommentValue: string; /** * Supabase client to be initialized with `supabaseUrl` and `supabaseKey`. * We will import this type when we install Supabase. */ private supabase: SupabaseClient; render() { //... } }
的this.comments
数组将保存从Supabase后端加载的注释数据。让我们定义一个MyComment
类型,这样我们就可以利用TypeScript内置的Stencil支持。
type MyComment ={/* *撰写评论的作者id。* / author_id:字符串;/* *注释的主体。* /内容:字符串;/* *评论第一次发布的日期时间。* / created_at:字符串;/* *创建此注释的组件的' id '。例如,将创建和检索带有“location_id”为“blog-post-1”的评论。* / location_id:字符串;/* *注释的唯一id,由Supabase生成。 */ id: string; }
呈现一个模板
现在我们准备好考虑我们需要渲染给用户什么:
-当前评论的列表。
-用于添加新注释的输入字段。
在构建具有多个活动部件的Stencil组件时,我发现将语义不同的模板分离为多个渲染函数或功能组件很有帮助。
的renderComment
Helper函数将用于呈现单个注释的标记。为了确保注释是可访问的,让我们将它写成HTML文章元素与咏叹调评论角色.
private renderComment(comment: MyComment) {return ( {评论。author_id} < / h1 > < /头> < p >{发表评论。content}
现在在我们的渲染
我们可以调用函数renderComment
中的每一项this.comments
状态变量:
render() {return ( Comments
{this.comments.map(comment => this.renderComment(comment))} );}
我们需要向模板添加的最后一件事是用户添加新注释的方法。让我们添加一个带有提交按钮和文本输入的小表单来更新newCommentValue
.
render() {return ( Comments
{this.comments.map(comment => renderComment(comment))} ); }
处理输入
在上面的表单模板中,我们引用了两个要实现的处理用户输入的方法。在handleChange
方法将输入元素的当前值存储到组件状态中。的handleSubmit
方法将在下一节中实现。
private handleChange(ev:事件){const目标= ev。currentTarget HTMLInputElement;这一点。newCommentValue = target.value;} private handleSubmit(ev: Event) {// TODO}
设置Supabase
现在我们设置了一个shell来显示我们的注释,设置了道具和状态来保存我们的数据。让我们配置Supabase来保存注释数据,并将其连接到组件的生命周期事件。
在注册一个帐户并创建一个新项目之后,配置Supabase以与我们的前端工作只需要几个步骤。
创建一个表来存储注释
在Supabase侧栏中,转到侧栏中的“Tables”页,然后选择新
按钮。让我们创建一个包含匹配我们的字段的表MyComment
上述类型。每个字段将是表中的一列,每一行将表示一个注释。
获取Supabase URL和Key
在Supabase侧栏中,转到侧栏中的“Settings”页面,继续转到“API”子页面。在这里,Supabase揭示了我们需要的两样东西:
-“anon”键是客户端api键,它允许我们的前端连接到Supabase。公开分享这把钥匙是安全的。
-配置URL是我们Supabase项目的公共REST端点。
这些值对应于supabaseUrl
而且supabaseKey
添加到组件中的道具。
.
本教程不介绍如何设置身份验证。Supabase有这样做的教程在这里。为了防止无限制的CRUD访问数据库,必须设置适当的身份验证。
连接Supabase到Stencil
我们需要组件以三种方式与Supabase交互:
-第一次加载时从数据库读取注释
-每当数据库更新时加载新的注释
-当用户按下提交按钮时提交一个新的评论
与我们在上一节中添加多个呈现帮助函数类似,当我创建一个组件时,我喜欢将这些逻辑任务也分离到它们自己的帮助函数中。
初始化Supabase
当我们的组件第一次加载时,我们还需要加载Supabase客户机并连接到它。
让我们将Supabase客户端作为依赖项添加到项目中npm我@supabase / supabase-js
.安装之后,我们可以通过组件文件顶部的以下import语句获得所需的引用。
import {createClient, SupabaseClient} from '@supabase/supabase-js';
现在,在componentWillLoad
生命周期函数中,我们可以使用提供给组件的适当道具来初始化Supabase。
{这个componentWillLoad()。supabase = createClient(这一点。supabaseUrl, this.supabaseKey); }
从数据库中读取注释
Supabase允许链接函数调用,从表中获取数据,过滤无关数据,并对返回的条目进行排序。
private async getComments() {const {data} =等待这个。supabase //从'comments'表中抓取数据. .from('comments') .select() //只抓取与该组件的' id'相关的数据. .eq('location_id', this.element.id) //对数据进行排序,使新的注释位于列表的顶部. . Order ('created_at', {ascending: false});//将响应存储在' comments '状态变量中this.comments =数据;}
我们希望在第一次加载组件时加载状态,因此可以调用getComments
在componentWillLoad
生命周期的功能。
componentWillLoad () {this.getComments ();}
来自数据库的实时更新
如果新的评论能自动显示在我们的评论列表中,那就太好了。Supabase也提供了一种实现这一点的方法。
private async watchComments(){等待这个。supabase //只观察与组件id匹配的更新。from(' comments:location_id=eq.${this.element.id} ') //当注释被插入到表中时,更新组件状态. .on('INSERT', payload =>{this.comments =[有效载荷。新,……this.comments);}}) .subscribe ()
这也可以添加到componentWillLoad
生命周期的功能。
componentWillLoad () {this.getComments ();this.watchComments ();}
向数据库添加新的注释
我们需要的最后一个功能是添加新注释的能力。
private async addComment() {const {data, error} =等待这个。Supabase .from('comments') .insert([{内容:此。newCommentValue, author: 'Author Name', // Dummy value. (To be implemented when auth is added.) location_id: this.element.id // Supabase will automatically generate `id` and `created_at` } ]); return data; }
现在,我们得打电话了addComment
每当提交组件模板中的表单时。我们把它加到handleSubmit
函数。
private handleSubmit(ev: Event){//阻止默认的事件行为来阻止页面刷新。ev.preventDefault ();this.addComment ();}
添加样式
最后,让我们通过添加一些样式使组件看起来更好一些。我已经添加了以下CSSmy-comments.css
中引用的@ component
装饰。
:主机{显示:块;字体类型:无衬线;}文章[role="comment"] {margin-top: 1rem;填充:1快速眼动;边框:2px纯黑色;border - radius: .5rem;盒影:黑色5px 5px;}形式{显示:flex;flex-direction:列;}形式textarea{宽度:100%; border-radius: 5px; border: 2px solid lightgray; resize: vertical; padding: .5rem; box-sizing: border-box; } form input[type="submit"] { background-color: black; color: white; border: none; border-radius: 5px; text-align: start; max-width: min-content; margin-top: .5rem; padding: .5rem; }
结束
在组件准备好供公众使用之前,本教程中没有涉及的一些内容是必要的,比如添加身份验证和一些内容审核功能。但是,当我们准备好了,我们将组件发布到NPM,我们将有一个强大的微前端,包装在一个Stencil web组件,并准备投入到任何Jamstack网站与零额外配置。
这是web标准Stencil web组件与Jamstack的自然协同作用之一。所需要的只是一个脚本标记,您的组件就可以被使用了。此外,该组件可以使用Stencil的内置组件构建到Angular、React或Vue组件中框架的集成。就我个人而言,我等不及要扩展这个启动器并添加它我的Jamstack博客建立与11泰.如果你喜欢本教程,请在下方留言,如果你想看更多内容!
伟大的文章Will,这正是我需要让自己开始开发Stencil组件。
但有一个问题,我经常看到一些文章说Supabase是“Firebase的开源替代品”,这是他们正在推广的东西吗?Firebase有NoSQL数据库,而Supabase有SQL -在我看来不是一个真正的选择?
作为AceBase的开发者,它是“Firebase的开源替代品”,所以公平地说我很有偏见,但AceBase确实是Firebase的替代品,因为它是NoSQL,基本上使用相同的编程语法——你可以使用你现有的Firebase代码,它将与AceBase一起工作。一开始我很犹豫要不要回复,但是我想借这个机会告诉你,你可能会喜欢它!它可以作为一个托管db服务器,独立的db,甚至在浏览器中离线支持和同步功能。所有的代码都可以通过npm和github免费获得。
再次感谢,周末愉快!
Ewout