Earlier this week Netlify announced their acquisition of Quirrel and (more importantly to me), the beta release of scheduled functions. As the name implies, this is the ability to write Netlify serverless functions that run on a particular schedule. It's currently documented over on their Labs repository, and it's certainly possible it will change before it's official release, I thought I'd build a quick example of this to see how it worked.

I began by creating a new web site. Here it is. All of it.

<h1>Hello World</h1>

But check out that Lighthouse score...

100 Lighthouse score like a G6

I then went ahead and created a GitHub repository, added my code to it, and made a new Netlify site that tied to it. Back in my command line, I used the CLI to generate a new function (ntl functions:create rebuild), and copied the code from the docs.

const { schedule } = require('@netlify/functions');

const handler = async function(event, context) {
    console.log("Received event:", event);

    return {
        statusCode: 200,
    };
};

module.exports.handler = schedule("@hourly", handler);

I started my site (ntl dev), and then used the CLI to hit the function (ntl functions:invoke rebuild) and took a look at the event object. (One thing Netlify has not done a great job of is fully documenting the event structure passed to various Netlify functions tied to events.) Here's how it looked:

 {
  path: '/.netlify/functions/rebuild',
  httpMethod: 'POST',
  queryStringParameters: {},
  multiValueQueryStringParameters: {},
  headers: {
    'x-forwarded-for': '::ffff:127.0.0.1',
    host: 'localhost:8888',
    connection: 'close',
    'accept-encoding': 'gzip,deflate',
    'content-length': '2',
    accept: '*/*',
    'content-type': 'text/plain;charset=UTF-8',
    'user-agent': 'Netlify Clockwork',
    'client-ip': '127.0.0.1',
    'X-NF-Event': 'schedule'
  },
  multiValueHeaders: {
    'x-forwarded-for': [ '::ffff:127.0.0.1' ],
    host: [ 'localhost:8888' ],
    connection: [ 'close' ],
    'accept-encoding': [ 'gzip,deflate' ],
    'content-length': [ '2' ],
    accept: [ '*/*' ],
    'content-type': [ 'text/plain;charset=UTF-8' ],
    'user-agent': [ 'Netlify Clockwork' ],
    'client-ip': [ '127.0.0.1' ]
  },
  body: '{"next_run":"2022-02-05T00:00:00.000Z"}',
  isBase64Encoded: false,
  rawUrl: 'http://localhost:8888/.netlify/functions/rebuild',
  rawQuery: ''
}

Most of this probably isn't useful (although I like that user-agent), but the body is really helpful. If we grab the body and parse it...

let body = JSON.parse(event.body);
console.log(body);

We can more clearly see what it's showing:

{ next_run: '2022-02-04T20:00:00.000Z' }

Nice! Your function knows when it will run again. I can see that being useful.

So - one of the first things I immediately thought of was using this feature as a way to schedule rebuilds. This is actually listed in the announcement blog about one of the possible use cases.

To enable this, you need to go into your "Build hooks" section of your site's "Build & deploy" settings. There you can add a new hook:

Form to add a new build hook

Once you add it, you get a secret URL:

Build hook with part of the URL obscured...

In order to trigger a build, you need to make a POST request. So I modified my scheduled function like so:

const { schedule } = require('@netlify/functions');
const fetch = require('node-fetch');

const REBUILD_URL = process.env.rebuildurl;

const handler = async function(event, context) {

    await fetch(REBUILD_URL, { method: 'POST'});

    return {
        statusCode: 200,
    };
};

module.exports.handler = schedule("@daily", handler);

First, note that I'm getting my rebuild URL via an environment variable. I simply copied the URL from the build hooks section and added it as a new environment setting.

Next, I do my POST.

And that's it. I also changed my schedule to @daily so it rebuilds once a day. I tested again via the CLI (ntl functions:invoke rebuild) and had the "Deploys" part of my Netlify site up. I could see it firing!

Success build of the site based on the scheduled task.

And that's it. I'm really happy with how easy Netlify made this, especially with them supporting the "simpler" shortcut aliases for CRON. There isn't anything more to the code than what I've shown here, but you can peruse the repo if you would like: https://github.com/cfjedimaster/netlify_scheduled_functions_test. I'd also love to know how you plan on using this, so reach out with your ideas!

Photo by Sonja Langford on Unsplash