JavaScript Function Apps in Azure

There is not a lot of stuff around to guide you through the process of deploying JavaScript Function Apps to Azure, so I had to go through a lot of trial and error in completing this process. But the process is definately not that complicated, so I decided to list my steps below.

As per the Microsoft definition, you can export a JavaScript function that executes when triggered within a set folder structure. At the root of the project, there's a shared host.json file that can be used to configure the function app.

Folder Structure

PROJECT NAME:
- timerTrigger
  > index.js
  > function.json
- queueTrigger
  > index.js
  > function.json
azure-pipelines.yml
host.json
package.json

Host file (host.json)

This file should be in the root of the folder, it basically controls how the application is interpreted by the Azure hosting environment.

{
  "version": "2.0",
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[1.*, 2.0.0)"
  }
}

Sample Function (index.js)

The JavaScript functions can be very simple as you can see by the example below, you can even import external libraries into them like axios or moment.

const moment = require('moment');

module.exports = function(context) {
  console.log(`Triggered Function at ${moment.toISOString()}`);
};

Build & Deploy

It is fairly simple to deploy a project like this to Azure. You create a YAML file in the root of your project called azure-pipelines.yml It will contain two different stages, a Build stage and a Deployment stage.

Build Stage

stages:
  - stage: Build
    displayName: Build Stage
    jobs:
      - job: Build
        displayName: Build
        pool:
          vmImage: 'ubuntu-latest'

        steps:
          - task: NodeTool@0
            inputs:
              versionSpec: '10.x'
            displayName: 'Install Node.js'

          - script: |
              npm install
            displayName: 'Build Functions'

          - task: ArchiveFiles@2
            displayName: 'Archive files'
            inputs:
              rootFolderOrFile: '$(System.DefaultWorkingDirectory)'
              includeRootFolder: false
              archiveType: zip
              archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
              replaceExistingArchive: true

          - upload: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
            artifact: drop

What is this Stage doing?

It pulls the code from a git repository, sets the correct build image, ubuntu-latest, installs Node on the image, runs npm install for all your dependencies, and then archives the files to a drop location to be picked up by the deployment stage.

Deployment Stage

  - stage: Deploy
    displayName: Deploy Stage
    dependsOn: Build
    condition: succeeded()
    jobs:
      - deployment: Deploy
        displayName: Deploy
        environment: 'function-app'
        pool:
          vmImage: 'ubuntu-latest'
        strategy:
          runOnce:
            deploy:
              steps:
                - task: AzureFunctionApp@1
                  displayName: 'Deploy to Azure Functions'
                  inputs:
                    azureSubscription: '$(azureSubscription)'
                    appType: functionAppLinux
                    appName: 'function-app'
                    package: '$(Pipeline.Workspace)/drop/$(Build.BuildId).zip'

What is this Stage doing?

It takes the Zipped files that were the result of npm run install && npm run build and deploy to the Azure Function App that you set up in the Portal. This state only runs if the build stage is completed successfully.

Wrap Up

And that is pretty much it ... you now have a simple JavaScript function can be run in the Azure Cloud, either on a schedule, or respond to events in the Azure Cloud environment.

You can see a simple functioning application on Github.

If you liked this article and would like to get in contact with me, you can either send me an email or call me on my mobile.

I feel lucky to be working with these companies :)