10

I have an analytics utility like this:

class Analytics {
    data: Record<string, IData>;

    constructor() {
        this.data = {};
    }
    setPaths(identifier: string) {
        if (!this.data[identifier])
            this.data[identifier] = {
                generic: getGenericInit(),
                session: getSessionInit(),
                paths: {
                    geoCollectionPath: '',
                    sessionCollectionPath: '',
                    eventsCollectionPath: ''
                }
            };
        this.data[identifier].paths = {
            geoCollectionPath: getGeoPath(identifier),
            sessionCollectionPath: getSessionPath(identifier),
            eventsCollectionPath: getEventPath(identifier)
        };
    }
    getAll() {
        return this.data;
    }
}

const analytics = new Analytics();
export default analytics;

And I import it into 2 api folders: e1.ts and e2.ts.

e1.ts:

import { NextApiHandler } from 'next';
import analytics from '@/firebase/v2/analytics';

const handler: NextApiHandler = (req, res) => {
    analytics.setPaths('abc');
    return res.status(201).end();
};
export default handler;

and e2.ts:

import { NextApiHandler } from 'next';
import analytics from '@/firebase/v2/analytics';

const handler: NextApiHandler = (req, res) => {
    return res.status(200).json(analytics.getAll());
};
export default handler;

Now even when I add the data by hitting /api/e1 since the import instantiates a fresh class in e2, I fail to retrieve the data from /api/e2. How can I achieve my use case for this?

I also tried using static instance but that doesn't work as well. Can someone help me in finding a solution to this?

0

1 Answer 1

16

In development, Next clears Node.js cache on run, so every time there is a "compiling..." in the terminal (which happens per page render), it starts as a new app, losing any previous variable.

This is why, in this article, down to the section where they instantiate a PrismaClient, to have it created only once, they use the global object, in your case, like so:

let analytics;

if (process.env.NODE_ENV === "production") {
  analytics = new Analytics();
} else {
  if (!global.analytics) {
    global.analytics = new Analytics();
  }
  analytics = global.analytics;
}

export default analytics;
Sign up to request clarification or add additional context in comments.

2 Comments

I'd like to add a caveat to this solution. If you're developing with hot module replacement (e.g. using next dev), this will prohibit new code from being loaded. So whenever you make changes to the Analytics class, the first version of the class instance may be stored globally, and any later versions will never be instantiated, so new code won't run unless you restart the dev server. If you're aware of this, then this solution works well.
Does this clearing of cache concept applies to Next.js Route Handlers?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.