As a product manager for Azure Static Web Apps, I'm always tinkering with new ways of using it and trying out different implementations based on questions that come up in our community GitHub.
The objective
Recently, I've been exploring hosting Static Web Apps with subpaths, such that the static site in question is hosted at <hostname>.azurestaticapps.net/<subpath>
, instead of <hostname>.azurestaticapps.net
. This is something that I've had a few questions about, so I decided to implement and document the solution.
In this article, I'll be documenting how to build a React application with a subpath and how to host it on Azure Static Web Apps with that subpath as well. While this solution will focus on the React implementation, you can adapt this to your own frontend framework as well.
Let's jump into it!
The solution
Hosting an application on Azure Static Web Apps with a subpath requires you to configure 3 things:
- Your React application must be configured to build and request assets to your subpath.
- Your Azure Static Web Apps deployment must be configured to serve your application from the subpath.
- Your React application must be configured to route with the expected subpath
I've created a GitHub repository for this project, which you can try out on your own.
The application is also deployed here: https://lively-smoke-0e4dd4a10.2.azurestaticapps.net/foobar. As you can see, the React application is hosted at the /foobar
subpath.
Configuring the React application to have a subpath
The first step will be to configure your React application to accept the subpath. For this case, we'll be using a sample React application created with create-react-app
since it's the most common tool used in existing React projects.
Create a React application (if you don't already have one)
To create a React, run npx create-react-app react-app-with-subpath
. This will scaffold a React application in the react-app-with-subpath folder. You can now navigate to this folder (cd react-app-with-subpath
), run npm install
to install dependencies, and start the project with npm start
.
Alternatively, you can start with the final solution provided in the accompanying GitHub repository.
Configure the React application to build to a subfolder
We're going to be configuring the React application to build with a subfolder. Instead of our React application being built to the build
folder, we'll build it to the build/<subpath>
folder. This way, Azure Static Web Apps will route requests to <hostname>.azurestaticapps.net/<subpath>
to our React application.
For this example, we'll be using foobar
as the subpath we want to host our application from. Replace this value with the subpath you want to use wherever it's used.
Follow these steps to configure your build for your React application.
-
In package.json, add the
homepage
attribute with a value of/foobar
(or the subpath you decide to use.) This ensures that your React application requests static assets from this path instead of the root path, as documented in the create-react-app docs.{ ... "homepage": "/foobar", ... }
-
In package.json, configure the build step to build to the
/build/foobar
folder. Since Static Web Apps will serve thebuild
folder at the root domain, requests to<hostname>.azurestaticapps.net/foobar
will be routed to thebuild/foobar
folder where our React application resides.It is important to configure the React application to be built to
/build/foobar
instead of handling the subpath within the React application itself using some type of router solution. This is because, if we want to front the Static Web App with an Azure Front Door instance (or an App Gateway instance) with path-based routing, we need the entrypoint of our React application to be served from<hostname>.azurestaticapps.net/foobar
. That is why it is important to build our React application to/build/foobar
and have Static Web Apps serve the/build/
folder.{ ... "scripts": { ... "build": "BUILD_PATH='build/foobar' react-scripts build && echo '' > build/index.html", ... }, ... }
Additionally, we create an empty
index.html
file in the build folder since Azure Static Web Apps requires anindex.html
file at the root of the project being deployed.In this case, the BUILD_PATH environment variable is used by create-react-app to build the application to the right directory as documented. To create the
index.html
file, we echo an empty string to the file. -
Build the React project. This will create the
build
folder with the proper subfolder and React assets.npm run build
Configure the Static Web App to handle the subpath
Now that we have configured the React application to build to the /build/foobar
directory, we must configure the Static Web App to redirect request to the root to the subpath, and to handle the navigation fallback for our application.
Configure Static Web Apps redirects and fallbacks
-
In the root directory, create a
staticwebapp.config.json
file. This config file will be responsible for redirecting users to the subpath if they try to access the root path, and configure the navigation fallback to point to the entrypoint of our React application.touch staticwebapp.config.json
Paste the following in your newly created
staticwebapp.config.json
file:{ "routes": [ { "route": "/index.html", "redirect": "/foobar" }, { "route": "/", "redirect": "/foobar" } ], "navigationFallback": { "rewrite": "/foobar/index.html" } }
In the above configuration file, the routes array redirects requests made to the root path to the
foobar
subpath. We also have the navigation fallback configured, such that requests directly made to<hostname>.azurestaticapps.net/foobar/someotherpath
fallback to the React application's entrypoint (/foobar/index.html
), such that the React application can handle the routing properly.
Validate locally with the SWA CLI
-
We can now run our project locally with the SWA CLI to emulate the deployed Azure Static Web Apps environment to validate that our application with subpath works.
swa start build
This command will indicate to the SWA CLI that we want to serve the build folder. The SWA CLI will also read our
staticwebapp.config.json
file and use the configurations when serving our application.Notice that requests made to
localhost:4280
get redirected to our subpath.
Deploy to Static Web Apps
-
We can now deploy the project to Azure Static Web Apps. We can go through the Azure Portal and link it to our GitHub repository for our project, or use the SWA CLI to deploy our application. In this case, I'll use the SWA CLI but the process would be similar for the Portal.
From the root of our project, run the following:
swa deploy build
The SWA CLI will interactively request where we want to create our Static Web Apps resource. It will also deploy our application with the
staticwebapp.config.json
file, such that our subpath will be properly handled.We have now deployed our React application with subpath, and can visit it at the link that the SWA CLI returned! 🎉
If you are using the Portal, it may ask you to configure your build details. You can select the React preset for your build details, since we've want the
build
folder to be served by Static Web Apps.
Configuring React Router to work with our subpath
In the above steps, I focused on the build and deployment configurations needed to host a React application with a subpath. However, it's quite likely that a React application will need a router (such as React Router), and this router needs to be configured to route appropriately.
In the following steps, I'll be showing you how you can configure your React Router to handle the subpath.
A fully built solution is provided in the accompanying GitHub repository.
Configure the React Router to handle the subpath
For the following steps, I will assume that you have an existing React application using React Router. If not, refer to the accompanying GitHub repository to get a project with React Router as a starting point.
-
Add the basename to your React Router BrowserRouter. This is needed such that the React application and the React Router serves the proper routes at the
/foobar
path. If the basename is not added, the React Router will serve the routes at the root of our domain, which is not what we want.Depending on how you are using the React Router (and which version you are using), you will have to configure this in different ways.
In my case, I am using
createBrowserRouter
, and I pass the subpath as an option when I callcreateBrowserRouter
as you can see below:import './App.css'; import { createBrowserRouter, RouterProvider } from 'react-router-dom'; import { Home } from './pages/Home'; import { Hello } from './pages/Hello'; const router = createBrowserRouter([ { path: "/hello", element: <Hello />, }, { path: "/", element: <Home />, } ], { basename: "/foobar", }); function App() { return ( <div className="App"> <RouterProvider router={router} /> </div> ); } export default App;
At this point, we can build your React application with npm run build
and deploy to Static Web Apps with swa deploy build
as we did in the previous steps.
Conclusion
In this blog post, we've successfully built a React application and deployed it with a subpath to Azure Static Web Apps. While this blog post was focused on a React implementation, the steps of the Configure the Static Web App to handle the subpath section should apply to any project and the steps to build the project could be adapted to your project as well.
Resources
Set the destination directory #1052, Deployment without index.html? #671