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

Unable to load some site assets. #78

Open
TimTinkers opened this issue Jan 13, 2022 · 6 comments
Open

Unable to load some site assets. #78

TimTinkers opened this issue Jan 13, 2022 · 6 comments

Comments

@TimTinkers
Copy link

The issue we are experiencing is one related to KV assets. For context: our site is a Vue 3 application. We are building it using Vitedge to support SSR running on a Cloudflare Worker.

The issue as reported by one of our devs:

  1. We deployed our application using Vitedge. In doing so, we deployed a new worker and KV:  - Worker: test-assets
      - KV: __test-assets-workers_sites_assets (c46d5f240d0643fe9f822ae3a25595de)

  2. We opened the page that the Wrangler GitHub action had spun up for our Worker: https://test-assets.superfarm.workers.dev/ in incognito mode and waited until test-assets redeployed, then navigated to one of our pages ("NFT Drops") and experienced some HTTP 500 errors that some of our assets could not be found.

Error: 1101
Ray ID: 6ccb5309f8d94991
Timestamp: 2022-01-13 02:51:43 UTC
  1. Checking our logs for the 500 error isn't helpful.```  "exceptions": [
        {
          "name": "Error",
          "message": "internal error",
          "timestamp": 1642042501244
        }
      ],

4. Further digging shows that the assets in the URL don't seem to match those that were stored in KV:```
$ wrangler kv:key get assets/Stats.af469f3b.js --namespace-id c46d5f240d0643fe9f822ae3a25595de
Code 10009: get: 'key not found'

The actual asset name:```
$ wrangler kv:key get assets/Stats.af469f3b.9ec2057bc5.js --namespace-id c46d5f240d0643fe9f822ae3a25595de


We're currently assuming that either Vitedge or Wrangler are adding some unique hash to the end of our assets. Vitedge is getting its assets using the `@cloudflare/kv-asset-handler` package so this might be a known issue in that handler?

We would love it if you could share some insights on this or help further debug.
@TimTinkers
Copy link
Author

I'm back with a bit of a clarifying example. Here's the persistence issue as we understand it:

  • one of our users opens a page in their browser, let's say one being served by the worker to dev.superfarm.workers.dev.
  • we deploy a new build to dev.superfarm.workers.dev
  • the user will begin experiencing the issues above regarding inability to load assets if they attempt to load a page containing a component which has been updated in the new build; this issue will persist until the user reloads the page.

For example: we have a "Stats" component in the top banner of our page that gets loaded when the user lands on the app. If a user loads our app and then tries to navigate to our "NFT Drops" page after we change the "Stats" component in our newly-deployed build, that asset hash will change and the user will start experiencing the problems above.

I hope this helps find some solution.

@frandiox
Copy link
Owner

@TimTinkers That example is definitely useful! I don't think Vitedge is doing anything special with assets, it's just leveraging Vite and Wrangler. I didn't have time yet to check myself but here are some pointers:

  • Assets are normally hashed to avoid getting old files from CDNs. You can add logs in Vitedge around assets using willRequestAsset and didRequestAsset hooks (the last one can actually modify the response). Also, most of the code for assets is here, in case you want to check.

  • I've seen some websites that get a cached asset map in the browser and keep requesting the same old assets even if the server has already been deployed and busted the old assets from CDN (I think this happened in Netlify). As far as I know, Wrangler does not remove old assets from cache on new deploys but I might be wrong, or this might be the case for *.worker.dev domains.

  • Vite is naming built files as [name].[hash].[ext]. I see in your example you have assets/Stats.af469f3b.9ec2057bc5.js, with 2 hashes, but I don't know what is adding the second one. As far as I remember, Wrangler didn't add any 🤔
    You can play with Vite build hashes by passing these options in the plugin as Rollup options:

vitedge({
      client: {
        build: {
          rollupOptions: {
            output: {
              entryFileNames: `assets/[name].js`,
              chunkFileNames: `assets/[name].js`,
              assetFileNames: `assets/[name].[ext]`,
            },
          },
        },
      },
    })

The previous options will build your assets without hashes at the Vite level.

I'll try to check when I have some more time but let me know if you find something.

@TimTinkers
Copy link
Author

Hi @frandiox thanks for the added information, we're still continuing out own debugging. Just curious if you've had any additional time yet to look at this one.

@frandiox
Copy link
Owner

frandiox commented Feb 2, 2022

@TimTinkers hey! Not yet, quite busy here moving apartments and stuff. Still in my list though!

@frandiox
Copy link
Owner

@TimTinkers Hello! Did you manage to find a workaround on your end?

I don't think this issue can be fixed in Vitedge easily because it's basically how SPA work. Once the old assets are removed from CDN, live users who don't yet have the new app version will need to refresh their browser to get it.

What we did once in a Vue SPA app (on Netlify) was something like this:

router.onError((error) => {
  // When a new version of the app is deployed, old version's files are
  // removed from CDN. Browsers that have old files cached will try to
  // download more old files on route navigation.
  // This will hard refresh browsers that fail when loading files in
  // order to get the updated version of the app.
  if (/loading chunk chunk-(\d|[a-z])+ failed\./i.test(error.message)) {
    const key = 'chunk-failed-reload'
    const lastReload = localStorage.getItem(key) || 0
    // Do not reload more than once a minute to avoid infinite loops.
    if (lastReload < Date.now() - 60000) {
      localStorage.setItem(key, Date.now())
      window.location.reload()
    }
  }
})

This basically detects the error and refreshes the browser. In this case, it was something like loading chunk chunk-lkj213lk.js failed blah but you might need to adjust it. This could be used to save Vuex state in localStorage before refreshing or anything like that.

@TimTinkers
Copy link
Author

Hi @frandiox thanks for the reply! No, we unfortunately haven't had time to continue working on this project and didn't end up resolving this one on our end. Thanks for the tip though regarding the CDN assets, that makes sense. We'll keep looking into it.

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

No branches or pull requests

2 participants