1

I want to set some performance marks and measures in my Angular components to measure how long selected components take to process and render. They work fine when running the app in "client mode", but as soon as I run the app in SSR mode, I get "performance" is undefined.

ReferenceError: performance is not defined

I tried importing it from nodes 'perf_hooks' internal module, but then I get unknown module 'perf_hooks' when called from app.component.ts.
https://github.com/buggy1985/angular-ssr-performance/blob/HEAD/src/app/app.component.ts#L17

Cannot find module 'perf_hooks' or its corresponding type declaration

If I use performance.now() in server.ts it seems to be working. https://github.com/buggy1985/angular-ssr-performance/blob/HEAD/server.ts#L13

Can I pass the performance class from server.ts to the component? And for browser to fall back to window.performance? Or what am I doing wrong?

buggy1985
  • 919
  • 8
  • 24
  • 1
    You can wrap the call in a conditional that only runs when on the browser – Phix Jun 25 '21 at 20:39
  • I want to use them in server mode too. I should be able to use the node internal module on server and window.performance in the browser – buggy1985 Jun 26 '21 at 10:11
  • As it seems, you should create your own implementation for the server side. I haven't done anything similar yet, but I believe that it is possible. – StPaulis Jun 28 '21 at 10:49

1 Answers1

3

I finally managed to solve it by providing the correct performance api depending on the platform.

Here is the full commit with my changes: https://github.com/buggy1985/angular-ssr-performance/commit/39aa08489e589172fa9bce6f1f5588f5eb962337

I basically created a new provider, that injects the imported performance from perf_hooks in server.ts

import { performance } from 'perf_hooks';
export const PERFORMANCE_API = new InjectionToken('performance-api');
...

@NgModule({
  providers: [
    { provide: PERFORMANCE_API, useValue: performance },
  ],
}

and injects windows.performance in app.browser.module

providers: [
  { provide: PERFORMANCE_API, useValue: window.performance },
],

In app.component.ts, instead of using performance directly, you have to inject it in the constructor and then use it as this.performance.

constructor(@Inject(PERFORMANCE_API) private performance) {
    console.log(this.performance.now());
}
buggy1985
  • 919
  • 8
  • 24