Turn your Single Page Application into an Artifact with Azure DevOps
Tags: azuredevops, singlepageapplication, devops, nx
Published: 2022-01-06 16:25:57

In order to use the output from a build in Azure DevOps later, you need to publish it as a Build Artifact. This article will show you how to configure that.

This examples uses an Angular based Single Page Application (SPA) build using the [Nx monorepo tools](https://nx.dev), however the general process can be applied to any SPA framework once you know the build commands.

## Create a new Azure Pipeline
1. In Azure DevOps, go to Pipelines > Pipelines
2. Select 'New Pipeline" (or "Create Pipeline if you don't have one)
   ![Arrows pointing to New Pipeline and Create Pipeline button in Azure DevOps](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8r1pgc5jdsvk36tekvnt.png) 
3. Connect to your Repo
   * Mine is in Azure Repos Git, so I will be using that
   ![List of Repo Options in Azure DevOps with Azure Repos Git circled](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s4z5xicsx6zhs8040vvj.png) 
4. Select your Repo
5. Configure your pipeline template
   * I selected the "Node.js with Angular" option for my example, however any of the Node.js options should work
   ![Azure DevOps Pipeline Templates List](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f36hvxa8sqw481vnfrg2.png) 
6. Complete Review, then Save (not "Save and Run") your pipeline
   * I created a new folder for mine and gave it a unique name
   * I also recommend creating a new branch while testing, as best practice

## Install Node, npm, and your Command Line Interface (CLI) 
1. Update the NodeTool task to your Node Version
   1. I used Node 14, as that matches my project's environment
2. Create 'npm install CLI' script task
   1. Add a new `script` task above the 'npm install and build' script task
   2. Set the first line to `npm install -g <ListOfCLIs>` to include the CLI(s) that you will need on the machine to build your project
      1. I needed the Angular (`@angular/cli`) and Nx (`@nrwl/cli`) CLIs for my project
   3. Specify the version of the CLI(s) to match your project
      1. Mine used version 12 for both Angular and Nx
   4. Update the displayName to `npm install <yourCLIName> CLI`
      1. In my example, I used `npm install Angular CLI and Nx CLI`
   6. Final script task should look like:
     ```yaml
     - script: |
         npm install -g @angular/cli@12 @nrwl/cli@12
       displayName: 'npm install Angular CLI and Nx CLI'
     ```
3.  Update the 'npm install and build' script task
    1.  Simplify the task to just `npm install` (we are already install the global tools needed in the step above)
    3.  Task should look like this:
      ```yaml
      - script: |
         npm install
      displayName: 'npm install'
      ```
## Update the Pipeline to Build and Publish
I have two different environments that I wanted to build and publish, 'staging' and 'production', so I am going to do this twice and use separate subfolders for each one. 
1.  Create 'build staging' task
     1.   Copy the 'npm install' script task and paste a new copy
     2.   Replace `npm install` with your project build command
          1.   Mine is `nx build account-info-manager:build --configuration=staging --outputPath=dist/staging`
          2.   **account-info-manager** is my project
          3.   **staging** is a custom configuration defined in my project
          4.   **outputPath** is set to create a separate folder called 'staging' under the typical Angular dist folder
          5. Change **displayName** to 'build staging' (or the name that is applicable for your environment)
2.  Add a Publish Build Artifacts task
     1. Add a Task to the Pipeline by clicking "+ Task"
     2. Search for "Artifacts"
     3. Select the "Publish build artifacts tasks" and click "Add"
        ![Highlight the Publish build artifacts task in the task list](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/71pu2bkzz5cj1ixlf2kr.png)
     4. Set the values based on your build path in the 'build staging' task
        1.   My **Path to publish** is set to `$(Agent.BuildDirectory)/s/dist/staging`
        2.   My **Artifact name** is set to `staging`
        3.   Keep **Artifact publish location** as `Azure Pipelines`
        4.   Click the "Add" button
![Publish build artifact task fields](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0l6w6kf14mhloreb4oey.png)
3. Save your Pipeline
4. Create 'build production' task 
     1. Copy the 'build staging' script task and paste a new copy
     2. Replace `staging` with `production` in your build commands
          1.   Mine is `nx build account-info-manager:build --configuration=production--outputPath=dist/production`
          2.   **account-info-manager** is my project
          3.   **production** is a configuration defined in my project
          4.   **outputPath** is set to create a separate folder called 'production' under the typical Angular dist folder
2.  Add a Publish Build Artifacts task
   1. Set the values based on your build path in the 'build production' task
        1.   My **Path to publish** is set to `$(Agent.BuildDirectory)/s/dist/production`
        2.   My **Artifact name** is set to `production`
        3.   Keep **Artifact publish location** as `Azure Pipelines`
        4.   Click the "Add" button
3. Save, then Run your Pipeline

### You now have an Build Artifact that can be used in Azure DevOps Releases! (Once it completes, of course)

If you would like deploy your newly created builds to Azure Static Web Apps (and have different environments + approval), check out my post on that {% link https://dev.to/blairlierman/static-web-apps-from-azure-devops-releases-2mpa %}