Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Netlify DEPLOY_URL to avoid missing chunks #20950

Closed
3 of 4 tasks
edwh opened this issue May 19, 2023 · 12 comments
Closed
3 of 4 tasks

Use Netlify DEPLOY_URL to avoid missing chunks #20950

edwh opened this issue May 19, 2023 · 12 comments

Comments

@edwh
Copy link
Contributor

edwh commented May 19, 2023

Describe the feature

Netlify uses atomic deploys, which means that when a deployment occurs, the old chunks disappear. This causes errors which Nuxt currently works around by reloading if a chunk is missing on a route. #19086 has discussion about this, and you can force reloads in all circumstances as per the end of that discussion.

But reloads are bad UX. Netlify exposes a DEPLOY_URL environment variable at build time which gives a permanent link to that build. Nuxt has cdnUrl / NUXT_APP_CDN_URL which can be used to serve assets from another url. https://answers.netlify.com/t/netlify-functions-and-env-variables-from-netlify-toml/4404/13 has an example of saving this off at build time and using it at run time (it's not available at run time within Netlify, sadly).

Could we not do this in the Netlify preset so that when we fetch chunks we always fetch chunks from the same build version as the code we are already running? This might avoid the missing chunks problem entirely.

Additional information

  • Would you be willing to help implement this feature?
  • Could this feature be implemented as a module?

Final checks

@edwh
Copy link
Contributor Author

edwh commented May 19, 2023

I will have a crack at trying this (outside the preset) to see if it works, and then report back.

@danielroe
Copy link
Member

How about this?

export default defineNuxtConfig({
  $production: {
    app: {
      cdnURL: process.env.DEPLOY_URL
    }
  }
})

@edwh
Copy link
Contributor Author

edwh commented May 19, 2023

@danielroe Would that embed the value at build time? It's not available in Netlify at runtime.

@danielroe
Copy link
Member

Yes, it would.

@edwh
Copy link
Contributor Author

edwh commented May 19, 2023

Thank you, it's kind of you to give me the exact incantation to try.

It looks promising, though I've not tested it live yet, only on a Netlify branch build. Initially I got CORS errors fetching the chunks, which I worked around with a netlify.toml file in the root folder of the project:

[[headers]]
  for = "*"
  [headers.values]
    Access-Control-Allow-Origin = "*"
    Access-Control-Allow-Headers = "Origin, X-Requested-With, Content-Type, Accept, Authorization"

Will report back further once I dare apply it to the live site.

@danielroe
Copy link
Member

You should also be able to set those headers in your nuxt config:

export default defineNuxtConfig({
  $production: {
    app: {
      cdnURL: process.env.DEPLOY_URL
    },
    routeRules: {
      '/_nuxt/**': {
        headers: {
          'Access-Control-Allow-Origin': '*',
          'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept, Authorization'
        }
      }
    }
  }
})

@edwh
Copy link
Contributor Author

edwh commented May 19, 2023

@danielroe This seems to work very nicely. Perhaps worth documenting this kind of solution, even if you don't think it's suitable as the default Netlify behaviour?

I'm still seeing some preload errors, e.g.

Failed to fetch dynamically imported module: https://64679fb12d8a07000836dddd--golden-caramel-d2c3a7.netlify.app/_nuxt/error-component.9a01195d.js

This is a bit odd, as the files exists. So perhaps that's a network error on the client. Does Nuxt have retries for loading?

@edwh
Copy link
Contributor Author

edwh commented May 20, 2023

This is a bit odd, as the files exists

Just pointing out that it's for the error.vue page. So perhaps there's something special about that. Or prefetches.

@danielroe
Copy link
Member

danielroe commented May 23, 2023

I think that this is ingenious, but too specific to a use-case to be enabled by default. Users may not want JS being fetched from a different domain than their site, or they may wish their site to be reloaded.

I'm going to close this but feel free to open a documentation PR - it could likely live in nitro docs for both Vercel + Netlify.

@danielroe danielroe closed this as not planned Won't fix, can't repro, duplicate, stale May 23, 2023
@edwh
Copy link
Contributor Author

edwh commented May 24, 2023

For anyone else interested in this. We need to be slightly more ingenious, because in the wild it turns out that some security software (e.g. Streamline3) blocks the script loads because they are from an odd looking domain (your domain at Netlify) and not from the domain of the site you loaded.

So here's a revised version. In nuxt.config.ts we munge the deployed site into a fictional path on the domain:

  $production: {
    app: {
      cdnURL: '/netlify/' + process.env.DEPLOY_URL?.replace('https://', ''),
    },
  },

That means we'll get JS chunks of the form https://www.ilovefreegle.org/netlify/646dec676b414a0008de734b--golden-caramel-d2c3a7.netlify.app/_nuxt/useTwem-legacy.dbec3c42.js

Then in Netlify's _redirects file we proxy it:

/netlify/* https://:splat 200!

That means we get the benefits of the build id being embedded into the assets, so that we we don't have the issue with chunks becoming invalid after a new deploy, but without the suspicious aspect of loading JS from another domain.

@edwh
Copy link
Contributor Author

edwh commented Jun 10, 2023

Docs PR created: unjs/nitro#1300

Copy link
Member

Great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants