Out of curiosity, is there a reason that you chose to go AppService over Static Web Apps (which has native Next.js support)?
Which is good question, the main answer to which is that we like to ensure that what we deploy has been fully tested, barring any configuration changes - we build the application once and then deploy that single package to every environment - static web apps supports this for a number of application styles, but sadly not for Next.js apps at this time - from the linked article on the feature:
During the preview, the following features of Static Web Apps are unsupported for Next.js with server-side rendering: […]
skip_api_buildcan't be used.
However, I do like the Static Web Apps offer, so we've been using them for a few landing pages recently and we recently had a need to front a secured API call, which is where this post comes in.
The Problem: We have a Static Web App that needs to call an API with a key, and we don't want that key (or indeed the API endpoint) exposed to the end users. We also want to follow our usual build and deploy process, with a single build that is deployed to each environment, and as an additional benefit if we can enable Password Protection on both the site and the API, that would be great.
Managed Functions to the Rescue!
The primary way to hide the key and endpoint of the API is by using an intermediary API - to hide the key, it must be stored server side, and added to the request. I considered using Front Door to add the header to requests, but that would still expose an additional URL I didn't really want to use, so using a function app seemed like a better way to go. Having this as a Managed Function answered two of my asks:
- It keeps everything on the same site and domain (all functions are under the
- Password Protection is enabled for the
/api/route as well as the site pages.
However, when I initially tried to pre-build and deploy the function application, the builds failed with:
Cannot deploy to the function app because Function language info isn't provided.
Which was a little annoying.
The answer to this is on the Build Configuration documentation under Skip building the API:
If you want to skip building the API, you can bypass the automatic build and deploy the API built in a previous step.
Steps to skip building the API:
- In the
apiRuntimeto the correct runtime and version. Refer to Configure Azure Static Web Apps for the list of supported runtimes and versions.
api_locationto the folder containing the built API app to deploy. This path is relative to the repository root in GitHub Actions and cwd in Azure Pipelines.
So, adding the following into our
staticwebapp.config.json was the final piece in the puzzle:
So now I can create a single build package, apply variable replacements to the
appSettings.Production.json file for the function app to provide sandbox/production endpoints and keys, and have the API protected in the same way as the static site.
Filed under: Azure, DevOps