简介
每隔一段时间,Gatsby的开发者就会发现自己需要洒上一些后端代码。我们不一定需要整个服务器,我们当然也不想处理诸如负载平衡和扩展的问题。我们只需要一些代码在非浏览器中运行。
案例:当我重建这个博客时,我想跟踪并显示每篇文章获得的喜欢数,以及点击数(用于复古风格的点击计数器)。
对于这类情况,无服务器函数是完美的。它们让我们可以编写小段的Node.js代码,而不必担心代码会在哪里运行。
这个博客是用Gatsby Cloud构建和部署的,它是Gatsby网站的CI服务,由Netlify托管。我是Netlify的一个非常愉快的客户,而Netlify功能似乎是满足我需求的完美服务
让Gatsby Cloud和Netlify Functions合作花了一点时间,但令人高兴的是,它是可以做到的我发现的解决方案感觉很强大和可靠,我的博客已经由这两个服务提供了几个星期,没有任何问题。
今天我们将看看为什么这两个服务值得结合,以及如何为你自己的Gatsby网站做到这一点
免责声明
我是一名在Gatsby云团队工作的工程师。我在业余时间写了这篇文章,而不是作为我工作的一部分,但当谈到我的团队所做的出色工作时,我还是有偏见的:D
什么是Netlify功能?
Netlify功能让你运行事件驱动的服务器端代码,而不用担心运行和维护服务器的问题。它是一个位于AWS Lambda前面的服务,并刷掉了一些直接与亚马逊产品合作的荆棘。
它允许你写这样的代码,这个博客用它来跟踪点击率。
const faunadb = require('faunadb'); /* Import faunaDB sdk */
module.exports = async (event, context, callback) => {
// Connect to the database
const q = faunadb.query;
const client = new faunadb.Client({
secret: process.env.FAUNADB_SECRET,
});
// Get the provided slug, and use it to look up
// the corresponding document.
const { slug } = JSON.parse(event.body);
const document = await client.query(
q.Get(q.Match(q.Index('hits_by_slug'), slug))
);
// Increment the number of hits by 1
await client.query(
q.Update(document.ref, {
data: { hits: document.data.hits + 1 },
})
);
// Return a happy result
return {
statusCode: 200,
body: JSON.stringify({
success: true,
}),
};
};
When using Netlify for CI and deployments, you can pop this co
当使用Netlify进行CI和部署时,你可以把这段代码放在/functions 目录中,只要你推送到Github,这些功能就会被构建和发送。不需要手动步骤 💯
什么是Gatsby Cloud?
Gatsby Cloud是由Gatsby公司提供的服务,用于管理Gatsby应用程序的部署。
重要的是,Gatsby Cloud不是Netlify的替代品--我们仍然使用CDN供应商,如Netlify或Amazon S3来托管您的项目。相反,Gatsby Cloud是一个CI服务,为你建立网站并分发。

使用Gatsby Cloud有很多理由,但对于大多数开发者来说,最令人信服的理由是速度。我们正在建立专门的基础设施,使我们能够在创纪录的时间内建立大型Gatsby网站。
通过我们的力量结合...
本节已过期!你不需要再这样做了。如果你把你的函数放在一个顶级的functions 目录中,它们应该被自动部署✨
问题是,当使用Gatsby Cloud时,我们并没有在Netlify上进行任何构建;我们提前构建网站,并将文件上传到Netlify。这就剥夺了Netlify对我们的功能进行打包和运输的机会。
幸运的是,我们可以解决这个问题。我们将深入研究这一切是如何运作的,但对于急于求成的人来说,这里有我们需要添加到gatsby-node.js 的代码。
const path = require('path');
const fs = require('fs');
const { zipFunctions } = require('@netlify/zip-it-and-ship-it');
exports.onPostBuild = () => {
const srcLocation = path.join(__dirname, `./functions`);
const outputLocation = path.join(__dirname, `./public/functions`);
if (!fs.existsSync(outputLocation)) {
fs.mkdirSync(outputLocation);
}
return zipFunctions(srcLocation, outputLocation);
};
Link to this headingGatsby build hooks
Gatsby构建钩子
在我看来,Gatsby.js最酷的一点是,你可以 "钩住 "它的任何构建步骤,就像一个生命周期方法。
onPostBuild 在构建完成后立即运行。我们可以用它来准备和复制函数到正确的地方,然后再交给Netlify。
压缩和发送
还记得我提到Netlify刷掉了与AWS Lambda合作的荆棘吗?其中一个荆棘就是每个函数都需要成为自己的打包项目的怪癖。
假设我有两个函数,track-hit.js 和like-content.js 。让我们假设它们都使用faunadb ,一个Node模块。我需要制作两个.zip 文件,内容如下。
.
└── functions
├── track-hit.zip
│ ├── track-hit.js
│ └── node_modules
│ ├── faunadb
│ │ ├── index.js
│ │ └── (all the other stuff in this module)
│ ├── some-faunadb-dependency
│ └── some-other-faunadb-dependency
└── like-content.zip
├── like-content.js
└── node_modules
├── faunadb
│ ├── index.js
│ └── (all the other stuff in this module)
├── some-faunadb-dependency
└── some-other-faunadb-dependency
因为Netlify的人是出色的向导,他们提取了准备函数的模块,并在NPM上发布为@netlify/zip-it-and-ship-it 。这意味着我们可以利用Netlify构建过程中的这个关键部分,即使我们没有在Netlify上构建。
冷建和暖建
当我们把构建好的项目提交给Netlify时,它会在一个非常特殊的地方寻找函数:/public/functions 。我们需要在这个目录中找到我们构建的、准备好的函数。在我们用zip-it-and-ship-it 构建和准备好函数之前,我们需要先创建这个目录。
这段代码检查该目录是否存在,如果有必要,就创建它。
if (!fs.existsSync(outputLocation)) {
fs.mkdirSync(outputLocation);
}
为什么该目录可能已经存在?Gatsby Cloud维护一个缓存,以加快后续的构建。一个 "冷构建 "将从头开始,而一个 "热构建 "将重复使用它可以使用的东西。我们需要确保我们的构建成功,无论该目录是否已经存在。
Node纯粹主义者可能会对我使用`existsSync`和`mkdirSync`而不是其默认的异步版本感到惊恐不安。因为这是一个构建步骤,而不是一个活动的服务器,我看不出这样做有什么令人信服的问题,而且它使代码变得更简单了
在结论中
通过一点Node.js的配置,我们可以在构建后做一些后处理,把我们的函数打包,并把它们移到Netlify期望找到的地方。当我们推送代码到Github时,Gatsby Cloud会运行一个新的构建,然后将生成的文件上传到Netlify。
如果你已经有一个Gatsby Cloud网站,并且你正在考虑使用无服务器函数,我可以明确地说,Netlify让你的体验无缝和无痛,而且他们慷慨的定价模式意味着你可以免费尝试。
如果您已经使用Netlify功能,并且正在考虑将您的Gatsby网站转移到Gatsby云,我们希望您能给我们一个机会我们Gatsby Cloud团队的主要重点之一是减少复杂/大型网站的构建时间。如果你一直在关注构建时间的攀升,我们正在尽最大的努力来加快进度。⚡️