当你把Vercel、SvelteKit和MongoDB Atlas结合起来时,你会得到什么?一个强大的无服务器优先的开发堆栈,可以大规模地扩展。
云计算继续朝着更高的抽象等级发展。自动部署和托管平台、前端框架和后端数据库越来越强大和复杂,而将它们整合起来比以往任何时候都容易。 本文向你展示了如何整合Vercel、SvelteKit和MongoDB以实现全栈无服务器开发。这些技术中的每一项都在自己的领域中领先。通过将它们结合起来使用,开发者可以用少量的工作实现令人印象深刻的能力。
一点一滴的比特示例应用程序
在这个演示中,我们将建立一个应用程序,创建一个存储在数据库中的双字段实体。 从用户的角度来看,该应用程序呈现出一个有两个字段的表单,一个字段是神谕,另一个字段是作者。(神谕是一个有点大小的智慧。)
我们在这里的重点是把这个强大的拼图的元素--Vercel、SvelteKit和MongoDB结合起来,把这个样本应用程序从开发到生产的整个过程。
首先,我们将使用SvelteKit在Svelte中构建一个前端视图。与Express.js类似,SvelteKit将端点视为请求-响应环境的抽象。
这种抽象将使其很容易部署到Vercel作为无服务器上下文。Vercel端点将简单地把收到的数据塞进MongoDB Atlas的一个集合中,这是一个云原生数据库的服务。
这样的设置可以满足我们的开发需求。 一旦我们有了前端,我们将在GitHub上创建一个仓库,并签入项目。 然后,我们可以使用Vercel拉入我们的项目,并将其部署到一个公开的IP上。
全堆栈开发SvelteKit
让我们从我们的开发环境SvelteKit开始。 你可以从SvelteKit的命令行启动一个Svelte应用程序,如该框架的文档中所述。 一旦应用程序在本地运行,你将能够访问它并看到SvelteKit的欢迎屏幕。
首先,让我们修改一下应用程序的主页面,使其包含一个简单的表单。编辑/src/routes/index.svelte ,修改内容见清单1。
清单1.修改应用程序的主页面(index.svelte)
<script context="module">
// export const prerender = true; Comment this out - this is now a dynamic page
</script>
<script>
import Counter from '$lib/Counter.svelte';
async function onSubmit(e) {
const formData = new FormData(e.target);
const data = {};
for (let field of formData) {
const [key, value] = field;
data[key] = value;
}
console.log("formData: " + formData);
const res = await fetch('/', {
method: 'POST',
body: JSON.stringify(data)
})
const json = await res.json()
result = JSON.stringify(json)
}
</script>
<svelte:head>
<title>Home</title>
</svelte:head>
<section>
<h1>
<!-- remains the same ... -->
</h1>
<form on:submit|preventDefault={onSubmit}>
<label for="apothegm">Apothegm</label>
<input type="text" name="apothegm" id="apothegm"/>
<label for="author">Author</label>
<input type="text" name="author" id="author"/>
<button type="submit">Submit</button>
</form>
<h2>
try editing <strong>src/routes/index.svelte</strong>
<!-- rest is the same ... -->
index.svelte 的大部分内容保持不变。注意,我注释了页面头部的模块导出,这样它就不再是预渲染的了。(SvelteKit的一个超能力是它能够完全预渲染那些不在后端的页面。我们必须禁用该功能,因为我们的页面会碰到后端)。
其余的改动都是为了提供一个有两个字段的表单元素。当表单被提交时,我们将把它整理成JSON,并通过POST将它通过fetch发送到根端点("/")。
处理POST功能
POST API调用将在后端由src/routes/index.js ,由任何以 "post "为名的函数来处理。现在让我们来看看。清单2显示了index.js 的正文。
清单2:index.js
import clientPromise from '../lib/mongo';
export async function post ({request}) {
const dbConnection = await clientPromise;
const db = dbConnection.db();
const collection = db.collection('apothegm');
let apothegm = await request.json();
const dbApothegm = await collection.insertOne(apothegm);
return { status: 200, body: { dbApothegm } }
}
在清单2中,我们首先看到的是对一个辅助库的导入,我们稍后会对其进行探讨。 接下来是post函数本身,它通过SvelteKit框架的重构来获取一个请求参数。 这个请求对象包含了我们处理HTTP请求所需的一切。
在我们的例子中,我们使用数据库助手打开一个数据库连接,得到一个指向 "apothegm "集合的指针,然后通过await request.json() 方法抓取前端正文的内容。
最后,该方法将请求主体放入数据库集合,并发回200的 "一切正常 "状态。
MongoDB连接器
现在,让我们看看清单3中所示的/src/lib/mongo.js 文件,我们用它来打入数据库。它主要是MongoDB文档中给出的典型帮助器,并稍作修改。还要注意的是,为了演示的目的,我选择将数据库的URL直接纳入文件中。**在现实生活中不要这样做!**这是一个明显的安全漏洞。在现实世界的应用中,你需要将URL外化为一个环境变量。
清单3.连接到MongoDB (mongo.js)
import dotenv from 'dotenv';
dotenv.config();
import { MongoClient } from 'mongodb';
//const uri = process.env['MONGODB_URI'];
// **Don’t do this in real life**:
const uri = "mongodb+srv://<username>:<password>@cluster0.foobar.mongodb.net/myFirstDatabase?retryWrites=true&w=majority";
const options = {
useUnifiedTopology: true,
useNewUrlParser: true,
}
let client
let clientPromise
if (!uri) {
throw new Error('Please add your Mongo URI to .env.local')
}
if (process.env['NODE_ENV'] === 'development') {
// In development mode, use a global variable
// so that the value is preserved across module reloads
// caused by HMR (Hot Module Replacement).
if (!global._mongoClientPromise) {
client = new MongoClient(uri, options)
global._mongoClientPromise = client.connect()
}
clientPromise = global._mongoClientPromise
} else {
// In production mode, it's best to
// not use a global variable.
client = new MongoClient(uri, options)
clientPromise = client.connect()
}
// Export a module-scoped MongoClient promise.
// By doing this in a separate module,
// the client can be shared across functions.
export default clientPromise;
这个帮助程序非常简单明了。最大的复杂性在于处理开发环境与生产环境的关系。 让我们继续设置数据库。
MongoDB Atlas 数据库作为一种服务
MongoDB是一个面向文档的数据库,是最早和最突出的NoSQL数据存储之一。 Atlas是MongoDB的管理云服务,或数据库即服务(DBaaS)。MongoDB Atlas让你访问MongoDB托管的数据库,并通过API使用它。
请注意,在接下来的步骤中,你需要设置一个免费的MongoDB Atlas账户。一旦你有了一个新的账户,你就会被带到仪表板,在那里你可以通过点击新项目按钮创建一个新的项目。
接下来,你会被要求为新项目命名,我把它叫做apothegm-foundry 。你还会有机会添加用户和权限,但你可以忽略这个提议,因为你是自动添加的。点击 "创建项目"来确认该项目。
添加一个数据库
一个项目就是一个数据库的桶。 现在,让我们通过点击建立数据库来添加一个数据库。 在这里,你会得到一个层次的选择。使用一个免费的、共享的数据库可以满足我们的目的。当你准备好了,点击创建。
接下来,你会得到一组关于云供应商和地区的选择。 你可以暂时接受默认值,但很高兴看到我们可以从亚马逊网络服务(AWS)、谷歌云平台(GCP)或微软Azure中选择。 点击创建集群。
接下来,你被邀请为数据库创建一个用户。 你可以创建一个用户名-密码组合或一个基于证书的用户。 为了方便起见,我们将采用用户名和密码。 选择一个你能记住的组合,然后点击创建用户。 这就是你将输入mongo.js 的用户名和密码。
现在,向下滚动到你想从哪里连接,你可以使用你的本地IP地址,但为了这个演示的目的,你可以直接输入0.0.0.0/0。同样,我们在这里保持简单,但你不会为一个真实世界的应用输入一个随机的IP地址。你需要输入实际的IP地址或IP地址范围。
在MongoDB Atlas主控台上,你可以通过点击数据库并点击连接按钮来找到你的连接字符串。 这样做会有一个弹出窗口,你可以选择与应用程序连接选项。 这个选项提供了一个类似这样的字符串。
mongodb+srv://<username>:<password>@cluster0.foobar.mongodb.net/myFirstDatabase?retryWrites=true&w=majority
添加你刚刚选择的用户名和密码,然后返回到mongo.js 文件,在那里添加字符串。 现在,当你在Svelte应用程序上使用该表格并点击提交,你应该能够进入MongoDB Atlas控制台,看到一个浏览集合按钮。
你应该看到一个反映你在表单中输入的内容的条目,类似于我在清单4中的内容。
清单4.MongoDB中的Apothegm条目
1. _id:6228f438e294d2c79754b64f
2. apothegm:"Form and emptiness are one"
3. author:"Unknown"
所以,开发环境已经工作了,接下来是部署。
部署应用程序 GitHub和Vercel
在用Vercel部署应用程序之前,我们需要在GitHub中创建一个源代码库。 你需要一个免费的GitHub账户。接下来,回到命令行,用你的应用程序代码填充仓库。(注意,SvelteKit启动器已经添加了一个.gitignore 文件。)一旦应用程序的源代码被检入主分支,你就可以访问Vercel了。
Vercel让你很容易注册一个免费的 "Hobby "账户。 我使用我的GitHub账户来访问Vercel的SSO(单点登录)。 一旦你有一个账户,按照步骤连接你的GitHub账户并授予Vercel权限。
你还需要在GitHub内部为特定的仓库或你托管代码的所有仓库授予Vercel的权限。 只要在你的账户资料上打开下拉菜单,点击设置,然后向下滚动到左侧的集成->应用选项并点击它。 现在,在主页面向下滚动到仓库访问部分。在那里,你可以授予Vercel对特定存储库(如图1所示)或所有存储库的访问权。
图1.通过 GitHub 授予 Vercel 的访问权。
接下来,进入Vercel并导入资源库。 注意Vercel是如何检测到该应用程序是一个SvelteKit应用程序的。它应该能无缝地导入和部署该应用程序。
现在,进入Vercel,你应该在仪表板上看到你的应用程序。 点击它,它将打开摘要,看起来应该类似于图2的屏幕。
图2.Vercel中的应用程序概述。
你可以点击并打开正在运行的应用程序的URL,如sveltekit-vercel-mongo.vercel.app。
如果你输入一个新的apothegm和作者,你应该能够使用MongoDB Atlas数据库集合视图重新加载控制台,并看到它反映在那里。 你的生产应用程序现在已经启动并针对数据库工作。
总结
这个堆栈有三个组件,它们都能很好地协同工作。Vercel在幕后做了很多工作,使生产部署得以实现。 在其他方面,注意它可以被配置为自动部署新的推送到主分支。
SvelteKit应用程序的后端部分被部署为无服务器函数,所以它的日志可以通过点击Deployments -> Functions获得。
显然,要将这个演示应用程序强化为你可以实际使用的东西,还需要做一些工作(举例来说,你会希望开发和生产使用不同的数据库)。有趣的是,你已经有了一个强大的全栈框架(SvelteKit)、部署管道(Vercel)和数据存储(MongoDB)。 而且整个事情运行在可以大规模扩展的基础设施上。

