Main
Contents
Handle application lifecycle events via main.ts.
main.ts
Enonic apps may contain a special main.ts at src/main/resources/main.ts.
main.ts is invoked when an application lifecycle event occurs. A common use is initialization — creating repositories, registering event listeners when the application starts — and cleaning up resources when the application stops.
The code should complete as quickly as possible to prevent the application from stalling. Never call remote endpoints or wait in loops for events at the top level of main.ts.
main.ts blocks the rest of the application. Nothing else in the same app runs until its top-level code returns — HTTP functions, component implementations, tasks and event listeners all wait. This is what makes main.ts a dependable place to initialize: a controller can never observe a half-initialized repository. The flip side is that slow start-up code delays the app’s first responses, so keep it short. Code called from main.ts itself is exempt — it is part of the start-up. If start-up has not finished within five minutes, XP logs a warning and lets the waiting executions proceed anyway. Other applications are unaffected; each app waits only for its own main.ts. |
If you need to perform time-consuming work during startup, run it from a task instead. Submitting the task returns immediately; the task itself starts once main.ts has returned. |
Add a main.ts even when there is nothing to initialize. XP brings an app’s JavaScript engine and context to life lazily, so an app without one makes its very first request pay for engine start-up, context creation and parsing every module that request touches. A main.ts moves that toll to application start. Requiring the libraries your entry points use is a cheap way to extend the warm-up — on the GraalJS engine compiled code is cached across contexts, so modules parsed during start-up stay warm for the contexts that later serve requests. This does not contradict keeping main.ts short: it is work the first request would otherwise do, paid where nobody is waiting on a response. |
Running code when the application starts:
main.ts
// Log application start
log.info(`Application ${app.name} started`);
Running code when the application stops:
main.ts
// Log application stop
__.disposer(() => {
log.info(`Application ${app.name} stopped`);
});
main.ts is the only dependable place to register a disposer — see __.disposer for why, and for the one-disposer-per-module rule.