Comparing Netlify and Azure Static Web Apps
Static web hosts have come a long way since dropping your bundle into an S3 bucket. Netlify and Azure Static Web Apps (SWA) both offer a free tier and the two are surprisingly similar in terms of features. In this post I’ll compare the two and look at the small differences that make me ultimately prefer Netlify.
Creating the SPA
Let’s create a simple static website and build an artifact for deployment. We’ll use the resulting dist
directory to deploy to both Netlify and Azure Static Web Apps.
npm create vite@latest -- --template react-ts my-react-app
cd my-react-app
npm i
npm run build
Deploying to Netlify
Create a free account on Netlify, install the Netlify CLI and login. Once logged in, create a new site and deploy the dist
directory:
npm install netlify-cli -g
netlify login
netlify sites:create
netlify deploy --prod --dir dist
Just like that, the site is up and publically accessible:
Deploying to Azure Static Web Apps
Azure Static Web Apps has a Visual Studio Code extension that can be used to create and manage static web apps, however, for comparison’s sake I’ll use the SWA CLI. In theory, and I guess outside of WSL2, it should be simple:
npm install -g @azure/static-web-apps-cli
swa
However even swa login
fails for me, and I was hit with these bugs and errors:
- An X11 server is required when keychain is enabled and;
- CLI assumes the AZURE_LOGIN_CONFIG file has subscriptions in it
The workaround for this is to (install and) use the Azure CLI to login and then use the SWA CLI. Note that this requires a valid subscription which will not be present on a new Azure account. Adding a Free Trial subscription on Azure requires both a Mobile phone number and a Credit Card. Once a subscription is added, the following can be done:
npm install -g @azure/static-web-apps-cli
az login --tenant MY_TENANT_ID
swa login
Deployment at this stage will result in:
The subscription is not registered to use namespace ‘Microsoft.Web’
So register the Azure Static Web Apps resource provider and then deployment should succeed:
az provider register --namespace Microsoft.Web
swa deploy --env production
A few more steps, and some head banging with Azure account caching in the browser, but ultimately the site is up and publically accessible:
APIs and CORS
Say now we have some API on another host, that does not have CORS enabled, and we don’t have control over that host to add those headers. For example, this deployment of the Dog API. In both the local, and deployed environments, calling this API will result in the following CORS error:
Access to fetch at ‘http://dog-api.kinduff.com/api/facts’ from origin ‘http://localhost:8888’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.
Thankfully, Netlify has us covered and adding the following to netlify.toml
and fetch
ing /dogs
will solve this error for us both during local development, and, in the deployed environment:
[[redirects]]
force = true
from = "/dogs"
status = 200
to = "http://dog-api.kinduff.com/api/facts"
Azure Static Web Apps has something similar, but it only works in the deployed environment. Adding the following to staticwebapp.config.json
solves for the deployed environment but swa start
does not honour this configuration:
{
"routes": [
{
"route": "/dogs",
"redirect": "https://dog-api.kinduff.com/api/facts"
}
]
}
Netlify’s rewrite and redirect functionality is quite flexible where Azure Static Web Apps routes configuration is more limited, misses functionality like passing on query strings, and is a little buggy.
Serverless Functions
Both services offer serverless functions on their free tiers and adding them is quite simple. For Netlify, netlify functions:create
will ask some questions and add your first function. Functions are available via /.netlify/functions/your-function
and are available both locally with netlify dev
and in the deployed environment with netlify deploy
.
Azure’s SWA CLI can run functions locally but adding them to the project requires either installation of Azure Functions Core Tools or (the easier approach) is to install both(!) the Azure Functions and Static Web Apps extensions for vscode. After adding a function with vscode running the app with swa start dist --api-location api
serves the function on /api/your-function
. Deploying the function along with the site is similar with:
swa deploy --api-location api --env production
Preview Environments
Finally, both services offer preview environments: non-prod environments either deployed directly via CLI or (for example) from a GitHub PR. Netlify takes preview deployments even further with their Drawer Feature, though I haven’t personally used it. To deploy a preview environment with Netlify, just omit the --prod
flag. For Azure, the relevant Github Actions are configured when using the vscode extension to create the static web app, or, by using the --env
flag with the swa deploy
command.
Conclusion
Over all the offerings are quite similar and almost have feature parity. Netlify’s CLI is more mature and easier to use, and the platform has a few more features that make it more appealing to me. Azure Static Web Apps has a few more steps to get started, but the platform is more integrated with the Azure ecosystem and may be more appealing to those already using Azure services. Both services are free for small projects and are a great way to get started with static web hosting.
All of the commands I ran in this post were done against the same project which can be deployed to both Netlify and Azure Static Web Apps (and were - the iframes above point to the live sites). The source code for this can be found here.