Backend development on Azure Functions with TypeScript

Burak Tasci
Burak Tasci
Published in
6 min readApr 7, 2018

Serverless architecture is without a doubt one of the hottest topics in cloud computing, allowing developers to build and run apps and services without thinking about the servers actually running the code as well as significantly reducing operational costs.

When we initiated a new project a few months ago, I decided to adopt this micro-services model — developing the back-end as a small series of services, each running independently and communicating through HTTP requests.

Then, I had to choose the server-side programming language to develop our backend.

Candidates were C#, TypeScript and Go

Except the last candidate, me and my team were able to work efficiently.

Go was something completely new, and I was considering it for the performance outcomes — it’s lightning FAST. However, there’re no cloud platform providing native support, and getting Go work with wrappers is a total nightmare. Furthermore, package storage is quite distributed (mainly on git repositories) — may lead to missing dependencies.

Go was eliminated.

Well, before making this choice we compared the three major cloud platforms in terms of languages supported, self-manageability and integration with CI processes so that developers could take the responsibility of the DevOps role.

  • AWS Lambda, is regarded as the pioneer of the serverless concept and has integrated it completely with other products and services in its cloud portfolio — having native support for code written in JavaScript, Python, Java and C#, in addition to wrapper support for Go, PHP and Ruby. Furthermore, AWS has a service (CodeDeploy) for automated deployments — integrated to a variety of online services (Github, Jenkins, TeamCity, CircleCI, Travis CI, etc).
  • Azure Functions, Microsoft’s counterpart of AWS Lambda, was created and introduced at the end of March 2016 — allowing functions to be coded in its native languages: C# and F#, as well as in JavaScript and Python. Similar to AWS, Azure has out-of-the-box integration with Github — and it is pretty easy to manage CI-triggered deployments of the code in the cloud.
  • Google was the last to join the serverless scene with Google Cloud Functions. Its current support is very limited, allowing functions to be written only in JavaScript.

The ease of management of functions was something extremely convenient about Azure — compared to AWS’s painstaking processes, as well as Github integration.

I chose Azure over AWS.

Me and the majority of my team were coming from strongly-typed languages like Java/C#, and the project was requiring us to join into full-stack roles.

After a set of discussions, I found out that the use of TypeScript was the best choice: as for being a typed language (without explicitly introducing abstractions), for the syntax allowing us to leverage our Java/C# knowledge to the backend, and its use on the Angular platform — being a full-stack solution.

Since TypeScript is a superset JavaScript, it’s easy to transpile it into JavaScript with a simple build setup (Webpack) and host it on Azure Functions platform — and I chose TypeScript over C# for all the reasons mentioned above.

In praise of TypeScript

Getting started

Enough background, in this article I’m going to walk through how to create a RESTful backend on Azure Functions with TypeScript.

First things first, we need to install the azure-cli to be able to self-host and debug the function apps:

npm install -g azure-cli

As we got the azure-cli running on our development machine, let’s fork the sample repository that I prepared as a reference:

git clone https://github.com/azure-seed/azure-functions-typescript

Now, you should be able to notice our sample function ./src/some-function and its contents (function settings, the function itself and its specs).

If you have a look at the ./tools directory, you’ll notice the build and deployment scripts. Because the Azure Functions portal doesn’t actually support TypeScript, we gottta handle the compilation into JavaScript. Webpack and UglifyJS are our best friends at this point.

So we have all the tooling needed!

Build steps

The build steps and deployment configuration can all be found the azure-seed/azure-functions-typescript repository. Running the following npm commands will compile our function app and generate the output at the ./dist directory and run the function

# dev build
npm run build:dev

The ./dist dist folder contains all the files (host.json, local.settings.json, and function output) to be hosted on the Azure Functions environment. In order to test run the function, you can run the following npm commands.

# run the function locally (azure-cli)
cd dist
func run f

At this point, I assume you’ve got Postman installed on your environment. There’re actually other HTTP testing tools that you can use — but I strongly recommend anyone to stick to Postman.

Testing the function

Let’s perform the following sample request:

GET http://localhost:7071/api/some-function

The sample request should return you the following result with the status code of HTTP 200 (OK).

HTTP 200
{
object: "list",
data: [
{
id: "57ade20771e59f422cc652d9",
object: "someObject",
name: "Azure"
}
],
hasMore: false,
totalCount: 1
}

At this point, we got a working backend

Under the hood

The ./src/some-function/some-function.ts file describes a simple RESTful backend which allows to simulate CRUD operations.

It exports a function named run, which routes the request to the default controller using the GET, POST, PATCH, and DELETE.

export function run(context: Context, req: HttpRequest): any {
let res: HttpResponse;
const id = req.params
? req.params.id
: undefined;
switch (req.method) {
case HttpMethod.Get:
res = id
? getOne(id)
: getMany(req);
break;
case HttpMethod.Post:
res = insertOne(req);
break;
case HttpMethod.Patch:
res = updateOne(req, id);
break;
case HttpMethod.Delete:
res = deleteOne(id);
break;
default:
res = {
status: HttpStatusCode.MethodNotAllowed,
body: {
error: {
type: 'not_supported',
message: `Method ${req.method} not supported.`
}
}
};
}
context.done(undefined, res);
}

To build your codebase out more declarative, easier to maintain and reusable, you may benefit from the azure-seed/azure-functions-ts-essentials project — containing the essential interfaces such as HttpMethod, HttpRequest, HttpResponse, HttpStatusCode.

Azure Functions TS Essentials is the best shorthand around

Last but not least, but there already are two more projects to significantly reduce the amount of boilerplate code (from establishing the connection, to route the requests to the relevant methods and returning the result/result set — ensuring the request payload is formed well) required to implement data access layers for MongoDB and Elasticsearch: azure-functions-mongooser and azure-functions-elasticizer.

I’d love to include more details about the those projects, but it would actually exceed the scope of this article. Soon, you should be hearing about them too on this publication — stay tuned!

Automatic deployment

In this seed, we used Circle-CI (circle.yml here) to run the build tasks and unit tests (using JEST testing framework) before pushing the output files to the prod branch.

Using the Azure Functions console (located in the Platform Features -> Deployment Options of the function app) and setting the automatic deployment settings to use the prod branch.

Go ahead, make my day!

We got our function developed in TypeScript, compiled to JavaScript and automatically deployed to Azure Functions on every push (while build & test succeed) via CI

…now this is a force to be reckoned with!

Burak Tasci (fulls1z3)
https://www.linkedin.com/in/buraktasci
http://stackoverflow.com/users/7047325/burak-tasci
https://github.com/fulls1z3

--

--

Burak Tasci
Burak Tasci

Full-stack software engineer and enthusiastic power-lifter