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

Feature request: cache fetch requisitions #637

Open
Noriller opened this issue May 17, 2021 · 3 comments
Open

Feature request: cache fetch requisitions #637

Noriller opened this issue May 17, 2021 · 3 comments

Comments

@Noriller
Copy link

Issue description or question

I'm using node-fetch to use fetch using quokka and today I got locked out of the github API because too many requisitions are sent as you play around...

Maybe for fetch specifically (maybe more), there could be something, quokka specific that memoize/intercepts and return the same value until something is changed in that expression.

@smcenlly
Copy link
Member

Marking as a feature request. We would definitely want/need people to opt into this.

This may also help: #528 (comment)

While not a first class Quokka feature, you can do what you're asking for today. When you run your file with Quokka, by default Quokka re-uses the node process it starts to make subsequent executions much faster. You may set your API response using a global variable. For example:

function getApiResponse() {
  if (!global.myApiResponse) {
    global.myApiResponse = makeExpensiveServerCall();
  }
  return global.myApiResponse;
}

This doesn't mean that the API endpoint won't get hit multiple times because Quokka may recycle your process if there's a catastrophic error, but it will definitely limit remote execution most of the time.

We ourselves don't actually do this. For scenarios like the one that you're describing, we usually add logic to cache/read from a disk location in our scratch pad. Here's a generic template that you could use over and over again (maybe even create your own npm package or helper file for it):

function getApiResponse(param1, param2, param3, ... etc) {
  const fs = require('fs');
  const path = require('path');
  const crypto = require('crypto');

  // Generate a unique filename for the function arguments are provided (assumes no cyclical references)
  const args = JSON.stringify(Array.prototype.slice.call(arguments));
  const hash = crypto.createHash('md5').update(args).digest('hex');  
  const cacheFileName = path.join(require('os').tmpdir(), 'scratchFile', hash); // change scratch file name based on project or API call

  // Ensure the directory exists for our scratch file
  if (!fs.existsSync(path.dirname(cacheFileName))) {
    fs.mkdirSync(path.dirname(cacheFileName));
  }

  // If we already have a matching response, use it, otherwise make the call and cache it
  if (fs.existsSync(cacheFileName)) {
    return JSON.parse(fs.readFileSync(cacheFileName));
  } else {
    const response = makeExpensiveServerCall();
    fs.writeFileSync(cacheFileName, JSON.stringify(response));
    return response;
  }
}

@BLamy
Copy link

BLamy commented Apr 10, 2023

@smcenlly Any way we could do something similar to next JS and just override window.prototype.fetch with one that caches.

https://beta.nextjs.org/docs/data-fetching/fetching#revalidating-data

@smcenlly
Copy link
Member

@BLamy - yes, you could create a Quokka plugin to do this for you.

If you are using [email protected]+ then fetch is now included as a global function by default. You would want to create a plugin that wraps the global fetch function and adds your own caching.

If you're using something like node-fetch as a polyfill for earlier versions of node then your plugin would need to know about and replace / wrap the node-fetch implementation.

You can read about plugins in our docs. There are a number of open source plugins referenced in the docs, and should provide a good basis for getting started with a plugin that caches fetch requests.


If you end up creating a plugin, please let us know and we may add it to our website.

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

3 participants