Cache

When writing Rspack plugins, you can use compiler.getCache(name: string) or compilation.getCache(name: string) to get the cache object which can share data in the build process. The cache data is stored on the Compiler, so it can be used in multiple Compilations in the watch mode.

Notice
  • Only available when cache: true which it is enabled in mode="development" by default.
  • Only used for the JavaScript plugins, the Rust cache cannot be accessed.
  • Only memory cache is provided, persistent cache is not supported yet.

Example

The following code finds out the newly added assets in the processAssets:

compiler.hooks.compilation.tap('MyPlugin', compilation => {
  compilation.hooks.processAssets.tapPromise('MyPlugin', async () => {
    const cache = compilation.getCache('MyPlugin');
    const currentAssets = compilation.getAssets().map(i => i.name);
    const lastAssets = await cache.getPromise('assets', null);
    if (lastAssets) {
      for (const asset of currentAssets) {
        if (!lastAssets.includes(asset)) {
          console.log(`New asset: ${asset}`);
        }
      }
    }
    await cache.storePromise('assets', null, currentAssets);
  });
});

Methods

Caching

get/getPromise

Get cache data asynchronously, callback by function or promise.

  • Type:
    • get: <T>(identifier: string, etag: Etag | null, callback: (err: Error, result: T) => void): void
    • getPromise: <T>(identifier: string, etag: Etag | null): Promise<T>;
  • Arguments:
    • identifier: ID of data item
    • etag: Etag of the data item, can be generated by getLazyHashedEtag

store/storePromise

Store cache data asynchronously, callback by function or promise.

  • Type:
    • store: <T>(identifier: string, etag: Etag | null, data: T, callback: (err: Error) => void): void;
    • storePromise: <T>(identifier: string, etag: Etag | null): Promise<T>;
  • Arguments:
    • identifier: ID of data item
    • etag: Etag of the data item, can be generated by getLazyHashedEtag

provide/providePromise

Try to get cache data asynchronously, call the computer function to generate when not exists, callback by function or promise.

  • Type:
    • provide:
      provide<T>(
        identifier: string,
        etag: Etag | null,
        computer: (fn: (err: Error, result: T) => void) => void,
        callback: () => T | Promise<T>,
      ): void;
    • providePromise
      providePromise<T>(
        identifier: string,
        etag: Etag | null,
        computer: () => T | Promise<T>,
      ): Promise<T>;
  • Arguments:
    • identifier: ID of data item
    • etag: Etag of the data item, can be generated by getLazyHashedEtag
    • computer: The called generating function when cache is not exists
MyPlugin.js
const createAssetsData = async () => {
  console.log('only called once');
  return compilation.getAssets().map(i => i.name);
};

compilation.hooks.processAssets.tapPromise('MyPlugin', async () => {
  const cache = compilation.getCache('MyPlugin');
  console.log(await cache.getPromise('assets', null)); // undefined
  await cache.providePromise('assets', null, createAssetsData); // call createAssetsData
  console.log(await cache.getPromise('assets', null)); // ["main.js"]
  await cache.providePromise('assets', null, createAssetsData); // not call
});
Output
undefined
only called once
[ 'main.js' ]

getLazyHashedEtag/mergeEtags

By using the getLazyHashedEtag and mergeEtags methods, an etag can be created as the unique identifier of the data item. It will not be calculated immediately when created, but rather delayed until it is used, and also can be cached. This can be used to improve performance when complex data objects are used as the unique identifier.

  • getLazyHashedEtag: (obj: HashableObject): Etag, calculates the hash of the object to generate the etag as the data identifier, the object needs to implement the updateHash(hash: Hash).
  • mergeEtags: (a: Etag, b: Etag): Etag, merges two etags to one.
MyPlugin.js
const cache = compilation.getCache('MyPlugin');
const dataEtag = cache.getLazyHashedEtag({
  content: 'a'.repeat(10000),
  updateHash(hash) {
    console.log("only called once");
    hash.update(this.content);
  }
});
const mergedEtag = cache.mergeEtags(dataEtag, "other etag");
await cache.storePromise("assets", mergedEtag, "cached value");
console.log(await cache.getPromise("assets", mergedEtag));
Output
only called once
cached value

getItemCache

By using the getItemCache method, a cache object for a single data item can be created. This cache object provides simplified data access methods, do not need identifier and etag as arguments any more.

  • Type: (identifier, etag): ItemCacheFacade
type ItemCacheFacade = {
  get<T>(callback: (err: Error, result: T) => void): void; // async data getter, callback by function
  getPromise<T>(): Promise<T>; // async data getter, callback by promise
  store<T>(data: T, callback: (err: Error, result: T) => void): void; // async data setter, callback by function
  storePromise<T>(data: T): Promise<void>; // async data setter, callback by promise
  provide<T>( // try to get the data, use function to compute if not exists, callback by function
    computer: (fn: (err: Error, result: T) => void) => void,
    callback: (err: Error, result: T) => void,
  ): void;
  providePromise<T>( // try to get the data, use function to compute if not exists, callback by promise
    computer: (fn: (err: Error, result: T) => void) => void,
  ): Promise<T>;
};
MyPlugin.js
const cache = compilation.getCache('MyPlugin');
const itemCache = cache.getItemCache('item');
await itemCache.storePromise('cached value');
console.log(await itemCache.getPromise());
Output
cached value

getChildCache

By using the getChildCache method, a child cache object can be generated, with its interface being completely consistent, and it can be utilized when there are numerous caches that require grouping for storage.

  • Type: (name: string): CacheFacade