All Projects → rjyo → Next Boost

rjyo / Next Boost

Add a cache layer for server-side-rendered pages with stale-while-revalidate. Can be considered as an implementation of next.js's Incremental Static Regeneration which works with getServerSideProps.

Programming Languages

typescript
32286 projects

Projects that are alternatives of or similar to Next Boost

React Esi
React ESI: Blazing-fast Server-Side Rendering for React and Next.js
Stars: ✭ 537 (+124.69%)
Mutual labels:  cache, nextjs, ssr
Gank
🦅 Gank api base △ next.js (react&ssr)
Stars: ✭ 122 (-48.95%)
Mutual labels:  nextjs, ssr
Wild Next
Our next.js boilerplate with sane base configuration.
Stars: ✭ 101 (-57.74%)
Mutual labels:  nextjs, ssr
Next I18next
The easiest way to translate your NextJs apps.
Stars: ✭ 2,818 (+1079.08%)
Mutual labels:  nextjs, ssr
Oh My Fullstack
🚀 Full stack web application skeleton (Next.js, Redux, RxJS, Immutable, Express)
Stars: ✭ 99 (-58.58%)
Mutual labels:  nextjs, ssr
Serverless With Next5 Boilerplate
Serverless.js with Next.js 5 on AWS, powered by the Serverless Framework
Stars: ✭ 100 (-58.16%)
Mutual labels:  nextjs, ssr
React Prerendered Component
🤔Partial hydration and caching in a pre-suspense era
Stars: ✭ 141 (-41%)
Mutual labels:  cache, ssr
Wordpress Api Nextjs Theme
A workshop on creating a WordPress theme with React and Next.js for WordCamp Montreal
Stars: ✭ 36 (-84.94%)
Mutual labels:  nextjs, ssr
Next Firebase Ssr
An Next.js example repo for building authenticated pages with Firebase Authentication, cookies, and getServerSideProps
Stars: ✭ 192 (-19.67%)
Mutual labels:  nextjs, ssr
Next Routes
Universal dynamic routes for Next.js
Stars: ✭ 2,354 (+884.94%)
Mutual labels:  nextjs, ssr
Mordred
[Experimental] Source data from anywhere, for Next.js, Nuxt.js, Eleventy and many more.
Stars: ✭ 208 (-12.97%)
Mutual labels:  nextjs, ssr
Next Offline
make your Next.js application work offline using service workers via Google's workbox
Stars: ✭ 1,306 (+446.44%)
Mutual labels:  cache, nextjs
Nextjs Jwt Example
next.js authorization example including private route protection
Stars: ✭ 72 (-69.87%)
Mutual labels:  nextjs, ssr
Next Express Bootstrap Boilerplate
⚡️ JavaScript boilerplate for a full stack app built using React.js, Next.js, Express.js, react-bootstrap, SCSS and full SSR with eslint.
Stars: ✭ 102 (-57.32%)
Mutual labels:  nextjs, ssr
Next.js Conf 2020
From Front-end to Full Stack with Amplify Framework
Stars: ✭ 40 (-83.26%)
Mutual labels:  nextjs, ssr
Egg React Ssr
最小而美的Egg + React + SSR 服务端渲染应用骨架,同时支持JS和TS
Stars: ✭ 1,837 (+668.62%)
Mutual labels:  nextjs, ssr
Firebase Functions Next Example
Host a Next.js SSR React app on Cloud Functions for Firebase with Firebase Hosting
Stars: ✭ 215 (-10.04%)
Mutual labels:  nextjs, ssr
Yunle Template Next
yunle-cli 前端开发模板- node 专为线上渲染中间层
Stars: ✭ 13 (-94.56%)
Mutual labels:  nextjs, ssr
Next Pwa
Zero config PWA plugin for Next.js, with workbox 🧰
Stars: ✭ 909 (+280.33%)
Mutual labels:  cache, nextjs
React Ssr
react16 next.js4 antd-mobile2 redux
Stars: ✭ 171 (-28.45%)
Mutual labels:  nextjs, ssr

CI Coverage Status Maintainability

next-boost

next-boost adds a cache layer to your SSR (Server-Side Rendering) applications. It was built originally for Next.js and should work with any node.js http.Server based application.

next-boost achieves great performance by rendering webpages on worker_threads while serving the cached on the main thread.

If you are familiar with Next.js, next-boost can be considered as an implementation of Incremental Static Regeneration which works with getServerSideProps.

$ npm install next-boost --save

Features

  • Drop-in replacement for Next.js's production mode: next start
  • Greatly reducing the server TTFB (time-to-first-byte)
  • Non-blocking main process for cache-serving and using worker_threads for SSR
  • Simultaneous requests with the first one rendered and the rest served from the cache
  • Small footprint with less than 200 LOC
  • Used in production with 300K pages cached
  • As a database-disk-hybrid cache
    • no memory capacity limit, and works great on cheap VPSs
    • no need to add a cache layer server like varnish, nginx Cache and etc.
    • great performance, and may even have better performace than pure file system cache
    • portability on major platforms

Use next-boost cli with Next.js

After install the package, just change the start script from next start to next-boost. All next start's command line arguments, like -p for specifing the port, are compatible.

 "scripts": {
    ...
    "start": "next-boost", // previously `next start`
    ...
  },

Examples

There's an example under examples/nodejs, which works with a plain http.Server.

To use it with express.js and next.js, please check examples/with-express.

Performance

By using worker_threads, the CPU-heavy SSR rendering will not blocking the main process from serving the cache.

