Page level caching

Timkor
6
Timkor
commented 8 months ago

What problem does this feature solve?

Reduce server side rendering time using page level caching.

What does the proposed changes look like?

We could use component cache. But this is still quite unnecessarily slow.

Would be nice to have a page level cache built in into Nuxt. See page level caching at Vue docs

What would be nice is a function with accepts a route and returns a cache key if it's able to be cached.

idea
0
GillesWHC
0
GillesWHC
commented 8 months ago

Definitely a must for our project. Would love to see this.

0
DenzoNL
0
DenzoNL
commented 8 months ago

+1, would be really nice to have this feature! My web application is rather slow now, and a built-in solution would be highly preferable over some random package.

0
henriqemalheiros
0
henriqemalheiros
commented 8 months ago

Duplicate of #4698. Ideally, we would all be using NGINX, but @clarkdo suggested this module. Here's a stripped down version of that with simple queuing I wrote and use:

import LRU from 'lru-cache'

const stringify = obj => JSON.stringify(obj, (k, v) =>
  typeof v === 'object' && v instanceof Set
    ? [ 'set', [ ...v ] ]
    : typeof v === 'function'
      ? [ 'func', v() ]
      : v
)

const parse = str => JSON.parse(str, (k, v) =>
  Array.isArray(v) && v.length === 2
    ? v[0] === 'set'
      ? new Set(v[1])
      : v[0] === 'func'
        ? () => v[1]
        : v
    : v
)

export default function ({ max = 100, maxAge = 3000 } = {}) {
  const cache = new LRU({
    max,
    maxAge,
  })

  const queue = new Map()

  const renderer = this.nuxt.renderer
  const renderRoute = renderer.renderRoute.bind(renderer)

  renderer.renderRoute = function (route, context) {
    if (cache.has(route)) {
      const cached = cache.get(route)

      if (cached) {
        return parse(cached)
      }
    }

    if (queue.has(route)) {
      const queued = queue.get(route)

      if (queued) {
        return queued
      }
    }

    const promise = new Promise((resolve, reject) => {
      renderRoute(route, context)
        .then((result) => {
          if (!result.error) {
            cache.set(route, stringify(result))
          }

          return resolve(result)
        })
        .catch((err) => {
          return reject(err)
        })
        .finally(() => {
          queue.delete(route)
        })
    })

    queue.set(route, promise)

    return promise
  }
}
0
mauxtin
0
mauxtin
commented 7 months ago

It would be great to have this supported out of the box though. Maybe we should leave it open as feature request? /cc @manniL

0
Informations
Feature Request โ€ข Open
#c8983 - Created 8 months ago