With ASP.NET Blazor WebAssembly (WASM) you can create .NET web applications that run completely inside of the browser sandbox. The published output of a Blazor WASM project are static files. Now that you can run .NET web applications without server-side code, you can deploy these applications to various static site hosts such as:
I wasn't going to cover Heroku because they don't offer static site hosting. But last week, I received a comment on one of my YouTube videos asking for a tutorial on deploying Blazor WASM to Heroku. Even though there's no official static site offering by Heroku yet, Heroku does have an experimental "buildpack" for static sites.
If you have a request, leave a comment (YouTube | Facebook) or sent a tweet and I'll happily consider it.
This walkthrough will show you how to deploy Blazor WASM to Heroku using the Heroku CLI and the 'heroku-buildpack-static'. Heroku is a cloud platformโnow owned by Salesforceโfor building apps using their PaaS services.
This guide will walk you through these high-level steps:
- Create Blazor WebAssembly project
- Create a new Heroku application using Heroku CLI
- Configure Heroku application for static site hosting
- Deploy Blazor application using Heroku CLI
Prerequisites :
- .NET SDK (download)
- Heroku Account
- Heroku CLI (download)
- OS with support for .NET and Heroku CLI (this tutorial has been verified using Windows 10 & Ubuntu 18.04)
You can find the source code for this guide on GitHub.
Create Blazor WebAssembly project
Run the following commands to create a new Blazor WASM project:
mkdir BlazorWasmHeroku
cd BlazorWasmHeroku
dotnet new blazorwasm
To give your application a try, execute dotnet run
and browse to the URL in the output (probably https://localhost:5001):
dotnet run
# Building...
# info: Microsoft.Hosting.Lifetime[0]
# Now listening on: https://localhost:5001
# info: Microsoft.Hosting.Lifetime[0]
# Now listening on: http://localhost:5000
# info: Microsoft.Hosting.Lifetime[0]
# Application started. Press Ctrl+C to shut down.
# info: Microsoft.Hosting.Lifetime[0]
# Hosting environment: Development
# info: Microsoft.Hosting.Lifetime[0]
# Content root path: C:\Users\niels\source\repos\BlazorWasmHeroku
# info: Microsoft.Hosting.Lifetime[0]
# Application is shutting down...
Optional: You can use the dotnet publish
command to publish the project and verify the output:
dotnet publish
# Microsoft (R) Build Engine version 16.8.0+126527ff1 for .NET
# Copyright (C) Microsoft Corporation. All rights reserved.
#
# Determining projects to restore...
# All projects are up-to-date for restore.
# BlazorWasmHeroku -> C:\Users\niels\source\repos\BlazorWasmHeroku\bin\Debug\net5.0\BlazorWasmHeroku.dll
# BlazorWasmHeroku (Blazor output) -> C:\Users\niels\source\repos\BlazorWasmHeroku\bin\Debug\net5.0\wwwroot Optimizing assemblies for size, which may change the behavior of the app. Be sure to test after publishing. See: https://aka.ms/dotnet-illink
# Compressing Blazor WebAssembly publish artifacts. This may take a while...
# BlazorWasmHeroku -> C:\Users\niels\source\repos\BlazorWasmHeroku\bin\Debug\net5.0\publish\
In the publish directory, you will find a web.config file and a wwwroot folder. The config file helps you host your application in IIS, but you don't need that file for static site hosts. Everything you need will be inside of the wwwroot folder. The wwwroot folder contains the index.html, CSS, JS, and DLL files necessary to run the Blazor application.
Create and configure Heroku application
You need to log in before you can do anything with the Heroku CLI. Run the following command:
heroku login
The CLI will print a URL where you need to login to Heroku. If you can't use a web browser on the machine, you can also login using your username, password, and your second factor by passing in the -i
argument:
heroku login -i
You can use the heroku create
to create a new application, but you'll also need to capture the Application ID to specify the application in future commands.
Run the following command using PowerShell or Bash:
PowerShell :
$AppId = (heroku create --json | ConvertFrom-Json).id
By passing in the --json
argument, the Heroku CLI will return the result as JSON. This JSON is converted to an object using the built-in ConvertFrom-Json
cmdlet.
From the object, the id
property is grabbed and stored in the $AppId
variable.
Bash :
AppId=$(heroku create --json | jq -r '.id')
By passing in the --json
argument, the Heroku CLI will return the result as JSON. The JSON is passed to the jq
utility which queries the id property which is stored in the AppId
variable.
You'll need to install the jq
utility if you don't have it on your machine already.
Configure the app to use the 'heroku-buildpack-static' buildpack:
heroku buildpacks:set https://github.com/heroku/heroku-buildpack-static -a $AppId
This buildpack will wire up all the static hosting functionality for your Heroku application.
The static website will require some configuration which can be generated by the 'heroku-cli-static' plugin. Run the following commands to install the plugin into your Heroku CLI:
heroku plugins:install heroku-cli-static
Run the following command to create the 'static.json' configuration file:
heroku static:init
# ? Enter the directory of your app: release/wwwroot
# ? Drop `.html` extensions from urls? Yes
# ? Path to custom error page from root directory: index.html
The command will ask you some questions. Answer them like this:
- Enter the directory of your app: release/wwwroot This is the location where you will publish the Blazor WASM application later.
- Drop
.html
extensions from URLs? Yes - Path to custom error page from root directory: index.html
This command will have created the following 'static.json' file:
{
"root": "release/wwwroot",
"clean\_urls": true,
"error\_page": "index.html"
}
Deploy Blazor WASM to the Heroku application
Run the following command to publish the Blazor WASM project:
dotnet publish -c Release -o release
The c-argument tells the CLI to build in Release configuration. The o-argument tells the CLI to put the output in the release folder.
Run the following command from the 'heroku-cli-static' plugin to deploy your Blazor app to your Heroku application:
heroku static:deploy -a $AppId
Navigate to your application using a web browser and verify your Blazor WASM application is returned and everything is working.
Almost everything that is. When you navigate to the counter page and refresh the page, you will get a 404 error.
Rewrite all requests to index.html
To fix the 404 issues, you need to tell the static Heroku app to rewrite all requests to index.html. You can do this by adding 'routes' to the 'static.json' configuration file:
{
"root": "release/wwwroot",
"clean\_urls": true,
"error\_page": "index.html",
"routes": {
"/\*\*": "index.html"
}
}
The '/**' route will match all requests and rewrite them to 'index.html'. Here's a PowerShell and Bash snippet to make the changes to your 'static.json' file:
PowerShell:
$StaticConfig = Get-Content ./static.json | ConvertFrom-Json
$StaticConfig | Add-Member -NotePropertyName "routes" -NotePropertyValue @{"/\*\*" = "index.html"}
Set-Content ./static.json -Value $($StaticConfig | ConvertTo-Json)
Bash:
echo $(cat static.json | jq '.routes={"/\*\*": "index.html"}') > static.json
Run the deploy command again for the changes to take effect:
heroku static:deploy -a $AppId
When you refresh the counter page now, you will not get any 404 errors anymore.
Next Steps
Now that you have learned how to create and deploy a static web application to Heroku, you can use this knowledge to automate the deployment aspect inside a continuous deployment (CD) pipeline.
The implementation details for every CI/CD platform will be different, but the high-level steps for a CD pipeline would be:
- Checkout code from Git
- Install the .NET SDK
- Run the
dotnet publish
command - Install the Heroku CLI
- Install the 'heroku-cli-static' plugin
- Authenticate to Heroku using API token or SSH key
- Run the
heroku static:deploy
command
Let me know what other guides you would like to see by leaving a comment (YouTube | Facebook) or sending a tweet. Cheers!
Top comments (0)