arash16 / nuxt-ssr-cache Goto Github PK
View Code? Open in Web Editor NEWCache middleware for nuxt's SSR rendering.
License: MIT License
Cache middleware for nuxt's SSR rendering.
License: MIT License
I'm seeing this warning when using memcached config in the cache. Not sure whats causing this.
My current cache nuxt.config.js
cache: {
useHostPrefix: true,
store: {
type: 'multi',
stores: [
{
type: 'memory',
max: 100,
ttl: 1800
},
{
type: 'memcached',
max: 1000,
ttl: 3600,
options: {
hosts: ['127.0.0.1:11211'],
maxValueSize: 5242880
}
}
]
},
pages: ['/']
},
When i remove memcached, i dont see this warning at all
Hello,
First of all, kudos for the module, it's being really helpful for me so far.
I have a couple of questions that I have not been able to resolve through the documentation.
I've a few pages that I'd like to cache while avoiding others, for my use case I've a dynamic set of routes with this structure:
/en/page-1
/en/page-2
/en/page-3
...
And I would like to cache them while avoiding to cache a route like /en/account
. If I could make an API call to declare the list of pages to cache that would be great.
Sometimes I'd like to force a cache clear when I change content from my CMS. I could do it using a cache system which I could alter from elsewhere like redis, but I'd like to avoid installing new services and keep the in memory cache. Is it feasible?
Thanks
Hi @arash16.
I really like what you did for implementing renderer-level caching for Nuxt. Nice job 👍
Nuxt.js is designed to be extended via modules. While providing API for using programmatically I highly recommend implementing it as a module.
Read more: https://nuxtjs.org/guide/modules
Change should not be really hard. The module exports a function which has access to all internals:
import { cacheRenderer } from './middleware'
export default function (options) {
cacheRenderer(this.nuxt, options)
}
Happy hacking :)
Currently nuxt-ssr-cache
is has a dependence of redis
of v2.8.0.
This is triggering a Security advisory npmjs - https://npmjs.com/advisories/1662
When will this module support redis
v3.1.1 or v3.1.2 - https://www.npmjs.com/package/redis?
Can this module skip caching specific components like the header which loads the user?
nuxtjs v2.10.1
npm run build
node_modules/nuxt-ssr-cache/lib/middleware.js:63
nuxt.renderer is undefined
I use memory mode , when i need to clear cache and i can not see the api from docs.
I tried to use it but it is not working, the component which wraps a axios call still calls the webservice. I also tried to cache all pages by using just '/'. any idea what could be the issue? Thank you
nuxt config:
const isProduction = (process.env.NODE_ENV === 'production')
const host = (isProduction) ? 'api.xxx.com' : 'localhost'
const scheme = (isProduction) ? 'https' : 'http'
const baseUrl = (isProduction) ? '${scheme}://${host}/rest-api' : '${scheme}://${host}:8080/vrmandat-rest-api'
export default {
env: {
api: {
host: host,
scheme: scheme,
baseUrl: baseUrl
},
payment: {
stripe: {
mode: 'test',
test: {
publicKey: 'pk_test_xxx'
},
live: {
publicKey: ''
}
}
}
},
mode: 'universal',
head: {
title: process.env.npm_package_name || '',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: process.env.npm_package_description || '' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
],
script: [
{ src: 'https://www.paypalobjects.com/api/checkout.js' }
]
},
css: [
'@/assets/styles/global.scss'
],
plugins: [
'~/plugins/axios.js',
'~/plugins/validate.js',
'~/plugins/mq.js',
'~/plugins/global.js',
'~/plugins/print.js'
],
buildModules: [
],
modules: [
'bootstrap-vue/nuxt',
'@nuxtjs/axios',
'~/modules/nuxt-auth/lib/module/index.js',
'nuxt-i18n',
'nuxt-stripe-module',
'nuxt-ssr-cache',
],
axios: {
baseURL: '${baseUrl}/',
https: (isProduction) ? true : false,
progress: true,
debug: false
},
/*
** Build configuration
*/
build: {
// Add exception
transpile: [
'vee-validate/dist/rules'
],
/*
** You can extend webpack config here
*/
extend (config, ctx) {
}
},
/*
** Router configuration
*/
router: {
middleware: [
'auth',
'auth-refresh'
]
},
/*
** Auth configuration
*/
auth: {
plugins: [
'~/plugins/auth.js'
],
redirect: {
login: '/auth/login',
logout: '/',
home: '/',
callback: '/auth/callback'
},
strategies: {
local: {
_scheme: 'local',
name: 'local',
endpoints: {
login: {
url: `${baseUrl}/auth/getAccessToken`,
method: 'post',
propertyName: false
},
refresh: {
url: '${baseUrl}/auth/refreshAccessToken',
method: 'post',
propertyName: false
},
logout: {
url: `${baseUrl}/auth/logout`,
method: 'post',
propertyName: false
},
user: {
url: '${baseUrl}/auth/user',
method: 'get',
propertyName: false
}
},
tokenRequired: true,
tokenType: 'Bearer',
tokenName: 'Authorization',
globalToken: true,
accessTokenKey: 'access_token',
refreshTokenKey: 'refresh_token',
automaticRefresh: true,
expiration: {
factor: 0.9,
timeFormat: 'seconds'
}
}
}
},
/*
** i18n configuration
*/
i18n: {
locales: [
{
code: 'en',
name: 'English',
file: 'en.json'
},
{
code: 'de',
name: 'Deutsch',
file: 'de.json'
},
{
code: 'fr',
name: 'Français',
file: 'fr.json'
},
{
code: 'it',
name: 'Italiano',
file: 'it.json'
}
],
lazy: true,
defaultLocale: 'de',
langDir: 'locales/'
},
stripe: {
version: 'v3',
publishableKey: 'pk_test_xxx'
},
cache: {
// if you're serving multiple host names (with differing
// results) from the same server, set this option to true.
// (cache keys will be prefixed by your host name)
// if your server is behind a reverse-proxy, please use
// express or whatever else that uses 'X-Forwarded-Host'
// header field to provide req.hostname (actual host name)
useHostPrefix: false,
pages: [
// these are prefixes of pages that need to be cached
// if you want to cache all pages, just include '/'
'/charts/alter',
],
store: {
type: 'memory',
// maximum number of pages to store in memory
// if limit is reached, least recently used page
// is removed.
max: 100,
// number of seconds to store this page in cache
ttl: 60,
},
},
}
package.json:
{
"name": "app",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate",
"test": "jest"
},
"dependencies": {
"@nuxtjs/auth": "^4.8.4",
"@nuxtjs/axios": "^5.6.0",
"bootstrap": "^4.3.1",
"bootstrap-vue": "2.1.0",
"highcharts": "^7.2.1",
"highcharts-3d": "^0.1.7",
"highcharts-vue": "^1.3.5",
"libphonenumber-js": "^1.7.23",
"moment": "2.24.0",
"nuxt": "2.10.2",
"nuxt-i18n": "^6.0.2",
"nuxt-ssr-cache": "^1.5.1",
"nuxt-stripe-module": "^2.0.0",
"popper.js": "^1.15.0",
"v-click-outside": "^2.1.3",
"vee-validate": "^3.0.3",
"vue-html-to-paper": "^1.1.1",
"vue-mq": "^1.0.1",
"vue-multiselect": "^2.1.6",
"vue-router": "^3.1.3",
"vue-script2": "^2.1.0"
},
"devDependencies": {
"@vue/test-utils": "^1.0.0-beta.27",
"babel-jest": "^24.1.0",
"jest": "^24.1.0",
"node-sass": "^4.12.0",
"sass-loader": "^7.3.1",
"vue-jest": "^4.0.0-0"
}
}
When restarting nuxt, the cache is cleared, this is my mistake or so it is conceived. Is there an option when the cache is permanent
p.s. My error :)
modules: [
[ 'nuxt-ssr-cache', { // options }]
],
https://nuxtjs.org/docs/2.x/directory-structure/modules/#1-moduleoptions
Hey,
I know I can set version: pkg.version,
but it is inside nuxt.config
. So to change it I have to reload app. In my case Im using dynamic pages from API Backend. I know current version in API,
Api update version of pages every time someone add page etc.
So question is:
Can I somehow set version dynamically, and without reloading nuxt app on server?
Like some server middleware?
sorry i don't know why use redis client and quit:
function redisCache(config) {
if (config && Array.isArray(config.configure)) {
const redis = require('redis')
const client = redis.createClient(config.client)
config.configure.forEach(function(options) {
client.config('set', ...options, function(err, result) {
if (err || result !== 'ok') {
console.error(err)
}
})
})
client.quit()
}
return cacheManager.caching({
store: require('cache-manager-redis'),
retry_strategy() {
return undefined
},
...config
})
}
why don't:
function redisCache(config) {
return cacheManager.caching({
store: require('cache-manager-redis'),
retry_strategy() {
return undefined
},
...config
})
}
and maybe we don't need multi-cache?
--- update
and why need serialize cache string?
nuxt.config.js
`
modules: [
'nuxt-ssr-cache',
'@nuxtjs/device',
'@nuxtjs/style-resources',
'@nuxtjs/apollo',
'vue-social-sharing/nuxt'
],
cache: {
useHostPrefix: false,
pages: [
// these are prefixes of pages that need to be cached
// if you want to cache all pages, just include '/'
'/',
],
store: {
type: 'memory',
max: 100,
// number of seconds to store this page in cache
ttl: 60,
},
},
`
And the console still print the logs from created and so on
e.g. to support if-modified-since or if-not-match?
In order to do this, the cached page, would also need to store an etag value and/or a last-modified time...
Then a request can be compared to the stored values and an appropriate 304 response could be returned...
This would then allow CDN's to cache pages, but have clients still check if the content is updated.
I would like to clear a page from cache at some point in the application life.
Suppose I have a cached questions page. If a new question gets created, I'd like a way to remove the page form the cache, so the newly posted question gets added to the new cache.
The cache will be removed either from memory or redis, depending on configuration.
Hi,
We are running Nuxt app with default(recommenced) server. When using and configured nuxt-ssr-cache as defined in readme, it caches nothing with following configurations.
Am I missing something?
import webpack from 'webpack'
import cheerio from 'cheerio'
const nodeExternals = require('webpack-node-externals')
export default {
mode: 'universal',
server: {
port: 80, // default: 3000
host: '0.0.0.0' // default: localhost
},
loading: false,
router: {
middleware: ['redirect'],
extendRoutes(routes, resolve) {
routes.push({
name: 'by_date',
path: '/live/:date',
component: resolve(__dirname, 'pages/live/index.vue')
})
}
},
/*
** Headers of the page
*/
head: {
title: 'title here',
meta: [
{ charset: 'utf-8' },
{
name: 'viewport',
content: 'width=device-width, initial-scale=1, viewport-fit=cover'
},
{
hid: 'description',
name: 'description',
content:
'description here'
}
],
link: [
{
rel: 'icon',
type: 'image/x-icon',
href: 'https://www.xyz.xyz/favicon.ico'
}
],
script: [
{
src: 'https://code.jquery.com/jquery-3.3.1.slim.min.js',
type: 'text/javascript'
},
{
src:
'https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js',
type: 'text/javascript'
}
]
},
icon: {
iconSrc: 'https://www.xyz.xyz/favicon.ico',
iconFileName: 'https://www.xyz.xyz/favicon.ico'
},
/*
** Global CSS
*/
css: ['~/assets/scss/index.scss'],
/*
** Plugins to load before mounting the App
*/
plugins: [
'~plugins/bootstrap.js',
{ src: '~/plugins/vue-slick', ssr: false }
],
/*
** Nuxt.js modules
*/
modules: [
// Doc: https://axios.nuxtjs.org/usage
'@nuxtjs/axios',
'@nuxtjs/pwa',
'@nuxtjs/dotenv',
'cookie-universal-nuxt',
['@nuxtjs/google-tag-manager', { id: '', layer: 'dataLayer' }],
[
'nuxt-fontawesome',
{
imports: [
{
set: '@fortawesome/free-solid-svg-icons',
icons: [
'faCamera',
'faExternalLinkAlt',
'faBars',
'faComment',
'faCheck',
'faArrowRight',
'faChevronLeft',
'faChevronRight',
'faPlay',
'faAlignLeft',
'faTable',
'faTh',
'faFire',
'faNewspaper'
]
}
]
}
],
'nuxt-ssr-cache'
],
cache: {
useHostPrefix: false,
pages: [
'/'
],
key(route, context) {
// custom function to return cache key, when used previous
// properties (useHostPrefix, pages) are ignored. return
// falsy value to bypass the cache
},
store: {
type: 'memory',
// maximum number of pages to store in memory
// if limit is reached, least recently used page
// is removed.
max: 100,
// number of seconds to store this page in cache
ttl: 600
}
},
hooks: {
// This hook is called before rendering the html to the browser
'render:route': (url, result) => {
if (url.startsWith('/embed/')) {
this.$ = cheerio.load(result.html)
this.$('#__nuxt')
.removeAttr('data-server-rendered')
.removeAttr('id')
this.$(`head script`).remove()
this.$(`body script[src^="/_nuxt/"][src$="js"]`).remove()
this.$(`head link[href^="/_nuxt/"][href$="js"]`).remove()
result.html = this.$.html()
}
}
},
/*
** Axios module configuration
*/
axios: {
// See https://github.com/nuxt-community/axios-module#options
},
/*
** Build configuration
*/
build: {
extractCSS: true,
vendor: ['jquery', 'bootstrap'],
plugins: [
new webpack.ProvidePlugin({
$: 'jquery'
})
],
/*
** You can extend webpack config here
*/
extend(config, ctx) {
// Run ESLint on save
if (ctx.isDev && ctx.isClient) {
config.module.rules.push({
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/,
options: {
fix: true
}
})
}
if (ctx.isServer) {
config.externals = [
nodeExternals({
whitelist: [/^vue-slick/]
})
]
}
}
}
}
Hi,
Firstly, I'd like to thank you so much for your extremely helpful module.
In my case, the site I am working on has large number of pages, so, in-memory solutions would not be suitable for me.
If this supports mongodb cache store, this will be a very big adding I believe.
It will be good for local development. Developer can generate part of nuxt config like this:
cache: {
useHostPrefix: true,
pages: [
'/',
],
store: {
type: isDevelopment?'none':'memory',
max: 100,
ttl: 60,
},
},
as described in module that you used https://www.npmjs.com/package/cache-manager
Development environment
You may disable real caching but still get all the callback functionality working by setting none store.
Hi! Thank you for awesome module!
I try to use memcached as a store. But I can't find a way to put ttl to cache options.
function renderSetCache(){ return renderRoute(route, context) .then(function(result) { if (!result.error) { cache.setAsync(cacheKey, serialize(result)); } return result; }); }
In your code from middleware.js you don't put options with ttl in set method of the cache.
node-cache-manager-memcached-store package wait for this signature:
/**
- Set a value for a given key.
- @method set
- @param {String} key - The cache key
- @param {String} value - The value to set
- @param {Object} [options] - The options (optional)
- @param {Object} options.ttl - The ttl value. Default is 2592000 seconds
- @param {Function} [cb] - A callback that returns a potential error, otherwise null
*/
MemcachedClient.prototype.set = function (key, value, options, cb) {
var opt = {
ttl: 2592000
}
Can you fix this or better will be to make a pull request?
Hi!
I would love to use this package but i have discovered a conflict.
If i use this package with Nuxt.js offical storage package universal-storage-module i receive the following error $storage is undefined and cannot use their package. It seems that there is a conflict between the two packages.
Is there a way to fix this.
Have a nice day:)
Regards Joel
This is my configuration, but it does not work:
Latest version of nuxt-ssr-cache (1.5.1) and nuxtjs (2.14.0) is installed.
cache: {
pages: [
'/'
],
store: {
type: 'memory',
max: 100,
ttl: 604800 // 1 week
}
}
Do you have plans to add memcached? I have tried to add it but it doesnt seem to work. I would love to see that implemented.
Hi!
I faced with error "ERROR Cannot redefine property: styles" when nuxt-ssr-cache module is included in nuxt.config.js.
Maybe I doing something wrong, cuz this problem has not issues.
nuxt version 2.15.8.
nuxt-ssr-cache version 1.5.2.
My config:
cache: {
version: pkg.version,
pages: [
/^\/$/,
'/main'
],
key(route, context) {
const hostname = context.req.headers.host || context.req.headers['x-forwarded-host'];
if (!hostname) {
return null;
}
return hostname ? path.join(hostname, route) : route;
},
store: {
type: 'memory',
max: 100,
ttl: 600
}
},
How about to add some function/module in nuxt config, to have ability control cache key and global version without rebuild app.
For examples:
Hi, this is already a good start point, thanks for this middleware.
But I would be even more happy if this could be used to display prerendered/cached pages on the client.
Because at the moment I have one page which displays a lot of data and needs massive api calls. I'm using nuxt-ssr-cache to not hurt the api that much, by caching the site and only reload data / rerender every 30 minutes. This works if the user goes directly to the page (server side rendered).
But if the client goes on front page first and lands through a nuxt-link on that page, the api calls are made again from client side.
Do you know if it is possible to also cache in this case?
/lib/middleware.js
if config.cache.useHostPrefix === true
context.req.hostname is undefined
Different users see different pages,can use cache?
Hello
I want to cache only my home page that is "/"
How can I do this?
pages: [
// you can also pass a regular expression to test a path
'/'
],
The code above is caching all pages.
key function comment doc says:
// custom function to return cache key, when used previous
// properties (useHostPrefix, pages) are ignored.
That is not true, if pages is not set with at least one element, cache is not initialiazed at all due the if statement: https://github.com/arash16/nuxt-ssr-cache/blob/master/src/middleware.js#L34
OS: MacOS
Node: 10.15
Nuxt: 2.6.2
Steps to reproduce:
Module settings:
export const cache = {
useHostPrefix: true,
store: {
type: 'memory',
// maximum number of pages to store in memory
max: 100,
// number of seconds to store this page in cache
ttl: 3600,
},
pages: [
'/',
],
}
Latest pull request is not applied in npm because the version is still 1.5.1.
From the looks of it this looks like a very interesting package - so good job so far!
I do, however, think this documentation needs some more information on what it caches exactly. Does it cache my axios / async data calls? How do I purge the cache? What are the expected load time difference?
Great work with this module! I have one problem though as it's only caching on path and not including host when it's adding and checking for cache.
On our localized site (localized with i18n) the result is that we get the same page (same localized content) on all domains (.se, .uk, .no) when the path i the same (e.g. the start page).
Anyway to solve this?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.