vue
vue copied to clipboard
SSR Component Cache doesn't cache Strings
Version
2.5.13
Reproduction link
https://runkit.com/martinlg/issue-vue-renderer-cache
Steps to reproduce
Run the Runkit code. If you prefer a git repository I can provide you one.
What is expected?
The value passed to the set
function should be a string.
What is actually happening?
The value passed to the set
function is an object, with 2 properties:
- html: a
string
containing the rendered component - components: a
Set
containing nothing or function, depending on context (sub-components I think)
This issue breaks any external cache possibility (Redis in my case). The only possible cache is in the process memory, like the LRUCache, but it seems impossible to scale processes and share a common cache.
Moreover, the documentation explain clearly that the cached value should be a string, and even provides a small Redis example implementation, that could just not work.
I think that the documentation describe the expected behavior, so I don't want to "fix" the documentation, I think we should fix the behavior.
I will try to help but I may need some explanations on some parts of the RenderContext, can I ask my questions on this thread ?
#7593 Old issue, rejected for heavy example.
I don't think SSR cache behavior is expected, either.
https://github.com/vuejs/vue/blob/dev/packages/vue-server-renderer/types/index.d.ts#L46-L48
However, component cache also needs to cache component's lifecycle in rendering. So the type definition and documentation are both outdated.
Actually, I don't see why we should cache component's lifecycle in rendering.
The component should be rendered, its template should be cached as a string (the html part of the currently stored object). Then when the component get fetched from the cache, it's template is static, and should not depend of the store. So I don't see why we should register all its child components.
Of course the browser takes back the hand, and make them dynamic like every components.
Did I miss something ?
I just tried to remove the component registration and I see now that it breaks the inline styles on the cached version.
Still looking for a solution to store the cache on an external data store.
@Atinux This is the issue I told you about. If you have any suggestions that could help me on SSR, I would love to ear it.
I don't believe caching doesn't work as it should be o_O Maybe some PR will help fix this? And it still opened... from February? Does no one use the cache or what?
Any updates on this? Having same issue with redis client.
the same issue . I want to use redis client , but the components is a Set .
Wow, this is just extremely disappointing. Especially since the SSR docs explicitly show a redis client example. https://ssr.vuejs.org/api/#cache
Has there been any progress on this or has everyone given up on having a shared cache?
This will make it work, but I am not sure how safe it is considering that is doesn't provide back the register callbacks (no idea what they're needed for):
cache: {
get: (key, cb) => {
redisClient.get(key).then((res) => {
if (!res) cb();
else cb({ components: [], html: res });
});
},
set: (key, val) => {
redisClient.set(key, val.html);
},
},
The same problem, now try use similar code as @CyberAP, but my inline styles not worked
UPDATE
Try add yahoo/serialize-javascript
, but code include some global vars: injectStyles
, moduleIdentifier
function (context) {
// 2.3 injection
context =
context || // cached call
(this.$vnode && this.$vnode.ssrContext) || // stateful
(this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional
// 2.2 with runInNewContext: true
if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
context = __VUE_SSR_CONTEXT__
}
// inject component styles
if (injectStyles) {
injectStyles.call(this, context)
}
// register component module identifier for async chunk inferrence
if (context && context._registeredComponents) {
context._registeredComponents.add(moduleIdentifier)
}
}
@CyberAP solutions seems working but I don't think it's too safe to use cache without components set. So is there any other solution for this?
The same problem, now try use similar code as @CyberAP, but my inline styles not worked UPDATE Try add
yahoo/serialize-javascript
, but code include some global vars:injectStyles
,moduleIdentifier
function (context) { // 2.3 injection context = context || // cached call (this.$vnode && this.$vnode.ssrContext) || // stateful (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional // 2.2 with runInNewContext: true if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') { context = __VUE_SSR_CONTEXT__ } // inject component styles if (injectStyles) { injectStyles.call(this, context) } // register component module identifier for async chunk inferrence if (context && context._registeredComponents) { context._registeredComponents.add(moduleIdentifier) } }
Sorry, where actually did you put this code?
@SuperIbm
This code i get from cache.set
arg val.components
, it some internally function of vue-renderer
Get it when try place it to redis