✨Discover storytelling in the AI age with Pixar's Matthew Luhn at Sanity Connect, May 8th—register now

Troubleshooting deployment issues with Sanity + NextJS on Azure web app

28 replies
Last updated: Feb 26, 2023
We are building a site with Sanity + NextJS, with deployment to an azure web app through nexts SSG. We keep getting issues when deploying new builds, that the index page (which fetches from GetStaticProps, and has preview-functionality) fails to locate files in the static standalone build (for example ssgManifest, buildManifest, css-files etc).
This happens on every deploy, and all the errors clear out as soon as we open the page from sanity in preview. Any hints to what this could be caused by? Errors in the console are attached:
Feb 23, 2023, 12:50 PM
Is the azure web app running windows or linux?
Feb 23, 2023, 12:59 PM
Linux!
Feb 23, 2023, 1:01 PM
Do you think that has anything to say?
user G
Feb 23, 2023, 1:11 PM
No, if it was windows that could be an issue. How are you deploying? In my experience the linux ones with Oryx is working well. Do you have any errors running next build locally?
Feb 23, 2023, 1:21 PM
No next build locally works fine, i cd into the standalone directory and run the node server without any errors. In relation to Oryx, I do get an error in the azure portal that looks like this:
Feb 23, 2023, 1:28 PM
We deploy through azure/webapps-deploy@v2 in gh actions, by downloading the build as an artifact (with actions/download-artifact@v3)
Feb 23, 2023, 1:29 PM
We use pnpm, and pnpm build for the build step
Feb 23, 2023, 1:30 PM
It seems like it always tries to load the very first deployment, and if I for example go through incognito, it is always refering to the wrong static files. Going through next seems to set the cache correctly..
Feb 23, 2023, 3:03 PM
Did you override the startup command? Sounds a bit like it doesn’t run build, just start
Feb 23, 2023, 3:30 PM
Yeah we specified the startup command to “cd app && npm start”, but do you think we need to run build in this step as well? Because the build is run in the workflow prior to deploying, and then we use these:

   - name: Compress build output
      if: ${{ inputs.save_artifact == 'true' }}
      shell: bash
      run: tar -cf ${{ inputs.artifact_name }}.tar -C ./.next/standalone .
      working-directory: ${{ inputs.working_dir }}

    - name: Upload Artifact
      if: ${{ inputs.save_artifact == 'true' }}
      uses: actions/upload-artifact@v3
      with:
        name: ${{ inputs.artifact_name }}
        path: '${{ inputs.working_dir }}/${{ inputs.artifact_name }}.tar'
        retention-days: 5
Feb 24, 2023, 7:37 AM
But yeah, it sounds like it doesn’t build as you say
user G
Feb 24, 2023, 7:38 AM
I think you have a conflict between Oryx and the way you are deploying. I think you either need to disable Oryx or do things the Oryx way. Oryx will normally auto detect Next.js apps and automatically run npm install, npm run build and npm run start for you. The advantage with Oryx is that it puts the node_modules folder outside the /home/site/wwwroot, because that folder is a mounted network drive. When your app is run on the server it will cause a lot of unnecessary network I/O if it has to read dependencies from a network drive. What Oryx does is it installs dependencies in /node_modules instead, so they are available on the physical drive of the server.
What I normally do is build and run tests in gh actions, but I will exclude the .next folder and node_modules from the zip that is deployed. I set
ENABLE_ORYX_BUILD
and
SCM_DO_BUILD_DURING_DEPLOYMENT
to true in the app service settings and let Oryx handle the rest (ie no startup command). This is a both a performance win for the app and it cuts down deployment times by a lot.

