Skip to content

Commit bf00915

Browse files
joshwcomeaugatsbybothashimwarrensidharthachatterjee
authored
docs(blog): Add Netlify Functions post (#22115)
* Add blog post * Rename post * Fix image path * Fix heading levels, remove unused caption prop * Push date back * Update publish date * Update publish date to March 25 Co-authored-by: gatsbybot <[email protected]> Co-authored-by: Hashim Warren <[email protected]> Co-authored-by: Sidhartha Chatterjee <[email protected]>
1 parent cc2fc56 commit bf00915

File tree

2 files changed

+163
-0
lines changed

2 files changed

+163
-0
lines changed
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
---
2+
title: "Using Netlify Functions with Gatsby Cloud"
3+
date: 2020-03-25
4+
author: "Josh Comeau"
5+
excerpt: "An article detailing how to use Netlify Functions and Gatsby Cloud together, to tremendous effect!"
6+
tags: ["netlify", "serverless", "lambda", "gatsby cloud"]
7+
canonicalLink: https://joshwcomeau.com/gatsby/using-netlify-functions-with-gatsby-cloud/
8+
---
9+
10+
import netlifyFunctions from "./gatsby-cloud.png"
11+
12+
Every now and then, Gatsby developers find themselves needing a sprinkle of back-end code. We don't necessarily need a whole server, and we certainly don't want to have to deal with things like load balancing and scaling. We just need some code to run not-in-the-browser.
13+
14+
Case in point: when I was rebuilding my [personal blog](https://joshwcomeau.com/), I wanted to track and display the number of likes each article gets, as well as the number of hits (for a retro-style hit counter).
15+
16+
For these kinds of situations, _serverless functions_ are perfect. They let us write small bits of Node.js code without worrying about where that code will run.
17+
18+
My personal blog is built and deployed with [Gatsby Cloud](https://www.gatsbyjs.com/), a CI service for Gatsby sites, and it's hosted by [Netlify](https://www.netlify.com/). I'm a very happy Netlify customer, and [Netlify Functions](https://www.netlify.com/products/functions/) seemed like the perfect service for my needs!
19+
20+
Getting Gatsby Cloud and Netlify Functions to cooperate took a bit of tinkering, but happily it can be done! The solution I discovered feels robust and reliable, and my blog has been powered by these two services for several weeks now, without any issues.
21+
22+
Today we'll look at how to use Netlify Functions for your Gatsby Cloud site.
23+
24+
## What are Netlify Functions?
25+
26+
Netlify functions let you run event-driven server-side code, without worrying about running and maintaining a server. It's a service that sits in front of AWS Lambda, and brushes away some of the thorns of working directly with Amazon Web Services.
27+
28+
It allows you to write code like this, used by my blog to track hits:
29+
30+
```js
31+
const faunadb = require("faunadb")
32+
33+
exports.handler = async (event, context, callback) => {
34+
// Connect to the database
35+
const q = faunadb.query
36+
const client = new faunadb.Client({
37+
secret: process.env.FAUNADB_SECRET,
38+
})
39+
40+
// Get the provided slug, and use it to look up
41+
// the corresponding document.
42+
const { slug } = JSON.parse(event.body)
43+
const document = await client.query(
44+
q.Get(q.Match(q.Index("hits_by_slug"), slug))
45+
)
46+
47+
// Increment the number of hits by 1
48+
await client.query(
49+
q.Update(document.ref, {
50+
data: { hits: document.data.hits + 1 },
51+
})
52+
)
53+
54+
return {
55+
statusCode: 200,
56+
body: JSON.stringify({
57+
success: true,
58+
}),
59+
}
60+
}
61+
```
62+
63+
When using Netlify for CI _and_ deployments, you can pop this code in a `/functions` directory and the functions will get built and shipped whenever you push to Github. No manual steps needed 💯
64+
65+
Learn more about Netlify Functions in [their documentation](https://docs.netlify.com/functions/overview/).
66+
67+
## What is Gatsby Cloud?
68+
69+
Gatsby Cloud is a service provided by Gatsby Inc. to manage deployments of Gatsby apps.
70+
71+
Critically, Gatsby Cloud is _not_ an alternative to Netlify—we still use CDN providers like Netlify or Amazon S3 to host your projects. Rather, Gatsby Cloud is a CI service that builds your site and distributes it for you.
72+
73+
<img
74+
src={netlifyFunctions}
75+
alt="Screenshot of Gatsby Cloud, showing a successful recent deploy."
76+
/>
77+
78+
There are lots of reasons to use Gatsby Cloud, but perhaps the most compelling reason for most developers is speed. We're building specialized infrastructure which allows us to build large Gatsby sites in record time.
79+
80+
## With our powers combined…
81+
82+
The trouble is that when using Gatsby Cloud, we aren't doing any building on Netlify; we build the site ahead of time, and upload the files to Netlify. This deprives Netlify of the opportunity to package and ship our functions!
83+
84+
Happily, we can work around this. We'll dive into how this all works, but for eager beavers, here's the code we need to add to `gatsby-node.js`.
85+
86+
```js
87+
const path = require("path")
88+
const fs = require("fs")
89+
90+
const { zipFunctions } = require("@netlify/zip-it-and-ship-it")
91+
92+
exports.onPostBuild = () => {
93+
const srcLocation = path.join(__dirname, `./functions`)
94+
const outputLocation = path.join(__dirname, `./public/functions`)
95+
96+
if (!fs.existsSync(outputLocation)) {
97+
fs.mkdirSync(outputLocation)
98+
}
99+
100+
return zipFunctions(srcLocation, outputLocation)
101+
}
102+
```
103+
104+
### Gatsby build hooks
105+
106+
In my opinion, one of the coolest things about Gatsby.js is that you can "hook in" to any of its build steps, like a lifecycle method.
107+
108+
`onPostBuild` runs right after the build completes. We can use it to prepare and copy the functions over to the right place, before it's handed off to Netlify.
109+
110+
Learn more about Gatsby build hooks in [our documentation](https://www.gatsbyjs.org/docs/node-apis/).
111+
112+
### Zip It and Ship It
113+
114+
Remember when I mentioned that Netlify brushes away the thorns of working with AWS Lambda? One of those thorns is the quirk that every function needs to be its own packaged project.
115+
116+
Let's say we have two functions, `track-hit.js` and `like-content.js`. And let's assume that they both use `faunadb`, a Node module. We need to produce two `.zip` files, with the following contents:
117+
118+
```
119+
.
120+
└── functions
121+
├── track-hit.zip
122+
│ ├── track-hit.js
123+
│ └── node_modules
124+
│ ├── faunadb
125+
│ │ ├── index.js
126+
│ │ └── (all the other stuff in this module)
127+
│ ├── some-faunadb-dependency
128+
│ └── some-other-faunadb-dependency
129+
└── like-content.zip
130+
├── like-content.js
131+
└── node_modules
132+
├── faunadb
133+
│ ├── index.js
134+
│ └── (all the other stuff in this module)
135+
├── some-faunadb-dependency
136+
└── some-other-faunadb-dependency
137+
```
138+
139+
Because the folks at Netlify are wonderful wizards, they extracted the module that prepares functions and published it on NPM as `@netlify/zip-it-and-ship-it`. This means we can leverage this critical part of Netlify's build process even though we aren't building on Netlify.
140+
141+
### Cold and warm builds
142+
143+
When we ship our built project over to Netlify, it's going to look for functions in a very specific place: `/public/functions`. We need to have our built, prepared functions hanging out in that directory. Before we can build and prep the functions with `zip-it-and-ship-it`, we need to create the directory first!
144+
145+
This bit of code checks to see if the directory exists, and creates it if necessary:
146+
147+
```js
148+
if (!fs.existsSync(outputLocation)) {
149+
fs.mkdirSync(outputLocation)
150+
}
151+
```
152+
153+
Why might the directory already exist? Gatsby Cloud maintains a cache, to speed up subsequent builds. A "cold build" will start from scratch, while a "warm build" will reuse what it can. We need to ensure our build succeeds regardless of whether or not the directory has been cached.
154+
155+
> Node purists are probably aghast in horror at the fact that I'm using `existsSync` and `mkdirSync` instead of their default async versions. Because this is a build step, and not an active server, I couldn't see any compelling issue with doing it this way, and it makes the code a little simpler!
156+
157+
## In conclusion
158+
159+
With a little bit of Node.js configuration, we're able to do some post-processing after the build, packaging up our functions and moving them to the spot Netlify expects to find them. When we push code to Github, Gatsby Cloud will run a new build, and then upload the resulting files to Netlify.
160+
161+
If you already have a Gatsby Cloud site, and you're considering using serverless functions, I can say unequivocally that Netlify makes the experience seamless and painless, and their generous pricing model means that you can experiment with them for free.
162+
163+
If you already use Netlify Functions and are considering moving your Gatsby site to Gatsby Cloud, we hope you'll give us a shot! One of our main focuses on the Gatsby Cloud team is to reduce the build time for complex / large sites. If you've been watching build times climb, we're doing our best to speed things up. ⚡️

0 commit comments

Comments
 (0)