react-three-fiber icon indicating copy to clipboard operation
react-three-fiber copied to clipboard

[v10] feat(cache): promise based caching with workers

Open krispya opened this issue 1 year ago • 4 comments

⚠️Includes breaking change: Removes extensions from useLoader in favor of passing in already extended loader instances.

Caching was hidden behind react-suspend and did not offer any way to utilize browser APIs or extend it. This PR adds PromiseCache class that creates a local cache compatible with React.use backed by the web Cache API. The Cache API offers many benefits such as:

  • Fully integrated with fetch.
  • Allows for caching resources across worker boundaries.
  • Allows for downloading, processing and caching resources inside of a service worker.
  • Allows for client side control over offline caching.
  • Fully inspectable via dev tools

The PromiseCache accesses and processes resources from the global cache while handling promises for you.

// Pass in the name of the global cache that backs it, or the cache itself if you have it.
const cache = new PromiseCache('assets') 
// Fetches resources from a url, caches it, then runs a handler on that data. Returns a promise with the handler's return value.
// ?? Should this just return a blob instead of a blob URL? ??
cache.run(url: string, handler: async (cacheUrl: string) => any)): Promise<any>
// Add a promise.
cache.add(url: string, promise: Promise<any>)
//  Get a promise from the cache.
cache.get(url: string): Promise<any>
// Check if the cache has a url stored.
cache.has(url: string): boolean
// Delete a cached response. Return true if successful, false if unsuccessful.
await cache.delete(url: string): Promise<boolean>

It looks like this when combined with React.use:

const cache = loaderCaches.get(loaderInstance)!

if (!cache.has(url)) cache.run(url, async (cacheUrl) => loadAsset(cacheUrl, loaderInstance))
const result = React.use(cache.get(url)!)

TODO

  • ~~Testing is broken. jest doesn't mock the Cache API or fetch. Trying to polyfill either proved harder than I expected.~~
  • The API could use some tuning.
  • This should probably get split off into its own library.
  • Make compatible with Node.

krispya avatar Apr 30 '24 23:04 krispya

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 5e539567e6d01ce771857dc8f4bf3c4bcbe5b213:

Sandbox Source
example Configuration

codesandbox-ci[bot] avatar Apr 30 '24 23:04 codesandbox-ci[bot]

  • extensions removed from useLoader.
  • Testing now works. Requires Node 18 or higher since it is using Node's browser-compliant fetch API.

krispya avatar May 02 '24 19:05 krispya

@CodyJasonBennett How can I check if this PR fixes the issue trying to be solved by https://github.com/pmndrs/react-three-fiber/pull/3243 ?

krispya avatar May 03 '24 01:05 krispya

I'll add tests once we can reproduce issues with error boundaries also. I don't expect that to be addressed here.

CodyJasonBennett avatar May 03 '24 05:05 CodyJasonBennett