Static Web Apps With APIs With Azure Functions

One of the relatively new services that Azure offers, or at least one that is gaining traction, is the Azure Static Web Pages. This service allows us to host what we know as Single-Page Applications (SPA) in a simple and effective manner. This kind of applications are those focused on the Front-End and are created with JavaScript frameworks/libraries (like Angular, React, Vue, etc) or even with Blazor. And most of the time consuming Back-End services to consume data or some other functionality on the server side.

In this article, we are going to review how we can implement Back-End services in our Azure Static Web Apps with Azure Functions.

Requirements

This time we will primarily use the command line, more specifically PowerShell together with the Command-Line Interface (CLI) tools for Static Web Apps and Azure Functions

You can find more information about in the following links:

Front-End

We'll start creating a vanilla Single-Page Application (SPA), with the purpose of focusing on the Static Web App/Azure Functions subject, but you can create your desired Front-End app.

To start, we need to create a working folder and create a simple HTML file

mkdir swa-vanilla
cd swa-vanilla
New-Item -Path . -Name "index.html"

* Remember we are working with PowerShell that is why we use New-Item command, but you can create the HTML file as you feel more comfortable

And the content for the index.html file is:

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vanilla JavaScript App</title>
</head>
 
<body>
    <main>
        <h1>Vanilla JavaScript App</h1>
        <p>Loading content from the API: <b id="apiresponse">...</b></p>
    </main>
 
    <script>
        (async function () {
            let response = await fetch(`/api/message`);
            let data = await response.text();
            console.log(data);
            document.querySelector('#apiresponse').textContent = data;
        }())
    </script>
</body>
 
</html>

As you can see, in the JavaScript code we are making a call to an API called 'message'. And the reference is even relative, it means, we are expecting to provide the service in the same domain. Let's proceed to create it.

API with Azure Functions

By design, the API needs to be created using Azure Functions. In this case, we'll create an Azure Function and after a simple endpoint called 'message'. Here is where we'll use our first CLI or toolset, the  “Azure Functions Core Tools“.

Inside our working folder

func init 'api' --worker-runtime dotnet-isolated --target-framework net6.0
cd api
func new --name 'message' --template "HTTP trigger" --authlevel "anonymous"

In the first command we created the Azure Function project named 'api' with an isolated execution model in .NET 6 (you can create the project with your own configurations). And a folder with the same name is created, where after we create the 'message' HttpTrigger function.

using System.Collections.Generic;
using System.Net;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
 
namespace api
{
    public class message
    {
        private readonly ILogger _logger;
 
        public message(ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger<message>();
        }
 
        [Function("message")]
        public HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req)
        {
            _logger.LogInformation("C# HTTP trigger function processed a request.");
 
            var response = req.CreateResponse(HttpStatusCode.OK);
            response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
 
            response.WriteString("Welcome to Azure Functions!");
 
            return response;
        }
    }
}

* This code is generated by the CLI, it is being shown just as a reference

Static Web App (local)

With the folder/files structure created we are ready to configure the Static Web App to work on the local machine.

We need to get back to our working folder (remember last action was executed on our 'api' folder) it is time to use the second CLI, the “Static Web Apps CLI (SWA CLI)

cd ..
swa init

On the first parameter, we need to configure what is going to be the name for the configuration. It is usually the folder name or the app name.

After we configure the name, the CLI run an analysis for our code and make some suggestion for the rest of the configuration which we include in the Single-Page App and the Azure Functions. In our case, it will be simple since we are using a vanilla app/static HTML.

Let's analyze these configurations

  • Framework(s): the framework or languages with which our applications are written
  • App location: the folder where the Front-End code is located
  • Output location: the folder where the result of compilation for the Front-End code will be
  • API location: the folder where the Back-End code is located
  • App build command: the Front-End code build command
  • API build command: the Back-End code build command
  • App dev server command: the Front-End code execution command
  • App dev server URL: the Front-End execution URL

And for example, for an Angular app and React app, we'll have configurations like:

Once the configuration is set, the CLI we'll run some steps finishing the option we have:

We'll proceed to build our app and start it

swa build
swa start

So we will see that our application is being executed in the URL http://localhost:4280/

And the result on the Front-End will be like:

And the most interesting thing, the Back-End is server in the same domain with url http://localhost:4280/api/message

Conclusion

In this entry, I tried to show just an introduction to Static Web Apps. In a subsequent post, I will be writing about how we can work with Visual Studio Code, how to configure this service in Azure, and how to create a CI/CD pipeline for Azure DevOps.