DEV Community

loading...
Cover image for Zip your own Netlify functions for better dependency control

Zip your own Netlify functions for better dependency control

Derek Gavey
A fullstack developer who would prefer to just write great user experiences with Ember.js all day. Frontend Lead @Onclusive.
・3 min read

When I was working on my side project Dedolist, which is mostly hosted on Netlify I started using Netlify functions. They are a really easy way to create small AWS Lambda functions.

In their simplest form you just created a file in your "functions" folder and they get deployed as a lambda function. Unfortunately I required a bit more control over the functions than the simplest case.

I needed:

  1. To access a file locally that is deployed with the function.
  2. Maintain the functions own dependencies that were not part of the main project.

It took a few hours and reading a lot of forum posts and sample projects, but I finally was able to figure it out. I'm hoping to save you some time by showing you the exact steps you need to take to accomplish this.

Netlify's build tools does try and smartly build your functions, however there are some scenarios where it may fail to find all the dependencies. There is also a limit to the size of the function that AWS lambda accepts (50MB) and this technique gives you more control over what is included in your final functions.

I have all the code for this demo in this repository. I'll point out some of the specific changes I made to deploy my bundled functions.

First off, in general the way to bundle your functions is you need to compress each function and all of it's dependencies in a single zip file. Just like the simplest form of Netlify functions, you can put each zip file in your functions folder and it will get deployed.

In order to be able to test your functions locally using netlify dev you need to be able to specify a separate folder for your "development" and "production" functions. It's easy to do that by changing your netlify.toml and adding environment specific configurations below.

#netlify.toml in root of project

[build]
  functions = "functions"

[dev]
  functions = "functions-dev"
Enter fullscreen mode Exit fullscreen mode

As you can see above, new now specify two different folders for function in "build" and "dev". So now when you run netlify dev the functions can be modified in the functions-dev folder and you can test them there.

Now lets look at what a function in the "functions-dev" folder looks like. Take a look at the structure below for a function called "hello-dev".

functions-dev
  hello-dev
    node_modules
    package.json
    hello-dev.js
    .gitignore
Enter fullscreen mode Exit fullscreen mode

Everything in the folder hello-dev will be zipped and become one lambda function. You can have multiple functions and even mix your single file functions with folder based ones.

For this example the package.json has a dependency for lambda-api. No other function will have this dependency only this one.

The magic is in the top level package.json file and the build commands. Let's look at each part of the build system.

"scripts": {
      "build": "NODE_ENV=production npm-run-all build:*",
      "build:static": "eleventy",
      "build:functions-install-dependencies": "cd functions-dev; for i in */; do cd ${i%/}; yarn; cd ..; done;",
      "build:zip-functions": "cd functions-dev; for i in */; do zip -r \"../functions/${i%/}.zip\" \"$i\"; done;",
      "build:copy-single-functions": "cp ./functions-dev/*.js ./functions",
      "dev": "eleventy --serve --quiet"
}
Enter fullscreen mode Exit fullscreen mode

So "build" simply runs all the build steps and signifies the node production environment. This is the command that Netlify calls when building the production application.

"build:static" Is just the normal Eleventy build command, not part of the functions build step.

"build:functions-install-dependencies" does what is says. It enters into each folder and install the dependencies for each function.

"build:zip-functions" zips each folder into the production functions folder so Netlify knows to create it.

Finally "build:copy-single-functions" copies any single file lambda functions you might have.

You can see a working example from the repository on https://dgavey-netlify-functions-demo.netlify.app/.

There was a couple of strange issues I ran into with the Netlify CLI that should be noted.

  1. It won't serve functions on a purely static site, so I included an extremely basic eleventy generator.
  2. It won't allow access to functions in folders unless there is a build command in dev environment.

Hopefully this can help you get more control over the building of your functions with Netlify.

Cover photo by Tony Pham

Discussion (1)

Collapse
arolland profile image
Antoine Rolland

Thanks man ! This article has been a lifesaver for me !