我正在尝试让组件缓存在 Vue 2(使用 Nuxt 2)中工作。
现在我们有来自 nuxt-multi-cache 的典型 LRU 实现,但我们想过渡到使用 Redis(这样它就在 Pod 之外,我们可以轻松地使其失效)。我已经准备好基本设置,组件保存在 Redis 中并由 Vue 读取。但是在解析Redis返回的数据的时候就崩溃了。
在
vue-server-renderer
中有一段接收Redis输出的代码:
// 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); });
write(res.html, next);
} else {
renderComponentWithCache(node, isRoot, key, context);
}
});
它正在突破这条线:
res.components.forEach(function (register) { return register(userContext); });
这么说
res.components.forEach is not a function
所以我的实现看起来像这样。
cache: {
get: (key, cb) => {
redisClient.get(key, (err, res) => {
console.log(res)
cb(res)
})
},
set: (key, val) => {
console.log(val)
redisClient.set(key, val)
}
}
遵循 Vue 文档中的类型声明:
type RenderCache = {
get: (key: string, cb?: Function) => string | void;
set: (key: string, val: string) => void;
has?: (key: string, cb?: Function) => boolean | void;
};
经过一番调查,我发现问题是在我们将数据保存到 Redis 时发生的。它解析它并删除部分数据。 我控制台我们在
set
方法中获得的记录数据(我们从 Vue 获得的渲染组件应该进入缓存以供将来使用)。
我得到了这个:
{
html: '<some loong rendered html>',
components: Set(8) {
[Function: hook],
[Function: hook],
[Function: hook],
[Function: hook],
[Function: hook],
[Function: hook],
[Function: hook],
[Function: hook]
}
}
因此,Vue 似乎破坏了自己的类型声明,我们得到的不是简单的字符串,而是一些带有组件的奇怪对象,其中包含带有函数的 Set。
显然这不能解析为字符串,所以 Redis 客户端只是将其删除:
{
html: '<some loong rendered html>',
components: {}
}
但现在的问题是——我该如何克服这个问题?我找不到将它们保存到 Redis 中的方法,但应该有一种方法可以使用 Redis 实现组件缓存。甚至 Vue 文档也说这应该是可能的: https://v2.ssr.vuejs.org/api/#cache。 但有关它的文档和资源确实很少。尤其是这个 Vue 版本即将结束生命。
请发送帮助
只需将
component
属性设置为对我有用的数组:
cache: {
set: (key, val) => {
val.components = [];
redisClient.set(key, JSON.stringify(val))
}
}
我认为发生这种情况是因为 JSON.stringify 将
Set
转换为对象而不是数组:
const componentMock = {
html: "<html>...</html>",
components: new Set([function foo() {}, function bar() {}])
}
console.log("Wrong, as object", JSON.parse(JSON.stringify(componentMock)));
console.log("Correct, as array", JSON.parse(JSON.stringify({...componentMock, components: []})));
还有一些方法可以指定 JSON.stringify 应如何以更通用的方式处理编码规则这里。