Going Serverless with Azure Static Web Apps and Functions for Production ready Scalable Web Applications
With web frameworks like Angular and React gaining traction every day, it has become easier to develop robust and secure web applications and single-page applications that typically connect to a backend API to get its data or perform the business logic. However, maintaining these applications using traditional servers is cost-intensive and cumbersome, especially with high availability and low latency business cases.
What is Serverless?
Serverless is a cloud-native development model that allows developers to build and run applications without having to manage servers.
Microsoft Azure provides services to build, deploy and operate serverless apps on an end-to-end platform to:
- Increase developer velocity by reducing the time spent on tasks that are non-core to the business
- Improve team agility and performance by using a fully managed platform to build, deploy and operate applications
- Improve organisational impact by accelerating time to market
We will today discuss one such service provided by Azure called Azure Static Web App.
What are static web applications?
Static web applications simply put, are web applications with files and assets that do not require server-side rendering. These files can be served as static assets via application server or a distribution service like CDN. Examples include HTML, CSS, JavaScript and Image files. It is important because these static files do not change dynamically per request or require any preprocessing on the server side and are processed only on the web browser.
How are they different from server-side rendered applications?
With server-side rendered web applications, the page is rendered on the application server using technologies like PHP, ASP or JSP and is then a processed HTML response is returned to the web browser. This requires the web server to perform the rendering and preprocessing of the pages which typically involves application business logic. However it has to be noted that, such type of applications can also have some static resources. Hence they are a combination of static resources and server side rendered pages.
Azure Static Web Apps
Traditionally these front-end web applications are served using single or multiple servers with a load balancer managing the server load.
Having a geographically distributed web application is expensive when serving them using the traditional methodology involving multiple application servers and load balancers.
This is where Azure Static Web Apps can help you with a fully managed global distribution of static content to significantly reduce latency and increase throughput for global users. The static application is served faster as its closer to the user geographically.
Azure Static Web Apps can also reduce the deployment and maintenance time and efforts.
A typical development workflow of a web application:
- A source code version control system like Git is used to safe-keep and version control the application code
- A developer will push application code to this repository
- A Continuous Integration (CI) system builds applications from the source code
- A Continuous Deployment (CD) system will push the application build to the application server
With Azure Static Web Apps, steps 3 and 4 are combined and the developer doesn't have to take care of the CI and CD of the application, Azure will.
Application development workflow with Azure Static Web Apps:
- A source code version control like GitHub or Azure DevOps is used to keep the application code
- The Azure Static Web App is configured to watch the code on a preferred branch of the code repository for any new changes
- When new code is pushed, the code is built and deployed to a geographically distributed CDN-like delivery network.
Let us try to build our own static web application using Angular and Node and deploy on Azure Static Web Apps
Prerequisites: In this demo, we will be using Angular to build a sample front-end application. We will use NodeJS to create an API application using Azure Functions. We will be using GitHub as the source code repository. You will also need an Azure account with an Azure subscription. You can try it for free here.
The code used in this demo is available on GitHub here. Feel free to fork it to save time.
Let's get started!
Create a new GitHub repository
If you do not have a GitHub account, create one first. Then, create a new repository. Follow the instructions provided here if you need help.
Clone this repository on your local machine, you will have to link your GitHub account with the local development machine to work with GitHub.
Next, navigate to this cloned directory. I have created a subfolder called StaticWebApps however this is not mandatory
Create an Angular application
If you are familiar with Angular development, then you are right at home. If not, you will get all the required information to get started from the angular website.
I have created an application web-angular as shown below:
The ‘dist’ folder is not created by default unless we run npm run build
If you run the app locally using ng serve
the application should look something like this and we won't be making a lot of changes to the application just yet. The application is typically served at http://localhost4200
Commit this code to the main branch and then push it to the repository.
The code should be visible in your GitHub repository now.
Create a new Azure Static Web App
Login into the Azure portal at https://portal.azure.com
Create a new Resource Group (eg. AzureSamples)
Now create a new Static Web App (search for Static Web App) as shown below and fill in the below details.
Choose Plan type as ‘Free’
Next, select a region for ‘Azure Functions API and staging details’ as shown below.
Select Deployment ‘Source’ as GitHub and connect it to your ‘GitHub account’ as shown below.
Select the ‘Organization’, ‘Repository’ which you created before and the ‘Branch’ (usually, the ‘main’ branch is selected for production deployments) These should be populated automatically and you will only have to select the right one.
Now select the Build Presets as ‘Angular’
Give the ‘App location’ as per your folder structure. Since I have created a subfolder within my cloned directory, I have provided the same.
Leave the ‘Api location’ blank for now. We will come back to it later.
Provide the ‘Output location’ dist/<app-name>
as shown below. The app name may vary based on how you named your angular application.
Click on ‘Review + create’ and the app should get deployed after a few seconds.
Go to the resource group and view the Static Web App, you should see a couple of details in the overview.
The URL is the URL where the web app will be hosted, you should also see the source which is the ‘main’ branch in our GitHub repository.
The deployment history gives information on the deployment runs that have happened through GitHub actions.
Click on the link and it will give you the information and history. The Workflow file can be viewed in your GitHub repository and can also be modified.
Let us make a small change to the Angular app and push the changes. This should reflect back on the deployment soon after the code is committed.
I am going to make one tiny change to the title of the application as shown below and then push the change to the repository.
You will see that a new Workflow run has kicked in and should be complete in a few mins.
Once completed, refresh the application URL to notice the change.
That is how simple it is to push new changes and deploy them to production!
Let us create an API using Azure Functions and Node
Now that we have our front-end up and running, let us create a simple API. Typically, applications get their data from an API. Let’s try to do the same in our sample application.
Azure Function is a serverless service provided by Azure, using which we can execute event-triggered business logic, run background jobs at timely intervals and create simple API endpoints without a complex setup.
Let us create a function, follow the below steps:
- Download and install the Azure Function Core Tools from here.
- Navigate to the root folder of your project (the parent folder of the angular application).
- Run the below command:
func init api --language javascript
Use runtime as ‘node’ and language as ‘javascript’
Once the project is created, you should notice a folder called ‘api’ has been created.
Now let's create a new function. Run the below command:
cd api
once inside the API folder, run:
func new --name message --template "HTTP trigger" --authlevel "anonymous"
Use runtime as ‘node’ and language as ‘javascript’
The content of the folder should look something like this:
Replace the code inside the message/index.js file with the following:
module.exports = async function (context, req) {
context.res.json({text: "Hello from the Function API"});
};
Let’s run this function locally using the command:
func start
The output should look something like this, notice the URL:
If your type in this URL on your browser, you should see the result as shown below:
We have successfully created a function app! We have to make a change in our angular application to call this API.
I have deleted most of the code from the page app.component.html and made one change as shown below:
Replace the code in app.component.ts with the below code:
import { Component } from '@angular/core';@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})export class AppComponent {
apiResult = "..."; constructor(){
this.callApi();
} async callApi(){
var result = await (await fetch(`/api/message`)).json();
this.apiResult = result.text;
}
}
Save the code.
Edit the GitHub workflow file found under .github/workflows/azure-static-web-apps-<DEFAULT-HOSTNAME>.yml and update the api_location to the API folder.
Save the file. Push the changes to the repository.
The GitHub action should kick in and the changes should get deployed to the static web app. Once the deployment has been completed, refresh the URL.
The API works and the front-end is able to connect and receive data from the API. We can further extend the API to connect to a database to meet our business requirements. However, it is out of the scope of this exercise.
Conclusion
We have created a serverless solution that can host both the front-end and an API using Azure Static Web App. This solution is simple to manage as we don't have to maintain complex server configurations or deployments. To know more about Static Web Apps, read the documentation available here.
The code used in the above exercise is available in my GitHub repository which can be found here.