使用 Gatsby 函数构建 API
已发表: 2022-03-10您可能听说过无服务器函数,但如果您没有听说过,无服务器函数提供通常与服务器端技术相关的功能,这些功能可以与前端代码一起实现,而不会被服务器端基础设施所束缚。
由于服务器端和客户端代码在同一个代码库中共存,像我这样的前端开发人员可以使用他们已经熟悉和喜爱的工具扩展可能的范围。
限制
共存很棒,但我遇到过至少两种情况,以这种方式使用无服务器函数并不完全适合手头的任务。 它们如下:
- 前端无法支持无服务器功能。
- 不止一个前端需要相同的功能。
为了帮助提供一些上下文,这里是上面提到的第 1 点和第 2 点的一个示例。 我维护了一个名为 MDX Embed 的开源项目,你会从 docs 网站看到它不是 Gatsby 网站。 它是使用 Storybook 构建的,Storybook 本身不提供无服务器功能功能。 我想实施“支付你想要的”捐款来帮助资助这个项目,我想使用 Stripe 来实现安全支付,但如果没有安全的“后端”,这是不可能的。
通过将此功能抽象到使用 Gatsby Functions 构建的 API 中,我能够使用 MDX Embed 实现我想要的,并且还可以重用相同的功能并为我的博客启用“按需付费”功能。
您可以在此处阅读有关我如何做到这一点的更多信息:使用 Gatsby 函数和 Stripe 将开源软件货币化。
正是在这一点上,使用 Gatsby Functions 可以充当前端或 BFF 的一种后端,以这种方式开发更类似于开发 API(应用程序编程接口)。
前端代码使用 API 来处理诸如登录、实时数据获取或仅由浏览器无法适当处理的安全任务。 在本教程中,我将解释如何使用 Gatsby Functions 构建 API 并将其部署到 Gatsby Cloud。
预检检查
Gatsby Functions 在部署到 Gatsby Cloud 或 Netlify 时工作,在本教程中,我将解释如何部署到 Gatsby Cloud,因此您需要先注册并创建一个免费帐户。
您还需要一个 GitHub、GitLab 或 BitBucket 帐户,这是 Gatsby Cloud 读取您的代码然后构建您的“站点”的方式,或者在本例中为 API。
出于本教程的目的,我将使用 GitHub。 如果您更愿意继续前进,可以在我的 GitHub 上找到完成的演示 API 代码。
入门
在本地驱动器的某处创建一个新目录,然后在终端中运行以下命令。 这将设置一个默认的package.json
。
npm init -y
依赖项
在终端中键入以下内容以安装所需的依赖项。
npm install gatsby react react-dom
页面
您的 API 可能没有任何“页面”,但为了避免在浏览器中访问根 URL 时看到 Gatsby 的默认缺失页面警告,请将以下内容添加到src/pages/index.js
和src/pages/404.js
。
//src/pages/index.js & src/pages/404.js export default () => null;
API
将以下内容添加到src/api/my-first-function.js
。
稍后我将解释'Access-Control-Allow-Origin', '*'
含义,但简而言之,它确保您的其他来源的 API 不会被 CORS 阻止。
//src/api/my-first-function.js export default function handler(req, res) { res.setHeader('Access-Control-Allow-Origin', '*'); res.status(200).json({ message: 'A ok!' }); }
脚本
将以下内容添加到package.json
。
//package.json ... "scripts": { "develop": "gatsby develop", "build": "gatsby build" }, ...
启动 Gatsby 开发服务器
要启动 Gatsby 开发服务器,请在终端中运行以下命令。
npm run develop
从浏览器发出请求
随着 Gatsby 的开发服务器运行,您可以访问 http://localhost:8000/api/my-first-function,由于这是一个简单的GET
请求,您应该在浏览器中看到以下内容。
{ "message": "A ok!" }
恭喜
您刚刚使用 Gatsby 函数开发了一个 API。
部署
如果您在浏览器中看到上述响应,则可以安全地假设您的函数在本地正常工作,在以下步骤中,我将解释如何将您的 API 部署到 Gatsby Cloud 并使用来自 CodeSandbox 的HTTP
请求访问它。
将代码推送到 Git
在尝试部署到 Gatsby Cloud 之前,您需要将代码推送到您选择的 Git 提供商。
盖茨比云
登录到您的 Gatsby Cloud 帐户并寻找显示“添加站点 +”的紫色大按钮。
在下一步中,您将被要求从 Git 存储库导入或从模板开始,选择Import from Git Repository
并点击next
。
如上所述,Gatsby Cloud 可以连接到 GitHub、GitLab 或 Bitbucket。 选择您喜欢的 Git 提供程序并点击next
。
连接您的 Git 提供程序后,您可以搜索您的存储库,并为您的站点命名。
一旦您选择了您的存储库并将您的站点命名为next
。
您可以跳过“集成”和“设置”,因为我们不需要这些。
如果一切都按计划进行,您应该会看到类似于以下屏幕截图的内容。
您会在屏幕左侧的顶部附近看到一个以gatsbyjs.io
结尾的 URL,这将是您的 API 的 URL,您创建的任何函数都可以通过添加/api/name-of-function
来访问/api/name-of-function
到此 URL 的末尾。
例如,我的演示 API 的my-first-function.js
的完整部署版本如下:
演示 API:我的第一个函数。
测试你的 API
访问 API 的 URL 是一回事,但这并不是 API 通常的使用方式。 理想情况下,要测试您的 API,您需要从完全不相关的来源向函数发出请求。
就在这里res.setHeader('Access-Control-Allow-Origin', '*');
前来救援。 虽然允许任何域(网站)访问您的功能并不总是可取的,但在大多数情况下,公共功能就是这样,公共的。 将 Access Control 标头设置为值*
意味着任何域都可以访问您的函数,如果没有这个,除了托管 API 的域之外的任何域都将被 CORS 阻止。
这是一个使用我的演示 API 中my-first-function
的 CodeSandbox。 您可以分叉并更改 Axios 请求 URL 以测试您的功能。
CodeSandbox:我的第一个函数
变得更漂亮
从您的 API 发送一条响应message: "A ok!"
不是很令人兴奋,所以接下来我将向您展示如何查询 GitHub REST API 并使用您刚刚创建的 API 制作个人资料卡以显示在您自己的网站上,它看起来有点像这样.
CodeSandbox:演示资料卡
依赖项
要使用 GitHub REST API,您需要安装 @octokit/rest 包。
npm install @octokit/rest
获取 GitHub 用户原始数据
将以下内容添加到src/api/get-github-user-raw.js
。
// src/api/get-github-user-raw.js import { Octokit } from '@octokit/rest'; const octokit = new Octokit({ auth: process.env.OCTOKIT_PERSONAL_ACCESS_TOKEN }); export default async function handler(req, res) { res.setHeader('Access-Control-Allow-Origin', '*'); try { const { data } = await octokit.request(`GET /users/{username}`, { username: 'PaulieScanlon' }); res.status(200).json({ message: 'A ok!', user: data }); } catch (error) { res.status(500).json({ message: 'Error!' }); } }
访问令牌
要与 GitHub REST API 通信,您需要一个访问令牌。 您可以按照 GitHub 上的本指南中的步骤获取此信息:创建个人访问令牌。
.env
变量
为了保证您的访问令牌安全,请将以下内容添加到.env.development
和.env.production
。
OCTOKIT_PERSONAL_ACCESS_TOKEN=123YourAccessTokenABC
您可以在 Gatsby 的本指南中阅读有关 Gatsby 环境变量的更多信息:环境变量。
启动开发服务器
正如您之前所做的那样,通过在终端中键入以下内容来启动 Gatsby 开发服务器。
npm run develop
从浏览器发出请求
随着 Gatsby 开发服务器的运行,您可以访问 http://localhost:8000/api/get-github-user-raw,由于这也是一个简单的GET
请求,您应该在浏览器中看到以下内容。 (为简洁起见,我删除了部分回复。 )
{ "message": "A ok!", "user": { "login": "PaulieScanlon", "id": 1465706, "node_id": "MDQ6VXNlcjE0NjU3MDY=", "avatar_url": "https://avatars.githubusercontent.com/u/1465706?v=4", "gravatar_id": "", "url": "https://api.github.com/users/PaulieScanlon", "type": "User", "site_admin": false, "name": "Paul Scanlon", "company": "Paulie Scanlon Ltd.", "blog": "https://www.paulie.dev", "location": "Worthing", "email": "[email protected]", "hireable": true, "bio": "Jamstack Developer / Technical Content Writer (freelance)", "twitter_username": "pauliescanlon", "created_at": "2012-02-23T13:43:26Z", "two_factor_authentication": true, ... } }
这是完整原始响应的 CodeSandbox 示例。
CodeSandbox:原始响应
你会从上面看到,返回了很多我并不真正需要的数据,下一点完全取决于你,因为它是你的 API,但我发现稍微操作 GitHub API 响应很有帮助在将其发送回我的前端代码之前。
如果你想做同样的事情,你可以创建一个新函数并将以下内容添加到src/api/get-github-user.js
。
// src/api/get-github-user.js import { Octokit } from '@octokit/rest'; const octokit = new Octokit({ auth: process.env.OCTOKIT_PERSONAL_ACCESS_TOKEN }); export default async function handler(req, res) { res.setHeader('Access-Control-Allow-Origin', '*'); try { const { data } = await octokit.request(`GET /users/{username}`, { username: 'PaulieScanlon' }); res.status(200).json({ message: 'A ok!', user: { name: data.name, blog_url: data.blog, bio: data.bio, photo: data.avatar_url, githubUsername: `@${data.login}`, githubUrl: data.html_url, twitterUsername: `@${data.twitter_username}`, twitterUrl: `https://twitter.com/${data.twitter_username}` } }); } catch (error) { res.status(500).json({ message: 'Error!' }); } }
从上面你会看到,我没有返回 GitHub REST API 返回的完整数据对象,而是只选择我需要的位,重命名它们并在用户名和 URL 值之前添加一些位。 当您在前端代码中呈现数据时,这会让生活变得更轻松。
这是格式化响应的 CodeSandbox 示例。
CodeSandbox:格式化响应
这与之前的 Profile Card CodeSandbox 非常相似,但我还将数据打印出来,这样您就可以看到每个被操纵的数据项是如何使用的。
在这一点上值得注意的是,本教程中的所有四个 CodeSandbox 演示都使用了演示 API,并且没有一个是使用 Gatsby 构建的,也不是托管在 Gatsby Cloud 上的——太棒了!
Gatsby Cloud .env
变量
在部署两个新函数之前,您需要将 GitHub 访问令牌添加到 Gatsby Cloud 中的环境变量部分。
然后去哪儿?
我问自己这个问题。 通常来说,无服务器函数用于客户端请求,虽然这很好,但我想知道它们是否也可以在构建时用于将数据静态“烘焙”到页面中,而不是依赖于可能会或可能不会在用户中禁用的 JavaScript浏览器。
……所以这正是我所做的。
这是一种数据仪表板,它使用 Gatsby Functions 在运行和构建时返回的数据。 我使用 Astro 构建了这个站点并将其部署到 GitHub Pages。
我认为这是一个很好的方法的原因是因为我能够在服务器和浏览器中重复使用相同的功能而无需复制任何内容。
在这个 Astro 构建中,我点击了由我的 API 公开的相同端点以返回数据,然后这些数据要么被烘焙到页面中(非常适合 SEO),要么在运行时由浏览器获取(非常适合显示新鲜或最新的实时数据) .
数据仪表板
网站左侧显示的数据是在构建时请求的,并使用 Astro 烘焙到页面中。 页面右侧的数据是在运行时使用客户端请求请求的。 我使用了由 GitHub REST API 公开的略有不同的端点来查询创建不同列表的不同 GitHub 用户帐户。
你在这个网站上看到的一切都是由我更完整的 API 提供的。 我称它为:Paulie API,我将它用于我的许多网站。
保利 API
Paulie API 与本教程中的 API 类似,是使用 Gatsby 构建的,但因为 Gatsby 既可以作为站点也可以作为 API,我使用它来记录我的所有函数的工作方式,并且每个端点都有自己的页面,可以用作交互式操场......随意看看周围。
所以,你有它,可以被任何客户端或服务器端代码使用的 Gatsby 函数 API,来自任何使用任何技术堆栈构建的网站。
试一试,我很想看看你建立了什么。 随时在下面的评论中分享或在 Twitter 上找到我:@PaulieScanlon。