vuejs/vue

Component caching - wrong type returned in a `set` method

AnJ-Github opened this issue · 1 comments

Vue version

2.6.14

Link to minimal reproduction

https://stackblitz.com/edit/vitejs-vite-6m9sxj?file=server.js

Steps to reproduce

  1. Implement server side rendering in Vue
  2. Implement component caching in Vue
  3. Observe what is passed to set method inside createRenderer cache

What is expected?

According to vue documentation set method should receive second argument as a string:

type RenderCache = {
  get: (key: string, cb?: Function) => string | void;
  set: (key: string, val: string) => void;
  has?: (key: string, cb?: Function) => boolean | void;
};

So val should have type string

What is actually happening?

Method set receives an object with this structure:

{
    html: '<some loong rendered html>',
    components: Set(8) {
        [Function: hook],
        [Function: hook],
        [Function: hook],
        [Function: hook],
        [Function: hook],
        [Function: hook],
        [Function: hook],
        [Function: hook]
    }
}

System Info

No response

Any additional comments?

I was trying to implement Redis for component caching. But due to the type of data passed to set method it is impossible to parse it as a string and store it in a cache. Redis is just removing components property:

{
    html: '<some loong rendered html>',
    components: {}
}

And it break vue-server-renderer, because it expects components to be there:

// node_modules/vue-server-renderer/build.dev.js:8399:26
get(key, function (res) {
  console.log({vsr_res_components: res?.components});
  if (isDef(res)) {
    if (isDef(registerComponent)) {
      registerComponent(userContext);
    }
    res.components.forEach(function (register) { return register(userContext); }); // this breaks, because components are parsed to an empty object
    write(res.html, next);
  } else {
    renderComponentWithCache(node, isRoot, key, context);
  }
});

Vue docs are suggesting that this should be possible, by even giving an example:

const renderer = createRenderer({
  cache: {
    get: (key, cb) => {
      redisClient.get(key, (err, res) => {
        // handle error if any
        cb(res)
      })
    },
    set: (key, val) => {
      redisClient.set(key, val) // but this does not work, as `val` is an object with Set and functions instead of a string, and it can not be stored in Redis
    }
  }
})

I implemented it like this, but it does not work. I also couldn't find any example of working component caching with Redis. Is this even possible?

Closed as duplicate of #7595