In my last blog post, I discussed hosting a React application with a subpath. It's a common question I've been getting about Static Web Apps.
Hosting an application with a subpath allows you to host multiple separate websites within the same domain, giving your users the impression that it is one site. Behind the scenes, the one site is composed of multiple 'micro-frontends', which facilitates the development of large websites (independent deployment, separation of domain, etc.). Read up on micro-frontends here!
I recently built this a demo similar to my last blog post with Blazor, so I figured I'd document it formally! In this blog post, I'll demonstrate how we can host a Blazor WASM app with a subpath on Static Web Apps as per this pattern.
The objective
We'll be hosting the Blazor WASM Static Web App at a subpath <hostname>.azurestaticapps.net/<subpath>
, rather than the root domain <hostname>.azurestaticapps.net
. The implementation will be similar to my React implementation from my last blog post.
This implementation focuses on Blazor WASM applications, though you should be able to generalize it to your frontend framework of choice. If you're trying to do this for a React application, checkout my last blog post.
Let's build it out!
The solution
Hosting an application on Azure Static Web Apps with a subpath requires the following:
- The Blazor WASM application must be built with the subpath. This will ensure the Blazor WASM app retrieves assets from the subpath and routes with the subpath.
- The Static Web Apps host must be configured to expect the application in the subpath.
I've built this out with Blazor WASM, and the sample project can be accessed on GitHub here: https://github.com/thomasgauvin/blazor-swa-with-subpath.
The application is also deployed here: https://red-ocean-027945410.2.azurestaticapps.net/app/. As you can see, this Blazor WASM application is hosted at the /app
subpath.
Configuring the Blazor WASM application to have a subpath
We'll start by modifying the Blazor WASM application to support the subpath.
Create a starter Blazor WASM application (if you don't have one already)
Don't have a Blazor WASM application to start with? Create a simple app with the following commands:
- Create a Blazor WASM application:
dotnet new blazorwasm -n blazor-swa-with-subpath
. - Open
blazor-swa-with-subpath
in VSCode. - You can now run the project with
dotnet run
.
Edit your Blazor WASM application to support a subpath (we'll choose app
)
Next, we'll configure our Blazor WASM application to support the app
subpath. This is needed so that your Blazor application can make requests to the right files when it is deployed with a subpath. For this example, we will use subpath app
, though you can choose any subpath for your project.
-
In the blazor-swa-with-subpath.csproj file, add
<StaticWebAssetBasePath>app</StaticWebAssetBasePath>
to the<PropertyGroup>
. This ensures that when you rundotnet publish
, the publish folder is created with the static web assets within anwwwroot/app
folder. Check out the docs of the StaticWebAssetBasePath property. -
In the
wwwroot/index.html
file, change the base href to<base href="/app/" />
. This ensures that requests from your index.html are prepended by/app/
. This will break the default development website served bydotnet run
. You will now have to calldotnet run
with the pathbase argument as such:dotnet run --pathbase=/app
. This will ensure that your Blazor WASM development server hosts your app at the subpath. -
In the
wwwroot/index.html
file, change the script for blazor.webassembly.js to<script src="/app/_framework/blazor.webassembly.js"></script>
. This will also break the default development website served bydotnet run
, so as I mentioned before, you will have to use thedotnet run --pathbase=/app
command instead. -
Build your Blazor project with
dotnet publish -o publish
. This will create apublish
folder, containingwwwroot
folder, which contains folderapp
, which contains the Blazor application. -
Optional step: You may now serve your built Blazor application with the
dotnet-serve
package. Frompublish/wwwroot
, rundotnet serve -o --fallback-file ./app/index.html
. The fallback file indicates the entry point of your Blazor app, in case a user tries to access a specific page of your Blazor app directly. Navigate tohttp://localhost:<PORT>/app
to see your built Blazor app working.
Configure the Static Web Apps resource to host your Blazor WASM app with a subpath
To host your Blazor WASM app with a subpath, you must add the following configurations so that Static Web Apps redirects users to your Blazor app on the /app
path.
The wwwroot folder will be our application folder, as defined by Static Web Apps. It will contain the following: the app
folder (which contains our Blazor application served at the app
subpath (the folder name is the same as the subpath)), index.html
which is needed by Static Web Apps, and staticwebapp.config.json
which contains the necessary redirects and navigation fallbacks for the Blazor app. The index.html
placed in publish/wwwroot
is needed because Static Web Apps requires an index.html file at the base of the application folder.
-
Within
publish/wwwroot
, create anindex.html
file with the following contents:<!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Refresh" content="0; url='/app/'" /> </head> <body> Redirecting to Blazor application </body> </html>
This HTML is needed since Static Web Apps requires an index.html at the root of the project. It redirects requests to
/index.html
(or/
) to/app/
, where our Blazor app is hosted. -
Within
publish/wwwroot
, create astaticwebapp.config.json
file with the following contents:{ "navigationFallback": { "rewrite": "/app/index.html" }, "routes": [{ "route": "/", "redirect": "/app/" }] }
This provides the navigation fallback for the entry-point of the Blazor WASM application. This also redirects customers accessing
/
to/app/
which is the entrypoint of our Blazor WASM application. -
(Optional) Use the
swa cli
to simulate the deployed Static Web Apps experience locally.- From
publish/wwwroot
, runswa start
. This will simulate your Static Web Apps locally, along with thestaticwebapp.config.json
and newly createdindex.html file
. - Open
http://localhost:4280/
in your browser.
Note: If this simulated Static Web Apps environment is not working, debug and resolve before moving onto the next step.
- From
This is akin to a custom build process. In this tutorial, I am completing these steps manually, since it is easier to explain this way. You may consider creating the stub publish/wwwroot/index.html
and placing the staticwebapp.config.json
files as part of a build process/script for automation.
Deploy to Static Web Apps with the SWA CLI
Note: This application requires a custom build process (as done manually above). As such, I will be uploading the built project to my GitHub repository (typically, one wouldn't commit built assets to one's repository, rather these would be built as part of the build pipeline).
For this blog, the custom-built project will be committed and uploaded to the Static Web Apps resource as is. This can be done using either a repository integration for Static Web Apps or the SWA CLI. In either case, the app build would need to be skipped, so that these custom build modifications are kept.
Alternatively, you may add these build customizations to your build scripts, so that you can have this build as part of a CI/CD pipeline.
Below, we show how to upload this project to an Azure Static Web Apps resource with the SWA CLI. If you are considering creating a resource from the Azure Portal instead, ensure that you skip the app build by following the Skip building front-end app guide.
-
Navigate to the
/publish
directory (cd ..
). -
Deploy the contents of
/publish/wwwroot
usingswa deploy wwwroot
.Note that
/publish/wwwroot
should contain theapp
folder, theindex.html
file, and thestaticwebapp.config.json
file. The publish folder has been provided in this repository for reference. -
Browse you app at the deployed project link indicated by the
swa cli
. For instance,https://red-ocean-027945410.2.azurestaticapps.net
.
Limitations
Hosting applications with a subpath in this manner has some limitations. Since we are hosting the application with a different path, it must be noted that some features of Static Web Apps will not use this subpath.
- Static Web Apps backend integration allows you to have a managed functions backend or to link an API backend, and will route requests to the
/api
path to the backend. The path of/api
cannot be changed, and as such, if you are hosting an application on/app
, these will be making API calls to/api
rather than/app/api
. This could cause conflicts if you intend to host multiple SWAs on the same domain. - Static Web Apps has built-in authentication, which relies on special paths such as the
/.auth
path. This cannot be changed to the/app/.auth
path for instance, so authentication using the built-in authentication could cause conflicts between applications.
These limitations can be circumvented by opting out of these Azure Static Web Apps features, for instance by calling APIs directly and using another authentication provider.
Conclusion
In this blog post, we successfully built and deployed a Blazor WASM app with a subpath to Azure Static Web Apps. Although we focused on Blazor, the steps to configure the Static Web App and build the project can be adapted to any web app. Hosting an application with a subpath can be quite useful when trying to host multiple Static Web Apps within the same domain, so this solution helps to enable those use cases.
Sources:
https://stackoverflow.com/questions/66862350/how-to-change-the-base-url-of-a-blazor-wasm-app, https://github.com/dotnet/AspNetCore.Docs/issues/26170, https://github.com/dotnet/AspNetCore.Docs/pull/26198/files