Using Azure Blob storage to host static website files has been around for many years, it’s cheap, effective and fast to setup. It gives you the ability to effectively create a directory with a unique public URL that you can upload your static files to and have them hosted (no need for any web server). Microsoft has great documentation available that steps you through how to do this:
Static website hosting in Azure Storage
Tutorial: Host a static website on Blob Storage
This works well if your static website files are a bunch of html files (that contain links to each other to provide navigation). One scenario in which the Azure Blob Storage approach falters however, is if you try to host Single Page Applications (SPAs) in Blob Storage. Some aspects of the URL routing doesn’t work as you would expect for a SPA.
Example of a SPA
Only one file hosted on the web server called my-spa.html
The URL of this file is
Internally the SPA may defines 2 routes
When the user clicks on a link on the
https://myserver/my-spa.html page the SPA tells the browser it’s changing the location to
https://myserver/my-spa/page1 and the SPA changes some or all of the current page content. When you look at that URL though you should notice it points to a page that doesn’t physically exist on the server,
https://myserver/my-spa/page1 isn’t a file you can go find on that webserver. Up until this point our Azure Blob Storage works as you would expect, because our modern browsers understand the SPA is routing internally and no request is sent to the server. There are two scenarios though that will break Azure Blob Storage.
Breaking Scenario 1 – Browser Refresh
What if we have
https://myserver/my-spa/page1 URL in our browser and we hit the refresh button? This time our browser will make a request to the server and
https://myserver/my-spa/page1 isn’t a file that exists so we will get a page not found error. Well that’s pretty crap you might think, these SPAs aren’t robust. There’s usually a little magic that goes on the server side when you host a SPA, you effectively rewrite/redirect all URLs
https://myserver/my-spa.html so that the SPA page handles all the URLs, it starts up, looks at the incoming URL and then it tries to match one of it’s internal routes and modifies the contents of the page to show content just as it would if the user started the SPA at the root URL and then navigated to that route.
Breaking Scenario 2 – Deep Links
A similar problem is a user trying to open a deep link into the SPA. Let’s say that a user was navigating through the SPA and arrived successfully at route that was displaying
https://myserver/my-spa/page1 in the browser location. The user might copy/paste this link and send it to someone else (or just bookmark it and try to use it later). When someone tries to use that deep link (I call it a deep link because it’s trying to go someone in the SPA that isn’t the root URL) we fall into the same issue as the refresh situation, we are asking the webserver for a file that doesn’t exist. Again SPAs rely on the webserver having a URL rewrite/redirect or similar in place to ensure all URLs load that root
The Azure Blob Storage Problem – No Redirect/Rewrite Rules Possible
Unfortunately when hosting a static website using Azure Blob Storage we don’t get any facility to do that server side rewrite or redirection that would make it respond with the
https://myserver/my-spa.html file. That’s one of the reasons that Azure later came up with an offering called Azure Static Web Apps, this is a different type of resource in Azure that is designed specifically for hosting static web apps and does overcome this server side URL rewrite issue. If you are creating a brand new site and have to ability to change your Azure architecture to use an Azure Static Web App rather than Azure Blob Storage then I’d suggest it might be your better option.
The Solution – Using Hash Location Strategy
There is a way to get your SPA working however with Azure Blob Storage, the solution is to change the way you construct your URLs to use something called a hash location strategy. This was actually a pattern to overcome a different issue, the issue of older browsers not knowing about SPAs and always sending server requests when the SPA wanted to navigate to one of it’s routes (e.g. from
https://myserver/my-spa/page1). Something browsers have understood for decades is the concept of a a inter-page anchor link, these are links to another section of the same page and the browser understands this by using # in the URL. The format is
https://myserver/my-spa.html#anchor-name. If you design your SPA to do it’s internally routing using # instead of a URL path then you can see that our route that was generating a URL of
https://myserver/my-spa/page1 could now generate a URL of
https://myserver/my-spa.html#page1. Like magic this is now a file our Azure Blob Storage can find, when it loads the root SPA page our SPA now looks at the URL interprets what comes after the # as the route and works in much the same way it used to.
If you are using a framework such as Angular then switching to use a hash location strategy may be a simple thing to do. In the case Angular it’s a simple router property
Leave a Reply