Created
March 8, 2018 04:11
-
-
Save nirzaq/85e84d2bb0fc4a3ed17aab014e47885f to your computer and use it in GitHub Desktop.
Cache API Call and Cache rendered pages in Next.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const express = require("express"); | |
const cors = require("cors") | |
const { join } = require("path"); | |
const { parse } = require("url"); | |
const next = require("next"); | |
const fetch = require("isomorphic-unfetch") | |
const LRUCache = require('lru-cache') | |
const port = parseInt(process.env.PORT, 10) || 3000; | |
const dev = process.env.NODE_ENV !== "production"; | |
const app = next({ dev }); | |
const handle = app.getRequestHandler(); | |
const apicache = require("apicache") | |
const server = express(); | |
let cache = apicache.middleware | |
const API_URL = `https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Fmedium.com%2Ffeed%2Fwwwid` | |
server.get('/api/feed', cors(), cache('60 minutes'), (req, res) => { | |
fetch(API_URL) | |
.then( r => r.json() ) | |
.then( data => { | |
res.json(data) | |
}); | |
console.log("API SERVED..") | |
}); | |
// This is where we cache our rendered HTML pages | |
const ssrCache = new LRUCache({ | |
max: 100, | |
maxAge: 1000 * 60 * 60 // 1hour | |
}) | |
app | |
.prepare() | |
.then(() => { | |
server.get('/', (req, res) => { | |
renderAndCache(req, res, '/') | |
}) | |
server.get("/articles/:title", (req, res) => { | |
const actualPage = "/article"; | |
const queryParams = { title: req.params.title }; | |
renderAndCache(req, res, actualPage, queryParams); | |
}); | |
server.get("/category/:cat", (req, res) => { | |
const actualPage = "/category"; | |
const queryParams = { cat: req.params.cat }; | |
renderAndCache(req, res, actualPage, queryParams); | |
}); | |
server.get("*", (req, res) => { | |
const parsedUrl = parse(req.url, true); | |
const { pathname } = parsedUrl; | |
if (pathname === "/service-worker.js") { | |
const filePath = join(__dirname, ".next", pathname); | |
app.serveStatic(req, res, filePath); | |
} else { | |
handle(req, res, parsedUrl); | |
} | |
}); | |
server.listen(3000, err => { | |
if (err) throw err; | |
console.log("> Ready on http://localhost:3000"); | |
}); | |
}) | |
.catch(ex => { | |
console.error(ex.stack); | |
process.exit(1); | |
}); | |
/* | |
* NB: make sure to modify this to take into account anything that should trigger | |
* an immediate page change (e.g a locale stored in req.session) | |
*/ | |
function getCacheKey (req) { | |
return `${req.url}` | |
} | |
async function renderAndCache (req, res, pagePath, queryParams) { | |
const key = getCacheKey(req) | |
// If we have a page in the cache, let's serve it | |
if (ssrCache.has(key)) { | |
res.setHeader('x-cache', 'HIT') | |
res.send(ssrCache.get(key)) | |
return | |
} | |
try { | |
// If not let's render the page into HTML | |
const html = await app.renderToHTML(req, res, pagePath, queryParams) | |
// Something is wrong with the request, let's skip the cache | |
if (res.statusCode !== 200) { | |
res.send(html) | |
return | |
} | |
// Let's cache this page | |
ssrCache.set(key, html) | |
res.setHeader('x-cache', 'MISS') | |
res.send(html) | |
} catch (err) { | |
app.renderError(err, req, res, pagePath, queryParams) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Currently, have you used it on production?