React js ➡ Azure Devops ➡ Azure Storage ➡ Azure CDN (Part 1/2)
Tags: azure, react, devops
Published: 2020-05-20 20:09:09

# How to use Azure DevOps to build and release your static React js Web App to an Azure Storage Account which is made public using an Azure CDN profile, part 1:

Part 1 guides you step by step through a simple process of using Azure DevOps to build and release a static React js Web App (or any other Node.js based Web App), which is then hosted using an Azure Storage Account.

~~Part 2 guides you through creating an Azure CDN profile and connecting it to our storage account and release pipeline.~~

> ⚠ **Part 2 is not yet available and might not will be finalized, as of writing this post in January 2020, [Azure Static Web Apps](https://docs.microsoft.com/en-us/azure/static-web-apps/overview) was not yet publicly announced. Azure Static Web Apps was globally announced yesterday at the BUILD 2020 (19th of May, 2020) and is basically a very similar approach to the approach explained in this post with the difference that [Azure Static Web Apps](https://docs.microsoft.com/en-us/azure/static-web-apps/overview) might be more comfortable to use, as it has all components of the explained approach in a single service. At the writing of this (20th of May, 2o20) [Azure Static Web Apps](https://docs.microsoft.com/en-us/azure/static-web-apps/overview) is in preview and able to use, give it a try. I will not remove this blog post yet, so this alternative approach is explained for the moment. Please keep this in mind when reading this post, thank you!** ⚠

## ✅ Requirements:
1. Azure Account ([If you are a student, click here to find out how to get free Azure Ressources](https://link.medium.com/ANGMMY2P5T))
2. A React Web App
3. [An Azure DevOps Service Account](https://azure.microsoft.com/de-de/services/devops/)

## Table of Contents

1. [Azure Storage Account](#1-azure-storage-account)
2. [Build Pipeline](#2-build-pipeline)
3. [Release Pipeline](#3-release-pipeline)

## 1. Azure Storage Account

First we need to create an Azure Storage Account that is used to host our React Web App later on using the static website feature of the Storage Account.

Login to the Azure portal and start the process of creating an new Storage Account. Choose the wanted subscription, name, location, replication level etc. Just make sure, to choose `StorageV2` as account type.

![Storage Account Creation](https://github.com/Jakob-vdH/BlogPosts/blob/master/devTo/reactStorageAccount/media/01-createAzureStorageAccount.jpg?raw=true)

When the Storage Account is created, open the resource and open the `Static Website` settings in the left sidebar.
Enable the feature and set the 'Index document name' and 'Error document path' to your index file of your react js build. In my case it is `index.html`.

![Enabling static website](https://github.com/Jakob-vdH/BlogPosts/blob/master/devTo/reactStorageAccount/media/02-staticWebsite.jpg?raw=true)

After saving the settings, Azure will give you an primary endpoint under which the website will be available in the end. Moreover, it gives you the Azure Storage container in which the website's files need be uploaded for being available at the endpoint later on.

Before setting up our build and release pipeline we need to save a few keys and ids of the storage account.
We should remember the following settings for our release process:
- the `STORAGE_ACCOUNT_NAME` you set when creating the Storage Account
- the `STORAGE_ACCOUNT_KEY` which can be found in the `Access Keys` settings of the Storage Account. You can either pick key1 or key2. 

You can either leave the page open or save these settings. I will refer to them later on as `STORAGE_ACCOUNT_NAME` and `STORAGE_ACCOUNT_KEY`.

![Access Keys](https://github.com/Jakob-vdH/BlogPosts/blob/master/devTo/reactStorageAccount/media/03-keys.jpg?raw=true)

## 2. Build Pipeline

Now, let's head over to our Azure DevOps Account to create a build pipeline.

Open the pipelines menu and create a new pipeline.

![Create new pipeline](https://github.com/Jakob-vdH/BlogPosts/blob/master/devTo/reactStorageAccount/media/04-newpipeline1.jpg?raw=true)

To make creating the build process for the first time a bit easier choose `Use the classic editor`. You can still get the Yaml file of our build process afterwards for future processes.

![Activating the classic editor](https://github.com/Jakob-vdH/BlogPosts/blob/master/devTo/reactStorageAccount/media/05.classciEditor.jpg?raw=true)

After that, choose the your respository for example on Github and set a default branch for manual and scheduled builds (for example `master`, depending on your branch structure).
Having set up the source of our build, we are able to choose a template, but we want to build our pipeline from an empty job, as seen in the screenshot.

![Start with an empty job](https://github.com/Jakob-vdH/BlogPosts/blob/master/devTo/reactStorageAccount/media/06-emptyJob.jpg?raw=true)

Set the name of your pipeline (for example `Build react-<app name>`) and set an agent specification. 

>ℹ: I like to use `vs2017-win2016`, but you can also choose `ubuntu-18.04` for example, which will also work with the standard setup we are doing in this guide.

Then click on add task (take a look at the screenshot if you have not build a pipeline with the visual editor before).

![Adding a new task](https://github.com/Jakob-vdH/BlogPosts/blob/master/devTo/reactStorageAccount/media/07-pipenlineSettings.jpg?raw=true)

By using the search in the task list, you can find and add the `npm` task which allows you to run all npm commands.
For the sample project of this guide I only need to run `npm install` and `npm run build`. If you have further commands that need to be run before the build you can add them here, like setting environmental variables or running additional npm commands.

Add `npm install` and `npm run build` as npm task as shown in the screenshots below.

![Npm install](https://github.com/Jakob-vdH/BlogPosts/blob/master/devTo/reactStorageAccount/media/08-npmInstall.jpg?raw=true)


![Npm run build](https://github.com/Jakob-vdH/BlogPosts/blob/master/devTo/reactStorageAccount/media/09-npmRunBuild.jpg?raw=true)

After the npm run build command finished, the build files will be available in the Build.SourcesDirectory of the build process. In this sample the build will be available in the `build` folder accessible via `$(Build.SourcesDirectory)/build`. Depending of your project the build files could also lie for example under `$(Build.SourcesDirectory)/dist`.
This is important for our next step as we will archive the build folder and drop it as artifact, which the release then will be able to use.

Firstly, add the `Archive files` task and configure it with the reference to the build folder as `Root folder or file to archive` - in our case `$(Build.SourcesDirectory)/build` - and $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip` as the `Archive file to create`. Take the screenshot below as reference.

![Archive Files](https://github.com/Jakob-vdH/BlogPosts/blob/master/devTo/reactStorageAccount/media/10-archiveFiles.jpg?raw=true)

Secondly, add the `Publish build artifacts` task, which has no settings that we need to change.

![Publish Artifact: drop](https://github.com/Jakob-vdH/BlogPosts/blob/master/devTo/reactStorageAccount/media/11-drop.jpg?raw=true)

Now our build pipeline is finished and we create our release. 
‼ Do not forget to save the pipeline.

## 3. Release Pipeline

To create a release choose the `Releases` menu in the left sidebar and create a new release pipeline (shown in the screenshot below).

![Create a new release pipeline](https://github.com/Jakob-vdH/BlogPosts/blob/master/devTo/reactStorageAccount/media/12-releases.jpg?raw=true)

After creating a new release pipeline start with an `Empty job` again and add an artifact.

![Add an artifact](https://github.com/Jakob-vdH/BlogPosts/blob/master/devTo/reactStorageAccount/media/13-artifact.jpg?raw=true)

Choose the build pipeline we just created as source for the release's artifact.

![Choose build pipeline](https://github.com/Jakob-vdH/BlogPosts/blob/master/devTo/reactStorageAccount/media/14-artifactMenu.jpg?raw=true)

Add a trigger to the release by enabling the `Continuous deployment trigger` and open the taks of the first and currently only stage of our release pipeline, as shown in the screenshot below.

![Add a trigger](https://github.com/Jakob-vdH/BlogPosts/blob/master/devTo/reactStorageAccount/media/15-trigger.jpg?raw=true)

Add a `Extract files` tasks and set the `Archive file patterns` to `**/$(Build.BuildId).zip` and the `Destination folder` to `$(System.DefaultWorkingDirectory)/build`.

![Extract files](https://github.com/Jakob-vdH/BlogPosts/blob/master/devTo/reactStorageAccount/media/16-extractFile.jpg?raw=true)

Now we will deal with updating the files in our Azure Storage Account. Before uplaoding the files we first have to remove all files that are currently in the $web container of the Storage Account.

We can do that via the Azure CLI. Add the `Azure CLI` task and set the following properties:
- **Azure subscription**: Choose the Azure subscription of your storage account. (ℹ You might have to authorize a connector.)
- **Script Location**: 'Inline Script'
- **Inline Script**: `az storage blob delete-batch --account-name <STORAGE_ACCOUNT_NAME> --account-key  <STORAGE_ACCOUNT_KEY>  --source $web` - remember the storage account information from step 1? You need to set these here.

![Delete current files](https://github.com/Jakob-vdH/BlogPosts/blob/master/devTo/reactStorageAccount/media/17-removeFilesStorage.jpg?raw=true)

For uploading our build files we will use another `Azure CLI` task with the following properties:
- **Azure subscription**: Choose the Azure subscription of your storage account. (ℹ You might have to authorize a connector.)
- **Script Location**: 'Inline Script'
- **Inline Script**: `az storage blob upload-batch --account-name <STORAGE_ACCOUNT_NAME> --account-key  <STORAGE_ACCOUNT_KEY> --destination $web --source $(System.DefaultWorkingDirectory)\build\build`

![Upload new build](https://github.com/Jakob-vdH/BlogPosts/blob/master/devTo/reactStorageAccount/media/18-uploadingFilesStorage.jpg?raw=true)

Now you can access your React app via the primary endpoint. The next step would be to connect the static website with a content delivery network, which additionally gives us the option to connect a custom domain and a SSL certificate for the custom domain.