cache
Although the server-side rendering (SSR) of Vue is quite fast, due to the overhead of creating component instances and virtual DOM nodes, it cannot match the performance of pure string based templates. When SSR performance is critical, using cache strategy wisely can greatly improve response time and reduce server load.
vue service area cache is divided into page cache, build cache and interface cache
Page cache:
Set in server.js
const LRU = require('lru-cache') const microCache = LRU({ max: 100, // Maximum number of caches maxAge: 1000 // Important: entries expire in 1 second. }) const isCacheable = req => { //Determine whether page caching is required if (req.url && req.url === '/') { return req.url } else { return false } } app.get('*', (req, res) => { const cacheable = isCacheable(req) if (cacheable) { const hit = microCache.get(req.url) if (hit) { return res.end(hit) } } const errorHandler = err => { if (err && err.code === 404) { // Page not found res.status(404).sendfile('public/404.html'); } else { // Page rendering error res.status(500).end('500 - Internal Server Error') console.error(`error during render : ${req.url}`) console.error(err) } } const context = { title: 'vue', keywords: 'vue-ssr Service end scaffold', description: 'vue-ssr-template, vue-server-renderer', version: v, url: req.url, cookies: req.cookies } renderer.renderToString(context, (err, html) => { if (err) { return errorHandler(err) } res.end(html) microCache.set(req.url, html) // Set the content of the current cached page }) })
Build cache:
The settings in server.js are as follows:
function createRenderer(bundle, template) { return require('vue-server-renderer').createBundleRenderer(bundle, { template, cache: LRU({ max: 1000, maxAge: 1000 * 60 * 5 // Build cache time }) }) } let renderer if (isProd) { // The production environment uses local packaging files for rendering const bundle = require('./output/vue-ssr-bundle.json') const template = fs.readFileSync(resolve('./output/index.html'), 'utf-8') renderer = createRenderer(bundle, template) } else { // Development environment using web pack hot update service require('./build/dev-server')(app, (bundle, template) => { renderer = createRenderer(bundle, template) }) }
Build to cache
export default { name: 'Home', title() { return { title: 'vue-ssr', keywords: 'vue-ssr Service end scaffold, home', description: 'vue-ssr-template, vue-server-renderer, home' } }, created() { }, computed: {}, asyncData({ store }) {}, methods: {}, serverCacheKey: props => props.id }
The key returned by serverCacheKey should contain enough information to represent the specific situation of the rendering result. If the rendering result is only determined by props.item.id, then the above is a good implementation. However, if an item with the same ID may change over time, or if the rendering results depend on other props, you need to modify the implementation of serverCacheKey to consider other variables. If serverCacheKey returns a constant, the component will always be cached, which is good for static components.
Interface cache:
Set cache in create API server.js
import qs from 'qs'
import axios from 'axios'
import md5 from 'md5'
import LRU from 'lru-cache'const microCache = LRU({
max: 100,
maxAge: 5000 // Set how long data expires
})export function createAPI({baseUrl, timeout}) {
let apiif (process.__API__) { api = process.__API__ } else {
// Define the global variable process. API__ api = process.__API__ = { get(url, params = {}) { const key = md5(url + JSON.stringify(params)) // Judge whether there is a cache and return the cache result directly if (params.cache && microCache.get(key)) { console.log('Return cache') return Promise.resolve(microCache.get(key)) } return new Promise((resolve, reject) => { axios({ url, params, headers: { 'X-Requested-With': 'XMLHttpRequest' // 'Cookie': parseCookie(SSR.cookies) }, method: 'get' }).then(res => { // Determine whether cache is needed if cache data is needed if (params.cache && microCache) { microCache.set(key, res.data) } console.log('Return new data') resolve(res.data) }).catch(error => { reject(error) }) }) }, post(url, params = {}) { const key = md5(url + JSON.stringify(params)) // Judge whether there is a cache and return the cache result directly if (params.cache && microCache.get(key)) { return Promise.resolve(microCache.get(key)) } return new Promise((resolve, reject) => { axios({ url, data: qs.stringify(params), method: 'post', headers: { 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/x-www-form-urlencoded' // 'Cookie': parseCookie(SSR.cookies) } }).then(res => { // Determine whether cache is needed if cache data is needed if (params.cache && microCache) { microCache.set(key, res.data) } resolve(res.data) }).catch(error => { reject(error) }) }) } } }
return api
}
That's ok