如何在没有服务器的情况下为静态网站添加动态功能
静态网站目前正受到人们的青睐,这是有原因的。一个包含HTML、CSS和JavaScript文件的文件夹,加载速度很快,托管成本也很低,而且几乎不可能出现故障。 像 Astro 、 Eleventy 和 Hugo 这样的工具,能够利用Markdown文件和模板帮您生成这样的网站结构。而Netlify、Vercel以及Cloudflare Pages等托管服务,则可以通过内容分发网络来提供这些生成的网站内容,而且通常还是免费的。 不过,您的网站还需要具备实际的功能。读者可能想要留下评论,或者有人想通过电子邮件与您联系。也许您还想实时显示价格信息,需要用户登录后才能查看某些页面,或者在网站发布之前收
静态网站目前正受到人们的青睐,这是有原因的。一个包含HTML、CSS和JavaScript文件的文件夹,加载速度很快,托管成本也很低,而且几乎不可能出现故障。
像Astro、Eleventy和Hugo这样的工具,能够利用Markdown文件和模板帮您生成这样的网站结构。而Netlify、Vercel以及Cloudflare Pages等托管服务,则可以通过内容分发网络来提供这些生成的网站内容,而且通常还是免费的。
不过,您的网站还需要具备实际的功能。读者可能想要留下评论,或者有人想通过电子邮件与您联系。也许您还想实时显示价格信息,需要用户登录后才能查看某些页面,或者在网站发布之前收集用户的电子邮件地址。
大多数开发者在这种情况下都会选择使用后端技术。他们会搭建一个Express应用程序,添加数据库,并选择合适的托管方案。这样一来,他们就拥有了自己的服务器,而服务器是需要长期维护的。
不过好消息是,很多时候您其实并不需要这样的服务器。对于小型网站来说,大多数动态功能即便没有自己的服务器也能正常运行。因此,下面我们来探讨一下如何解决这些问题。
目录
静态并不意味着无法实现动态功能
“静态”这个词描述的是您的HTML代码是如何传输到浏览器的,而不是这些代码在浏览器中被执行后会发生什么。一个静态网站仍然可以运行您需要的所有JavaScript代码,它可以获取数据、重新生成页面内容、响应用户的点击操作,也可以与任何公共API进行交互。
但它有一件事是无法做到的,那就是在页面被发送给用户之前先运行您的代码。这意味着它无法隐藏某些信息、查询私有数据库,也无法根据请求者的身份来做出不同的处理。
正是这个限制决定了静态网站的设计方式。一旦您清楚地了解了这一点,剩下的问题就都很容易解决了:有些功能应该由浏览器本身来完成,有些则可以通过租用的服务来实现,而还有一些功能则需要在一个私密的环境中运行。
从浏览器已有的功能入手
在添加任何新的技术组件之前,请先了解当前所使用的平台——因为现代浏览器的功能远比我们大多数人所意识到的要强大得多。
fetch API可以用来从任何公共接口获取JSON数据。元素可以让您无需使用任何第三方库就能创建可交互的模态窗口,而元素则可以实现折叠式菜单的功能。如今,CSS已经能够处理固定标题、滚动动画以及容器查询等功能,而这些功能在过去都是需要借助JavaScript来实现的。
很多看似需要后端处理的功能,其实只需要进行一次数据获取请求,并使用模板字符串即可实现。天气插件、GitHub活动动态、货币转换器、实时比分显示工具,或是Mastodon的时间线功能:所有这些都可以通过浏览器顺利运行,因为相关数据都是公开的,而且调用这些接口也不需要任何密钥。只要编写好数据获取代码,妥善处理加载过程及可能出现的错误情况,问题就能迎刃而解。
处理表单提交
对于大多数静态网站来说,表单处理往往会成为第一个遇到的障碍,因为用户提交的表单数据必须被存储在访客无法看到的地方。你不能在客户端代码中存放数据库密码,也不能直接通过浏览器发送电子邮件。
幸运的是,这个问题已经被多次解决过了,大多数静态网站托管服务都会帮你处理表单相关事务。使用Netlify Forms时,只需要在表单标签中添加一个额外的属性即可。之后,Netlify会捕获每一份提交的表单数据,将其存储在控制面板中,并要么通过电子邮件通知你,要么触发Webhook接口。
不过有时候,你可能需要更多的功能。垃圾邮件过滤、文件上传、条件逻辑处理、多步骤流程设计、表单内集成支付功能,或者需要将数据直接导入电子表格……这些需求往往意味着你需要使用专门的工具来满足它们。通过查看这些优秀的表单构建工具,你可以对比各种选项,因为真正的区别在于这些工具所提供的逻辑处理能力、集成功能,以及你对自己编写的前端代码能拥有多少控制权。
无论如何,最终的选择还是取决于你是否愿意自己负责相关功能的实现。如果你自己编写表单处理的后端代码,那么你就能够完全掌控数据验证、请求速率限制、垃圾邮件过滤机制、数据存储方式、警报通知功能,以及符合GDPR规定的数据删除流程。不过,对于一个简单的联系表单来说,这样做未免有些大费周章。只有当表单成为你产品的重要组成部分时,才值得自己动手开发;而如果表单只是人们用来联系你的工具,那么租用现成的服务才是更合理的选择。
其余场景下的无服务器函数
迟早你会需要运行一些代码来处理某些特定任务——比如在数据发送给浏览器之前对其进行修改,或者隐藏API密钥。而无服务器函数正是为了解决这类问题而存在的,它们使你能够以最简单的方式让静态网站具备更多的动态功能。
你只需要将代码文件放入指定的文件夹中,托管服务就会在下次部署时将其转换成一个URL地址。这样的设置方式在Netlify Functions、Vercel Functions以及Cloudflare Pages Functions中都是通用的。代码量也会保持得很少:
export default async function handler(request) {
const res = await fetch("https://api.example.com/data", {
headers: { Authorization: `Bearer ${process.env.API_KEY}` },
});
const data = await res.json();
return Response.json({ total: data.items.length });
}
你的密钥存储在主机上的环境变量中,因此浏览器在调用 `/api/handler` 时根本看不到这个密钥。既不需要维护任何服务器,也不需要更新操作系统,更不会在平时产生任何费用。
对于任何需要使用凭证的功能来说,这种架构都是理想的选择。你可以利用它通过 Resend 或 Postmark 发送邮件,调用 AI 模型,验证 Webhook 签名,或者代理那些密钥否则会在一天内就被泄露的付费 API。
可租赁的数据库与登录服务
人们通常认为状态管理功能需要服务器来支持,但实际上并非如此。Supabase 通过 REST API 和行级安全机制来实现 Postgres 的状态管理。这些规则直接存储在数据库中,因此你可以通过浏览器进行查询而无需担心安全性问题。Firebase 采用不同的数据模型实现了类似的功能,而 Cloudflare D1 和 Turso 则在边缘节点提供了 SQLite 支持。
登录功能也遵循同样的模式。Clerk、Auth0 和 Supabase Auth 都通过客户端 SDK 来处理会话管理、密码重置、社交登录以及双因素认证等功能。认证机制的实现确实非常复杂,因此使用经过审计的服务来处理这些功能并不是偷懒,而是明智的风险管理措施。
评论、搜索与支付功能
对于最后这几类常见的功能,也有简单的解决方案。Giscus 只需要使用一个脚本标签,就能将 GitHub 的讨论区转换为评论框,而且完全不需要数据库。Pagefind 会在你的网站构建过程中生成搜索索引,并将其作为静态文件发布,因此运行时进行全文本搜索不会产生任何费用。
Stripe 可以处理所有的支付事务。通过 Payment Links 和 Checkout 功能,你可以使用简单的链接来销售商品,而 Stripe 会负责处理信用卡信息、税费以及开具收据等工作。你的网站根本不需要接触任何信用卡数据。
了解何时该升级系统
这种架构确实存在上限,你应该清楚这一点,而不是试图强行突破它。当出现以下情况时,你就应该考虑升级了:你的业务逻辑分散在六种不同的服务中;每月的 SaaS 费用已经超过了购买小型服务器的成本;系统的冷启动时间过长,影响了用户的体验;或者你需要执行耗时较长的任务、使用队列系统,或者需要保持连接数小时以上的socket。到了那个时候,使用传统的应用服务器会更加方便,所以应该及时进行升级。
在之前,这种架构确实能为你带来很多实际的好处。你的网站默认情况下就能保持较高的运行速度,安全风险也会降到最低,你可以将更多的精力投入到产品本身的开发中,而不是系统基础设施的维护上。先从浏览器开始使用这个架构,当需要使用密钥时再添加相应的功能,而对于那些复杂的部分,则可以选择租赁服务来使用。
希望你喜欢这篇文章。你可以通过 在 LinkedIn 上与我联系 。
相关文章
如何阻止人工智能代理生成尼日利亚的邮政编码
2026年10月1日,尼日利亚的邮政编码从六位数字改为由11个字符组成的代码,这种编码能够唯一标识某栋建筑,例如 EK-01-A03-FK-01 。 在此之前训练的语言模型仍然会自信地使用旧格式来处理邮政编码。这会影响两种类型的程序:一种是负责生成验证代码的编程程序,另一种是在运行时从客户信息中读取邮政编码或填写配送表格的程序。 本文将介绍如何解决这个问题。对于那些生成验证代码的程序,你需要检测它们目前生成的代码是否存在错误,并为它们提供相应的规则来纠正这些错误;而对于在运行时处理邮政编码的程序,则需要为它们设定明确的边界:当模型提出一个邮政编码时,由特定的程序来判断该编码是否符合规范、是否已
阅读全文
如何将应用程序从AWS迁移到GKE [完整指南]
这个指导性实验将带你了解如何迁移一个小型支付应用。该应用包含使用React开发的用户界面以及运行在AWS EC2实例上的Express API,而数据库则仍保存在AWS上。 你需要将用户界面和API迁移到Google Kubernetes Engine上,但无需更改客户目前使用的公共URL地址,而是逐步将流量从AWS转移至GKE,每次转移的比例为几百分比。 完成整个迁移过程后,你将能够在本地运行该应用,在AWS上搭建基础设施,通过八个Terraform步骤在GKE上构建环境,测试新环境是否正常工作,然后将生产环境的流量全部转移到GKE上,完成切换流程,并拆除不再需要的资源。 下图展示了迁移过程
阅读全文
如何使用 GitHub Actions、Ingress 以及自动 TLS 功能,在 GKE 上搭建临时性的 PR 预览环境
每一个发布软件的团队最终都会搭建一个测试环境。而每一个搭建了测试环境的团队,最终都会遇到同样的问题。 测试环境是共享的。一个环境,却有大量的拉取请求。有人会部署一个尚未完成的功能来进行测试,其他人会在其基础上继续进行开发,还有第三个人会执行数据库迁移操作。到了周四下午,就没人能弄清楚到底哪个分支的哪个版本正在运行中,“在测试环境中可以正常使用”这句话已经完全失去了任何参考意义。 常见的解决办法包括:创建一个Slack频道,让大家把测试环境当作会议室来使用;制定轮换部署计划;或者再搭建第二个、甚至第三个测试环境,但每个测试环境的配置都会与生产环境越来越偏离。 其实有更好的解决方案。像Vercel
阅读全文
如何在数据传输流程中对个人身份信息进行加密,同时确保这些信息仍可被检索到
在Intuit,我的团队构建了一个数据处理流程,用于处理TurboTax电子申报系统中产生的数据。这些数据需要被用于制作仪表板、进行分析,以及满足其他后续使用需求。 其中最大的挑战之一就是如何保护那些属于 个人身份信息 的数据,比如社会安全号码。这类信息具有极高的敏感性,因此在数据处理的每一个环节都必须得到妥善保护。与此同时,分析团队有时也需要进行一些正常的业务操作,例如识别与特定客户相关的记录,或者进行精确匹配查询。 那么,如何在保证这些敏感信息不被泄露的同时,允许人们对这些数据进行受控的搜索呢?在本文中,我将解释解决这一问题所涉及的加密技术原理,包括以下内容: 概率加密与确定性加密 对加密
阅读全文