Learning Cache
Published: 2024-03-10 05:57:58

Recently, [ChatCraft](https://github.com/tarasglek/chatcraft.org) enabled python support via WASI which is really amazing! (You can check out this [PR](https://github.com/tarasglek/chatcraft.org/pull/485) by [WangGithub0](https://github.com/WangGithub0) for more details)

In that PR, I found
```ts
WASI.start(fetch(url), {
        args: ["python", "-c", code],
        stdout: (out) => {
          console.log(out);
        },
        stderr: (err) => {
          console.error(err);
        },
      })
        .then((result) => {
```
seems each time run the `fetch`, but after the first time running, which is time-consuming, the later ones are significantly speeds up loading times.

After some research, I got to know it is related to the cache, I would like to share what I learned in this post.

## How Caching Works with WebAssembly
1. Fetching and Compiling: The first time a WebAssembly module is requested, the browser fetches it, compiles it into machine code, and then executes it. This process can be time-consuming, especially for large modules.

2. Cache Storage: After the initial compilation, both the raw and compiled versions of the module can be stored in the browser's cache.

3. Subsequent Requests: For subsequent requests, if the browser detects that the module is already in its cache and hasn't changed (based on cache headers and validation tokens), it can skip the fetching and compilation steps, directly loading the module from cache. This significantly speeds up loading times.

4. Cache-Control Headers: The effectiveness of caching can be influenced by HTTP Cache-Control headers sent by the server. These headers can instruct the browser on how and when to cache resources, including WASM modules. 

5. Versioning and Updates: To ensure users receive the latest version of a WASM module, developers must manage caching carefully. Changing the URL of the module or using cache-busting techniques can force the browser to fetch a new version.

## Cache-Control Headers

The caching behavior is determined by the HTTP Cache-Control header and other caching headers sent by the server along with the resource. These headers can specify directives such as:

- max-age: Indicates how long the resource is considered fresh and can be served from the cache without revalidation.
- no-cache: Instructs the browser to revalidate the resource with the server before using the cached copy.
- no-store: Tells the browser not to cache the resource at all.
- must-revalidate: Indicates that once a resource becomes stale, it must be revalidated with the server before it can be used.
- public or private: Specifies whether the response is intended for a single user (private) or can be cached by shared caches (public).

And developers can control caching behavior in the fetch request by using the cache option in the Request object to specify how the request should interact with the browser's cache. For example:
- default: The browser will follow its default caching algorithm.
- reload: The browser will bypass the cache and download the resource from the server.

See more at [Request: cache property](https://developer.mozilla.org/en-US/docs/Web/API/Request/cache)

## @antonz/python-wasi headers

Now let's see the headers of the used lib [`@antonz/python-wasi`](https://www.npmjs.com/package/@antonz/python-wasi) using [Thunder client](https://www.thunderclient.com) in VS code)

![lib](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nnyaigrpoj5v8j2loal0.png)

We can also see the MIME type to `content-type application/wasm`, it looks like being set [here](https://github.com/nalgeon/python-wasi/blob/76801832b642a49f11fdce0f0e2a759f72d1c284/src/index.js#L12)  in the source code 

## Other helpful links:
[MDN: WebAssembly](https://developer.mozilla.org/en-US/docs/WebAssembly)
[Code caching for WebAssembly developers](https://v8.dev/blog/wasm-code-caching)