Azure Functions are great for creating solutions built on top of serverless architecture. In the past I've talked about the various deployment options but today I want to focus on performance improvements. The team recently introduced pre-compiled Functions which, in my mind, is a fantastic enhancement. Because it promotes good design by allowing you to decouple your implementation from the Function call itself and make your code a lot more testable. Some may digress because this may also cause Function code to explode in size. My answer to this is that you need to show restrain and keep your functions lean and fast.
There are 2 ways to address this issue:
- Upload the node_modules folder along with your Function as part of the deployment (not recommended IMHO)
- Use FuncPack (the WebPack derivative tool for Functions) to minimize and pack your code along with its dependencies
How to use Funcpack in your development process
Chris Anderson is the man behind this little tool. You can find the details and source code on GitHub. This is an OSS project that anyone can contribute so feel free to help out.
Side note: using the tool and reporting bugs or feature requests can be an invaluable contribution so don't be shy and help make this tool mainstream!
Firstly, let's install the Azure Functions CLI, in case you don't have it already installed:
npm I -g azure-functions-cli
To install the tool, open the command line and run the following command:
npm i -g azure-functions-pack
With this in place we can now start using the tool to pack and unpack our Function code.
The commands available with this tool are:
Packing a Function
func pack [options] <path> [Available Options] -h, --help output usage information -o, --output <path> Path for output directory -u, --uglify Uglify the project when webpacking
Unpacking a Function
func unpack [options] <path> [Available Options] -h, --help output usage information -o, --output <path> Path for output directory
The uglify feature only supports some small amount of ES6, so if you get errors either don't uglify or make sure your code targets ES5.
For the purpose of this demo, I've created a very basic Function with an HttpTrigger that consumes 2 NPM packages:
Since I love the command line, I'll stick with the CLI. You, however, can use the Portal if you find it easier or more convenient. Each to its own people and make sure you use the tools you love and feel comfortable with :)
To create my Function, all I have to do is call the
func init command and follow the wizard as per my example below:
I can now test my Function and run it locally using the
func run command.
This is to prove that it works as expected. When running locally, the Functions CLI spins up a local server listening to incoming http requests. In this case, the Function can be hit over
http://localhost:7071/api/myhttptrigger. We can use any tool capable of sending an HTTP request (Postman, Fiddler, any browser) to test this URL. To pass the expected parameter, we can either send it in the body with a POST or as a URL parameter with a GET. For the last, I've attached an example below:
We can see the Function executing and logging on the separately spun process:
Next, I'm going to pack my Function using the
funcpack pack ./ command. I'll refrain from uglifying the code to keep things simple.
This command will have the following 2 effects:
- It will pack all my code and place it into a
- It will change the entry point of my Function to point to the right location, i.e my .funcpack folder
With this change the
function.json file should look like this:
We can run the Function again to make sure that all is working as expected:
Deploy to Azure Portal
You can use any of the methods I blogged about earlier for pushing your code to the portal:
The files you need to deploy are:
In the portal, once you've uploaded your files, you should have the following structure in the Kudu console:
Running the code for a test, should generate the following result:
The overall benefit to your deployment and Function size can be significant when using this method. It will also simplify your CI/CD with less files to worry about during deployment. For example, my Function size was reduced significantly and I didn't have to worry about
npm restore during the deployment of my Function.
Did you know that we also supported .NET-based pre-compiled Functions now? Check Donna's post here
Make sure you use the comments if you have any questions or problems using my demo. You can download and test the sample code for this Function from GitHub