diff --git a/examples/ssr-caching/README.md b/examples/ssr-caching/README.md new file mode 100644 index 00000000..2b36134b --- /dev/null +++ b/examples/ssr-caching/README.md @@ -0,0 +1,31 @@ + +# Example app where it caches SSR'ed pages in the memory + +## How to use + +Download the example (or clone the repo)[https://github.com/zeit/next.js.git]: + +```bash +curl https://codeload.github.com/zeit/next.js/tar.gz/master | tar -xz --strip=2 next.js-master/examples/ssr-caching +cd ssr-caching +``` + +Install it and run: + +```bash +npm install +npm run dev +``` + +Deploy it to the cloud with [now](https://zeit.co/now) ([download](https://zeit.co/download)) + +```bash +now +``` + +## The idea behind the example + +React Server Side rendering is very costly and takes a lot of server's CPU power for that. One of the best solutions for this problem is cache already rendered pages. +That's what this example demonstrate. + +This app uses Next's [custom server and routing](https://github.com/zeit/next.js#custom-server-and-routing) mode. It also uses [express](https://expressjs.com/) to handle routing and page serving. diff --git a/examples/ssr-caching/package.json b/examples/ssr-caching/package.json new file mode 100644 index 00000000..a709de48 --- /dev/null +++ b/examples/ssr-caching/package.json @@ -0,0 +1,10 @@ +{ + "scripts": { + "start": "node server.js" + }, + "dependencies": { + "express": "^4.14.0", + "lru-cache": "^4.0.2", + "next": "^2.0.0-beta" + } +} diff --git a/examples/ssr-caching/pages/blog.js b/examples/ssr-caching/pages/blog.js new file mode 100644 index 00000000..0ad84704 --- /dev/null +++ b/examples/ssr-caching/pages/blog.js @@ -0,0 +1,17 @@ +import React from 'react' + +export default class extends React.Component { + static getInitialProps ({ query: { id } }) { + return { id } + } + + render () { + return
+

My {this.props.id} blog post

+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. +

+
+ } +} diff --git a/examples/ssr-caching/pages/index.js b/examples/ssr-caching/pages/index.js new file mode 100644 index 00000000..72cee8ed --- /dev/null +++ b/examples/ssr-caching/pages/index.js @@ -0,0 +1,9 @@ +import Link from 'next/link' + +export default () => ( + +) diff --git a/examples/ssr-caching/server.js b/examples/ssr-caching/server.js new file mode 100644 index 00000000..86b9d935 --- /dev/null +++ b/examples/ssr-caching/server.js @@ -0,0 +1,58 @@ +const express = require('express') +const next = require('next') +const LRUCache = require('lru-cache') + +const app = next({ dir: '.', dev: true }) +const handle = app.getRequestHandler() + +// This is where we cache our rendered HTML pages +const ssrCache = new LRUCache({ + max: 100, + maxAge: 1000 * 60 * 60 // 1hour +}) + +app.prepare() +.then(() => { + const server = express() + + // Use the `renderAndCache` utility defined below to serve pages + server.get('/', (req, res) => { + renderAndCache(req, res, '/') + }) + + server.get('/blog/:id', (req, res) => { + const queryParams = { id: req.paradms.id } + renderAndCache(req, res, '/blog', queryParams) + }) + + server.get('*', (req, res) => { + return handle(req, res) + }) + + server.listen(3000, (err) => { + if (err) throw err + console.log('> Ready on http://localhost:3000') + }) +}) + +function renderAndCache (req, res, pagePath, queryParams) { + // If we have a page in the cache, let's serve it + if (ssrCache.has(req.url)) { + console.log(`CACHE HIT: ${req.url}`) + res.send(ssrCache.get(req.url)) + return + } + + // If not let's render the page into HTML + app.renderToHTML(req, res, pagePath, queryParams) + .then((html) => { + // Let's cache this page + console.log(`CACHE MISS: ${req.url}`) + ssrCache.set(req.url, html) + + res.send(html) + }) + .catch((err) => { + app.renderError(err, req, res, pagePath, queryParams) + }) +}