https://github.com/microsoft/Oryx/blob/main/doc/runtimes/nodejs.md
https://github.com/microsoft/Oryx/blob/main/doc/hosts/appservice.md
Feb 24, 2023, 8:14 AM
(I think you might have to explicitly put those mentioned flags as false to completely disable Oryx)
Feb 24, 2023, 8:18 AM
Ah i see, but when we override the startupcommand, its to cd into the app directory of the standalone build
Feb 24, 2023, 8:18 AM
Since the path there is .next/standalone/app
Feb 24, 2023, 8:18 AM
node_modules is also in the standalone directory, but outside app
Feb 24, 2023, 8:19 AM
Yeah, because you are using standalone. Does the standalone include your public folder? Don’t you need to copy that in? Standalone is not really necessary on Azure, since you only really need to deploy the source code and package.json + package.lock files and Oryx handles the rest in a optimised way. Deployments are insanely quick because you don’t need to deploy any bloat
Feb 24, 2023, 8:26 AM
If you want to continue with standalone, make sure public folder is included and disable Oryx. Keep the startup command
Feb 24, 2023, 8:26 AM
We copy the public folder into the standalone folder postbuild:
"build:copy-files": "cp -R public .next/standalone/app/public && cp -R .next/static .next/standalone/app/.next/static",
Feb 24, 2023, 8:28 AM
Oh okay, so perhaps things will be solved by just disabling Oryx then
Feb 24, 2023, 8:30 AM
Maybe, I don’t really have any experience with it on Azure. I’ll add my build steps here in case you want to try the Oryx approach instead of standalone

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2

      - name: Set up Node.js version
        uses: actions/setup-node@v3
        with:
          node-version: "18.x"

      - name: npm install, build, and test
        env:
          SANITY_DATASET: ${{ secrets.SANITY_DATASET }}
          SANITY_PROJECT_ID: ${{ secrets.SANITY_PROJECT_ID }}
          SANITY_API_VERSION: ${{ secrets.SANITY_API_VERSION }}
          SANITY_TOKEN: ${{ secrets.SANITY_TOKEN }}
        run: |
          npm ci
          npm run build --if-present
          npm run test --if-present

      - name: Zip artifact for deployment
        run: zip -qr artifact.zip -x "node_modules/*" ".next/"

      - name: Upload artifact for deployment job
        uses: actions/upload-artifact@v2
        with:
          name: node-app
          path: ./artifact.zip

  deploy:
    runs-on: ubuntu-latest
    needs: build
    environment:
      name: "dev"
      url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}

    steps:
      - name: Download artifact from build job
        uses: actions/download-artifact@v3
        with:
          name: node-app

      - name: unzip artifact for deployment
        working-directory: ./
        run: |
          unzip artifact.zip
          rm artifact.zip

      - name: "Deploy to Azure Web App"
        id: deploy-to-webapp
        uses: azure/webapps-deploy@v2
        with:
          app-name: "xxx"
          slot-name: "xxx"
          publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_XXX }}
          package: .
Feb 24, 2023, 8:34 AM
I see, well I will at least give it a shot. We have some reasoning behind not wanting to use Oryx due to pnpm
Feb 24, 2023, 8:36 AM
Thanks for the workflow man!
Feb 24, 2023, 8:36 AM
Good luck!
I believe you can use pnpm with Oryx by adding an app setting
CUSTOM_BUILD_COMMAND
and setting it to
pnpm install && pnpm run build
which will override the default npm commands that are run by Oryx
Feb 24, 2023, 8:45 AM
https://github.com/microsoft/Oryx/issues/823 (from the bottom reply from qianz2 here)
Feb 24, 2023, 8:47 AM
Thank you so much for your input! I will try to see if i can fix it
Feb 24, 2023, 8:51 AM
Her is the docs on the config options, you just add them as app settings on the web app

https://github.com/microsoft/Oryx/blob/main/doc/configuration.md
Feb 24, 2023, 8:52 AM
Extremely interesting, we solved the issue, but not by changing anything in the workflows. I had forgotten a revalidate prop in the GSP on index’s
notFound: true
return statement. My theory was that the function returned notFound during build, and pulled out a cached version. Since revaldiate was set to the default, which I guess is 365 days(?), the function wasn’t called again. Not sure where this would have been pulled from, but introducing
revalidate
for this return statement ensured that the GSP was run. Any thoughts?
Feb 26, 2023, 12:34 PM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?