N
Nuxt20h ago
Geferon

How to cleanup/dispose resources in a plugin

Hello, I'm currently trying to implement PostHog in my website and I'm implementing it via plugins. Implementing the client plugin is easy, since it's just a .init call which loads their library, but using the serverside library is a little bit difficult, since you have to dispose of it when your server is about to be closed/destroyed. I know that with Vite, I can use the 'close' hook to dispose of it, but is there anything similar that I can do inside of a plugin, or what would the best way of doing it be? I want it to be a plugin since I want to be able to expose the instance to use it inside components and pages. I've seen others clearing resources in the app:rendered hook serverside since that's when pages are going to be rendered, but because the instance is not disposed off and is active when pre-rendering, the build process never finishes as it hasn't been properly disposed, and that hook isn't being called on prerender, so I'm a little bit clueless of what the best way of achieving what I want is.
5 Replies
kapa.ai
kapa.ai20h ago
Hi @Geferon. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Short answer: use the proper lifecycle hooks where shutdown is guaranteed, not an app runtime hook. - If you’re creating a server-side instance (e.g. PostHog) in Nitro, put it in a Nitro server plugin (server/plugins) and clean it up with Nitro’s close hook. Example pattern: - Initialize once when Nitro starts (server/plugins run once per server start) (docs note this in lifecycle) (Nuxt lifecycle – Setup Nitro Server and Nitro Plugins (Once)). - Dispose in the Nitro close hook (runtime) (Nitro app hooks – close). - If you’re building a Nuxt module that wires your plugin, you can also register a build-time close hook to perform cleanup when Nuxt shuts down in dev/build contexts (Nuxt Hooks (build time): close; module usage shown here (Using hooks in modules)). - Avoid using app runtime hooks like app:rendered for disposal. They are SSR-rendering hooks and won’t reliably fire during prerender or at process shutdown, so resources may remain open (App hooks overview). Practical setup: - Server instance: create it in a Nitro plugin (server/plugins/...) and expose it to handlers via shared module scope or by attaching to nitroApp, then dispose in nitroApp.hooks.hook('close', ...) (Nitro app hooks – close; server plugins run once (Nuxt lifecycle – Nitro plugins once)). - Client instance: initialize in a client plugin; for deferring heavy work, onNuxtReady can help on client only (onNuxtReady). Note: nuxtApp context isn’t available in Nitro routes; use Nitro/plugin patterns for server access (useNuxtApp limitation). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai20h ago
<@132953837915996160> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Geferon
GeferonOP20h ago
@kapa.ai if I register it within Nitro how do I expose it to Nuxt so it can be used?
kapa.ai
kapa.ai20h ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Use a Nitro server plugin to create the instance once, then attach it to Nitro or to a shared place you can import from server code. You don’t expose it via useNuxtApp (not available in Nitro routes) (useNuxtApp). Recommended patterns: - Attach to Nitro and access in server code: - Create it in server/plugins/your-plugin.ts, then store it on nitroApp (e.g., nitroApp.someService = instance) and dispose it in the Nitro close hook. Nitro server plugins run once at server start (Nuxt lifecycle – Nitro plugins once). You can register server plugins via addServerPlugin in a module too (addServerPlugin).
- From your server handlers (server/api, server/routes, middleware), access it via the Nitro runtime (e.g., through the plugin’s augmentation), since those files run in Nitro’s context (server directory). - Or place the instance in a shared module and import it where needed on the server: - The Nuxt team suggests using a shared folder (not server/) when you need something available to both Nitro routes and Vue components, but be careful not to leak server-only deps to the client. For server-only use, keeping it in server/ and importing it in server handlers is safe; do not import it from client-bound code (see discussion about server utils not being auto-imported into Vue and avoiding client leakage) (GitHub issue discussion). Note: Public runtime config is added to page payload and accessible in components, while private config stays server-only—use it to configure your instance without exposing secrets (Runtime config). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai20h ago
<@132953837915996160> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?