Here are the comparision of using ApacheBench on a blog post fetched from database. HTML prerendered and the db operation takes around 10~20ms. The page takes around 200ms for Next.js to render.

$ /usr/local/bin/ab -n 200 -c 8 http://127.0.0.1:3000/blog/posts/2020/3/postname

Not a scientific benchmark, but the improvements are visibly huge.

with next start (data fetched with getServerSideProps):

Document Length:        76424 bytes
Concurrency Level:      8
Time taken for tests:   41.855 seconds
Complete requests:      200
Failed requests:        0
Total transferred:      15325600 bytes
HTML transferred:       15284800 bytes
Requests per second:    4.78 [#/sec] (mean)
Time per request:       1674.185 [ms] (mean)
Time per request:       209.273 [ms] (mean, across all concurrent requests)
Transfer rate:          357.58 [Kbytes/sec] received

with the drop-in next-boost cli:

Document Length:        78557 bytes
Concurrency Level:      8
Time taken for tests:   0.149 seconds
Complete requests:      200
Failed requests:        0
Total transferred:      15747600 bytes
HTML transferred:       15711400 bytes
Requests per second:    1340.48 [#/sec] (mean)
Time per request:       5.968 [ms] (mean)
Time per request:       0.746 [ms] (mean, across all concurrent requests)
Transfer rate:          103073.16 [Kbytes/sec] received

It even outperforms next.js's static generated page (getStaticProps), handling 2~2.5x requests per seconds in my environment.

How it works

next-boost implements a server-side cache in the manner of stale-while-revalidate. When an expired (stale) page is accessed, the cache will be served and at the same time, a background process will fetch the latest version (revalidate) of that page and save it to the cache.

There are 2 parameters to control the behavior of the cache:

  • ttl (time-to-live): After ttl, the cache will be revalidated. And a cached page's ttl will be updated when a page is revalidated.
  • tbd (time-before-deletion): When a page is not hit again in ttl + tbd seconds, it will be completely remove from cache.

Advanced Usages

Deleting/Revalidating a Single URL

By sending a GET with header x-cache-status:update to the URL, the cache will be revalidated. And if the page doesn't exists anymore, the cache will be deleted.

curl -H x-cache-status:update https://the_server_name.com/path_a

Batch Deleting/Revalidating

If you want to delete mutiple pages at once, you can run SQL on the cache directly:

sqlite3 /cache_path/cache.db "update cache set ttl=0 where key like '%/url/a%';"

This will force all urls containing /url/a to be revalidated when next time accessed.

Deleting cache_path will remove all the caches.

Filtering Query Parameters

By default, each page with different URLs will be cached separately. But in some cases you would like, /path_a?utm_source=twitter to be served with the same contents of /path_a. paramFilter is for filtering the query parameters.

// in .next-boost.js
{
  ...
  paramFilter: (p) => p !== 'utm_source'
}

Changing the cache key

By default, the URL will be used as the key for cached pages. If you want to server pages from different domains or by different user-agent, you can use this function to custom the cache key.

Notes:

  • If there's any exception thrown from this function, or the returned value is not a string, your server will crash.
// in .next-boost.js
{
  ...
  cacheKey: (req) => (req.headers.host || '') + ':' + req.url
}

All Configurable Options

If available, .next-boost.js at project root will be used. If you use next-boost programmatically, the filename can be changed in options you passed to CachedHandler.

tips: If you are using next-boost cli with Next.js, you may want to use the config file.

And here's an example .next-boost.sample.js in the repo.

By default, all URLs will be cached under the default rule .*. You can change the rules programmatically or by .next-boost.js:

module.exports = {
  rules: [
    { regex: '^/blog.*', ttl: 300 },
  ],
}

Above: only caching pages with URL start with /blog.

interface HandlerConfig {
  filename?: string
  quiet?: boolean
  cache?: {
    ttl?: number
    tbd?: number
    path?: string
  }
  rules?: Array<URLCacheRule>
  paramFilter?: ParamFilter
  cacheKey?: CacheKeyBuilder
}

interface URLCacheRule {
  regex: string
  ttl: number
}

type ParamFilter = (param: string) => boolean
type CacheKeyBuilder = (req: IncomingMessage) => string

Logging

Logging is enabled by default. If you use next-boost programmatically, you can disable logs by passing the quiet boolean flag as an option to CachedHandler.

...
const cached = await CachedHandler(args, { quiet: true });
...

There's also a --quiet flag if you are using the command line.

Limitations

  • For architecture with multiple load-balanced rendering servers, the benefit of using next-boost is limited. Until the url is hit on every backend server, it can still miss the cache. Use reverse proxy with cache support (nginx, varnish etc) for that.
  • GET and HEAD requests only.
  • worker_threads is used and it is a node.js 12+ feature.

FAQs

Notice about Next.js's custom server

next-boost works as an in-place replacement for next start by using Next.js's custom server feature.

On the linked page above, you can see the following notice:

Before deciding to use a custom server please keep in mind that it should only be used when the integrated router of Next.js can't meet your app requirements. A custom server will remove important performance optimizations, like serverless functions and Automatic Static Optimization.

next-boost is meant to be used on cloud VPS or containers, so serverless function is not an issue here. As to Automatic Static Optimization, because we are not doing any app.render here, it still works, as perfect as always.

Why SQLite

Here's the article about when not to use SQLite. And for next-boost's main purpuse: super faster SSR on low-cost VPSs, as far as I know, it is the best choice.

License

MIT. Copyright 2020 Rakuraku Jyo.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].