Using Netlify functions with Gatsby

Learn how to implement Netlify functions using Gatsby

Mon, 30 Jul 2018

Quick intro, Netlify functions is a quick and powerful feature that will allow you to write AWS Lambdas without having an AWS account. These functions serve the purpose of replacing any backend servers you would implement that would handle API calls. I’m splitting this into 5 posts.

  1. Setting up Netlify Functions and creating a simple Hello World function
  2. Query a MongoDB instance and return some data
  3. Post data on a MongoDB instance
  4. Set up React Stripe Elements
  5. Create charges using the Stripe API
  6. Use node mailer to send emails

If you would like to get a more in depth overview of Netlify’s function reader please feel free to click this link. Lets begin!

Setup Netlify Lambda CLI

Netlify offers a tool that will allow us to test our functions during development. The tool name is netlify-Lambda. With this tool you can compile your lambdas into Netlify functions that are ready to use at run time for your application. These steps come directly from Netlify, I just made a little bit of tweaks to make things simple.

  1. Install it in your project directory using npm install netlify-lambda or yarn add netlify-lambda.

  2. Include a netlify.toml file in the base of your project, specifying the location of your functions folder. The contents of my netlify.toml is as follows

    [build]
    functions = "src/functions"
  3. Put the source files for your Lambda functions in another folder inside your project. This will be the <source-folder> in your netlify-lambda commands. For those example the source folder I will be using is src/lambdas

If everything is correct you should have the following structure for your project

Project
--- netlify.toml
--- src
------ functions
------ lambdas

Hello World Lambda

Proper convention for learning new coding techniques/languages is to create a very basic hello world function. The file name does not matter but for simplicity we will name it hello.js, this file should be created inside the lambda folder. You can copy/paste the following code into the new file you just created

export function handler(event, context, callback) {
	console.log(event)
	callback(null, {
		statusCode: 200,
		body: JSON.stringify({msg: "Hello, World!"})
	})
}

All lambdas take 3 parameters.

  • Event - Information about the invocation of the function is found here
  • Context - Provides run time info while the function is being executed. Click here for more info
  • Callback - returns data to the caller

Gatsby Proxy

To test functions during develop, you will need to add extra code to your gatsby-config.js file. Without the proxy you will get nasty cors errors during development. Add the following lines of code to your gatsby-config.js file.

  developMiddleware: app => {
    app.use(
      "/.netlify/functions/",
      proxy({
        target: "http://localhost:9000",
        pathRewrite: {
          "/.netlify/functions/": "",
        },
      })
    );
  },

The code is very straightforward, whenever a request is going to http://localhost:9000 it will instead be routed to /.netlify/functions/. The best part about this proxy is that there is no code that needs to be changed once it is time to deploy to Netlify.

Putting it all together

To serve your Lambda functions locally, run:

netlify-lambda serve src/lambdas

This will start a local dev server and a file watcher for the specified folder. Requests to http://localhost:9000/hello will route to src/functions/hello.js. If you were to put http://localhost:9000/hello into your browser, “Hello World” should appear on the page as a response. If you would like to test this in a project you can make an easy fetch request to get hello world as a response. This code is directly from the create react app lambda repo, it should give the same results when used within a Gatsby app.

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class LambdaDemo extends Component {
	constructor(props) {
		super(props);
		this.state = {loading: false, msg: null};
	}
	handleClick = (e) => {
		e.preventDefault();
		this.setState({loading: true});

		fetch('/.netlify/functions/hello')
		.then(response => response.json())
		.then(json => this.setState({loading: false, msg: json.msg}));
	}

	render() {
		const {loading, msg} = this.state;
		return
		<p>
			<button onClick={this.handleClick}>{loading ? 'Loading...' : 'Call Lambda'}</button><br/>
			<span>{msg}</span>
		</p>
	}
}

class App extends Component {

	render() {

		return (
		<div className="App">
			<header className="App-header">
				<img src={logo} className="App-logo" alt="logo" />
				<h1 className="App-title">Welcome to React</h1>
			</header>
			<p className="App-intro">
				To get started, edit <code>src/App.js</code> and save to reload.
			</p>
			<LambdaDemo/>
		</div>
		);
	}
}
export default App;
Loading...
Edward Beazer

Edward Beazer - I just like to build shit. Sometimes I get stuck for hours, even days while trying to figure out how to solve an issue or implement a new feature. Hope my tips and tutorials can save you some time.