Skip to content

Component caching - wrong type returned in a set method #13175

Closed as not planned
@AnJ-Github

Description

@AnJ-Github

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions