Developing Azure Functions in Node.js is a fantastic way to build scalable and event-driven serverless applications.
You can create Azure Functions using the Azure Functions Core Tools, which allows you to create and deploy Functions locally before moving them to the cloud.
To get started, you'll need to install the Azure Functions Core Tools and the Azure Functions Core Runtime.
Getting Started
To get started with Azure Functions Node, you'll need a few things. You'll need a RavenDB Cloud account or self-hosted client certificate, and Azure Function Core Tools 4.x+. You'll also need Git and Node.js 18+.
If you're new to Azure Function local development, check out the Getting started guide to set up your toolchain.
You can create a new repository derived from the RavenDB Azure Function template on GitHub, or clone and push it to a new repository. This template is only for testing purposes, so you'll need to configure the connection to your existing RavenDB database.
Azure Functions Basics
Azure Functions is a serverless compute service provided by Microsoft Azure, allowing you to run small pieces of code, known as functions, in response to events triggered by various sources.
You can create functions in various languages, including Node.js, and deploy them to the cloud, eliminating the need to manage infrastructure.
Functions can be triggered by events such as HTTP requests, timer triggers, or changes to storage blobs.
Durable, Stateful
Durable Functions in Azure allow you to create long-running functions.
These functions can retain state, making it easier to manage complex tasks.
You can create your first durable function in JavaScript, which is a great starting point.
Durable Functions are designed to handle tasks that take a long time to complete.
They can even manage tasks that need to be resumed from where they left off.
This is particularly useful for tasks that involve multiple steps or require human intervention.
With Durable Functions, you can write code that feels more like traditional programming.
You can write loops, conditional statements, and even use variables to store state.
This makes it easier to build robust and scalable applications.
Bindings Data Type
Bindings Data Type is a crucial aspect of Azure Functions, and it's essential to understand how it works. In Node.js, only string and binary data types are supported, with stream not being an option.
You can change the data type of an input binding using the dataType property, but be aware of its limitations. The dataType property is ignored for HTTP inputs, and instead, you should use properties on the request object to get the body in your desired format.
In the example of a storage queue trigger, setting dataType to binary changes the type of myQueueItem from a string to a Node.js Buffer. This is a powerful feature that allows you to work with different data types in your Azure Functions.
Here's a quick rundown of the data types supported in Node.js and HTTP inputs:
- Node.js: string and binary
- HTTP: properties on the request object
Remember to use the dataType property with caution, and always check the data type of your input binding to ensure it matches your needs.
JavaScript for HTTP Requests
JavaScript for HTTP Requests is a crucial aspect of Azure Functions, and understanding its basics is essential for building robust and efficient functions. You can create a simple JavaScript function for HTTP requests, as shown in Example 2.
This function is an exported asynchronous function with request and context information. The function code is visible in the Azure portal, and it's a great starting point for building your own HTTP requests.
The request and response objects are used to represent HTTP messages in HTTP and webhook triggers. These objects are a subset of the fetch standard, utilizing Node.js's undici package. This means you can rely on the standard fetch API to handle HTTP requests and responses.
Azure Functions supports HTTP streams, a feature that enables real-time exchange and interaction between client and server over HTTP. This feature is particularly useful for processing large data, streaming OpenAI responses, and delivering dynamic content. However, it's only available in the v4 model, so be sure to upgrade if you want to use HTTP streams.
Here's a brief summary of the properties you can use to handle the message body in HTTP streams:
In terms of context, the InvocationContext class has several properties that provide information about the current function invocation. These properties include invocationId, functionName, extraInputs, extraOutputs, retryContext, traceContext, and triggerMetadata.
Version
Azure Functions supports multiple versions of the Node.js programming model, each with its own set of supported Node.js versions.
The supported versions are listed in a table, which shows that the 4.x programming model supports Node.js versions 20.x and 18.x, while the 3.x model supports versions 20.x, 18.x, 16.x, and 14.x.
You can see the current Node.js version being used by the runtime by logging process.version from any function.
The Node.js version can be set using the WEBSITE_NODE_DEFAULT_VERSION application setting on Windows or the linuxfxversion site setting on Linux.
Here's a quick rundown of how to set the Node.js version on Windows:
- Use the Azure CLI to update the WEBSITE_NODE_DEFAULT_VERSION application setting.
- Verify that your function app is running on the latest version of the Functions runtime.
- Update the Node.js Version to the latest version in the Azure portal.
- Save your changes and restart your function app.
Alternatively, you can use the Azure CLI to set the Node.js version on Linux by updating the base image of the Linux function app.
Here's a summary of the supported Node.js versions for each programming model:
Context.ExecutionContext
The context.executionContext object is a crucial part of Azure Functions, providing valuable information about the current function invocation. It's always the first argument passed to your handler.
The context.executionContext object has several properties, including invocationId, functionName, and functionDirectory. These properties give you insights into the current function invocation, such as the invocation ID, function name, and folder containing the function.json file.
Here are the properties of context.executionContext:
The retryContext property within context.executionContext provides additional information about the current retry attempt. It includes properties like retryCount, maxRetryCount, and exception.
The retryContext object has the following properties:
Understanding context.executionContext is essential for building robust and reliable Azure Functions.
Logging
Logging is crucial in Azure Functions, and it's surprisingly easy to get right. You can use context.log() to write logs, which integrates with Azure Application Insights for better capture and analysis of your function app logs.
Azure Application Insights provides facilities for collection, visual rendering, and analysis of both application logs and your trace outputs. To learn more, see monitoring Azure Functions.
Using context.log() has its advantages, such as associating logs with a specific function, which is essential for debugging and troubleshooting.
The Node.js console.log method is an alternative, but it's not recommended as it tracks logs at the app-level and won't be associated with any specific function.
You can write logs at specific levels using the following methods: context.log.error(), context.log.warn(), context.log.info(), context.log.verbose(), context.trace(), context.debug(), context.info(), context.warn(), and context.error().
Here's a list of the available log levels and their descriptions:
Configuration and Settings
Configuration and Settings is a crucial part of Azure Functions, and you'll want to get it right to ensure your functions are secure and running smoothly. The first step is to configure common security settings, which includes configuring settings, API CORS, TLS/SSL settings for HTTPS, and deployment slots.
You should enable HTTPS only in the TLS/SSL settings, as your Function app is hosted on a secure subdomain. This allows you to use it immediately and delay purchasing a domain name and certificate until you're ready. Configuration settings, such as API CORS, should be configured to keep your Azure Function secure.
To configure log level, you can use the logging.logLevel property in the host.json file. This property lets you define a default level applied to all functions, or a threshold for each individual function. To set the threshold, use the logging.logLevel property in the host.json file.
Here's a summary of the common security settings you need to configure:
- Configuration settings
- API CORS - configure your client domains
- TLS/SSL setting for HTTPS - enable HTTPS only
- Deployment Slots - create a deployment slot and swap it to production when ready
You can also configure application settings, such as DB_URLS and DB_NAME, by adding app settings in the Azure Portal. These values will override local.settings.json once deployed on Azure.
Configure Log Level
Configuring the log level in Azure Functions is a breeze. You can define the threshold level to be used when tracking and viewing logs by using the logging.logLevel property in the host.json file.
This property lets you define a default level applied to all functions, or a threshold for each individual function. To learn more, see How to configure monitoring for Azure Functions.
You can choose from various log levels, including error, warning, information, and verbose. Each log level has its own specific method for writing logs, making it easy to customize your logging needs.
Here's a breakdown of the available log levels and their corresponding methods:
You can also use other methods like context.trace() and context.debug() to write logs at specific levels.
Configuring Application Settings
Configuring Application Settings is a crucial step in setting up your Azure Function. You can access the Application Settings menu in the Azure Portal to add settings for your Function App.
To add an app setting, click on the Application Settings menu and then add a new setting. For example, you can add an app setting for DB_URLS with a comma-separated list of RavenDB node URLs to connect to.
These values will override local.settings.json once deployed on Azure. This is a great feature that allows you to easily switch between different configurations without having to re-deploy your code.
You can also use environment variables to configure your APM agent. Open the Configuration > Application settings for your Function App in the Azure Portal and set the environment variables as needed.
For local testing, you can set these environment variables in your terminal or in the "local.settings.json" file. This is a convenient way to test your Function App without having to deploy it to Azure.
Here are some common application settings you may need to configure:
By configuring these application settings, you can ensure that your Azure Function is properly set up and running smoothly.
Configure Entry Point
When working with functions, it's essential to configure the entry point correctly. The function.json properties scriptFile and entryPoint can be used to configure the location and name of your exported function.
If you're using TypeScript, the scriptFile property is required and should point to the compiled JavaScript. This allows you to export your function and make it accessible to others.
To configure the entry point, you need to specify the name of your exported function using the entryPoint property. This is where you determine what action your function will perform.
The scriptFile property is particularly important when working with TypeScript, as it ensures that your function is exported correctly.
Enable Streams
To enable streams in your function app, you'll need to make a few tweaks to your settings. First, if you plan to stream large amounts of data, you'll want to modify the FUNCTIONS_REQUEST_BODY_SIZE_LIMIT setting in Azure to increase the maximum body size allowed.
To do this, you can simply update the setting to a higher value, such as 104857600, which allows for requests up to ~100 MB in size. This is the default maximum body size allowed, but you can adjust it as needed.
For local development, you'll also need to add the FUNCTIONS_REQUEST_BODY_SIZE_LIMIT setting to your local.settings.json file. This will ensure that your local environment is configured to handle large data streams.
Once you've made these updates, you can enable HTTP streams in your app by adding the following code to any file included by your main field: const { app } = require('@azure/functions'); app.setup({ enableHttpStream: true });. This will allow your app to take full advantage of the HTTP streaming feature.
Setting the Version
To set the Node.js version for your function app, you need to consider the OS on which it runs. For Windows, the Node.js version is set by the WEBSITE_NODE_DEFAULT_VERSION application setting, which can be updated using the Azure CLI or in the Azure portal.
If your function app is running on Linux, the Node.js version is set by the linuxfxversion site setting, and you'll need to use the Azure CLI to update it.
To update the Node.js version for a Windows function app using the Azure CLI, run the command az functionapp config appsettings set, which sets the WEBSITE_NODE_DEFAULT_VERSION application setting to the supported LTS version of ~20.
For Linux function apps, you can't change the Node.js version in the Azure portal if it's running in a Consumption plan. Instead, use the Azure CLI to update the Node.js version by running the command az functionapp config set, which sets the base image of the Linux function app to Node.js version 20.
Here's a summary of how to update the Node.js version for function apps running on different platforms:
After updating the Node.js version, your function app will restart.
Context.Bindings
Context.Bindings is used to read inputs or set outputs, making it an essential tool for managing data flow in your applications.
It's especially useful in storage queue triggers, where it allows you to copy a storage blob input to a storage blob output.
Context.Bindings can also be used with binding expressions, which enable you to dynamically replace placeholders in your code with actual values from the queue message's content.
For example, in a storage queue trigger, you can use context.bindings to copy a storage blob input to a storage blob output, with the queue message's content replacing {queueTrigger} as the file name to be copied.
Frequently Asked Questions
What language does Azure Functions use?
Azure Functions support a range of languages including C#, F#, JavaScript, and more. Discover the full list of supported languages and create scalable serverless applications with Azure Functions.
Sources
- https://learn.microsoft.com/en-us/azure/developer/javascript/how-to/develop-serverless-apps
- https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-node
- https://earthly.dev/blog/azure-functions-node/
- https://ravendb.net/docs/article-page/6.2/nodejs/start/guides/azure-functions/overview
- https://www.elastic.co/guide/en/apm/agent/nodejs/current/azure-functions.html
Featured Images: pexels.com