Export buffer related methods in server-renderer
What problem does this feature solve?
Since component caching was removed from the V3 releases of server-renderer, I was looking into implementing component caching myself using a wrapper component that renders its default slot to string. The string can then be cached server-side and used from there on when the component should be rendered again.
I'm using the ssrRenderSlotInner
method for that, exported from vue/server-renderer
. I tried other approaches but this one is the cleanest, as the wrapper component doesn't have to implement a lot of boilerplate code. The only exception is the buffer handling: ssrRenderSlotInner
expects a push
method that will push all the rendered parts into a buffer. After execution the resulting nested array needs to be unrolled. Two unexported methods exist in server-renderer that would be very helpful: createBuffer
and unrollBuffer
. With that it would be possible to implement component caching.
What does the proposed API look like?
Export createBuffer
and unrollBuffer
methods. With that component caching can be implemented something like this:
import { defineComponent, useSSRContext, useSlots, getCurrentInstance, h } from 'vue'
import { ssrRenderSlotInner, unrollBuffer, createBuffer } from 'vue/server-renderer'
// The global cache singleton.
import CACHE from '#cache-singleton'
export default defineComponent({
name: 'RenderCacheable',
props: {
cacheKey: {
type: String,
default: '',
},
},
async setup(props) {
const slots = useSlots()
if (process.server) {
const cached = CACHE.get(props.cacheKey)
if (cached) {
return () =>
h('div', {
innerHTML: cached,
})
}
const currentInstance = getCurrentInstance()
const parent = currentInstance.parent
// Render to string.
const { getBuffer, push } = createBuffer()
ssrRenderSlotInner(slots, 'default', {}, null, push, parent)
const markup = await unrollBuffer(getBuffer())
// Save in cache.
CACHE.set(props.cacheKey, markup)
return () =>
h('div', {
innerHTML: markup,
})
}
return () => h('div', slots.default())
},
})
Another option would be to create a new method ssrRenderSlotToString
or similar, that combines ssrRenderSlotInner
with the buffer handling and directly returns a string.
Also, maybe I'm totally going a wrong path here with this approach for component caching. If that's the case I'm very much open for suggestions or hints what might be the best solution here.