Next.js: how to persist data server-side to access it from page calls

Viewed 1628

I have a Next.js app with a custom server (Express) that does some stuff continuously and keeps some data in memory as long as the server is alive.

I want to access this data from the API calls (pages). What is the proper way to store and access it?

My server index file:

    import { createServer } from 'http'
    import express from 'express'
    import { parse } from 'url'
    import next from 'next'
    import pinoHttp from 'pino-http'
    
    const logger = pinoHttp()
    const dev = process.env.NODE_ENV !== 'production'
    const nextApp = next({ dev })
    
    try {
      const handle = nextApp.getRequestHandler()
      const port = process.env.NODE_PORT || 3000
      
      nextApp.prepare().then(() => {
        const app = express()
        app.locals.myArray = []
        
        // Do stuff in the background that will update the array
        
        createServer((request, response) => {
          const parsedUrl = parse(request.url, true)

          logger(request, response)
          handle(request, response, parsedUrl)
        }).listen(port, (error?: Error) => {
          if (error) throw error
        
          console.log(`Listening on: http://localhost:${port}`)
        })
      })
    } catch (error) {
      console.log(error)
      process.exit(1)
    }

My page:

    import { Request, Response } from 'express'
    
    export default async function (request: Request, response: Response): Promise<void> {
      // Here, request.app and response.app are both undefined.
    }
1 Answers

If your data only needs to persist as long as your nodejs program is running you can store it in RAM using the Map object. Maps are collections of key / value pairs much like C# Dictionaries, python dictionaries, or php arrays.

You can create this object just once when you start up and then attach it to your Express app object like so.

var app = express();
app.locals.myMap = new Map()

Then, in each route handler you can refer to it like so.

const myMap = req.app.locals.myMap

Then you can write code like this:

let userdata = {}
const username = 'whatever'
if(myMap.has(username)) {
   userdata = myMap.get(username)
}
...
myMap.set(username, userdata)

This particular example stores a userdata object in the Map for each username.

Obviously the Map vanishes without a trace if your nodejs stops for whatever reason.

You can put anything you like in app.locals; it doesn't have to be a Map.

Related