diff --git a/packages/rum/src/boot/postStartStrategy.ts b/packages/rum/src/boot/postStartStrategy.ts index f55afb881a..b15894d64c 100644 --- a/packages/rum/src/boot/postStartStrategy.ts +++ b/packages/rum/src/boot/postStartStrategy.ts @@ -12,6 +12,7 @@ import { asyncRunOnReadyState, monitorError, Observable } from '@datadog/browser import { getSessionReplayLink } from '../domain/getSessionReplayLink' import { startRecorderInitTelemetry } from '../domain/startRecorderInitTelemetry' import type { startRecording } from './startRecording' +import { lazyLoadRecorder } from './lazyLoadRecorder' export type StartRecording = typeof startRecording @@ -48,7 +49,6 @@ export function createPostStartStrategy( lifeCycle: LifeCycle, sessionManager: RumSessionManager, viewHistory: ViewHistory, - loadRecorder: () => Promise, getOrCreateDeflateEncoder: () => DeflateEncoder | undefined, telemetry: Telemetry ): Strategy { @@ -75,7 +75,7 @@ export function createPostStartStrategy( observable.notify({ type: 'start', forced }) const [startRecordingImpl] = await Promise.all([ - notifyWhenSettled(observable, { type: 'recorder-settled' }, loadRecorder()), + notifyWhenSettled(observable, { type: 'recorder-settled' }, lazyLoadRecorder()), notifyWhenSettled(observable, { type: 'document-ready' }, asyncRunOnReadyState(configuration, 'interactive')), ]) diff --git a/packages/rum/src/boot/recorderApi.spec.ts b/packages/rum/src/boot/recorderApi.spec.ts index 144bfde357..2d6dec14e1 100644 --- a/packages/rum/src/boot/recorderApi.spec.ts +++ b/packages/rum/src/boot/recorderApi.spec.ts @@ -30,12 +30,13 @@ import * as replayStats from '../domain/replayStats' import { type RecorderInitMetrics } from '../domain/startRecorderInitTelemetry' import { makeRecorderApi } from './recorderApi' import type { StartRecording } from './postStartStrategy' +import { importRecorder } from './lazyLoadRecorder' describe('makeRecorderApi', () => { let lifeCycle: LifeCycle let recorderApi: RecorderApi let startRecordingSpy: jasmine.Spy - let loadRecorderSpy: jasmine.Spy<() => Promise> + let importRecorderSpy: jasmine.Spy<() => Promise> let stopRecordingSpy: jasmine.Spy<() => void> let mockWorker: MockWorker let createDeflateWorkerSpy: jasmine.Spy @@ -59,13 +60,13 @@ describe('makeRecorderApi', () => { lifeCycle = new LifeCycle() stopRecordingSpy = jasmine.createSpy('stopRecording') startRecordingSpy = jasmine.createSpy('startRecording') - loadRecorderSpy = jasmine.createSpy('loadRecorder') + importRecorderSpy = replaceMockableWithSpy(importRecorder) if (loadRecorderError) { - loadRecorderSpy.and.resolveTo(undefined) + importRecorderSpy.and.resolveTo(undefined) } else { // Workaround because using resolveTo(startRecordingSpy) was not working - loadRecorderSpy.and.resolveTo((...args: any) => { + importRecorderSpy.and.resolveTo((...args: any) => { startRecordingSpy(...args) return { stop: stopRecordingSpy, @@ -77,7 +78,7 @@ describe('makeRecorderApi', () => { startSessionReplayRecordingManually: startSessionReplayRecordingManually ?? false, }) - recorderApi = makeRecorderApi(loadRecorderSpy) + recorderApi = makeRecorderApi() rumInit = ({ worker } = {}) => { recorderApi.onRumStart( lifeCycle, @@ -98,7 +99,7 @@ describe('makeRecorderApi', () => { describe('with automatic start', () => { it('starts recording when init() is called', async () => { setupRecorderApi() - expect(loadRecorderSpy).not.toHaveBeenCalled() + expect(importRecorderSpy).not.toHaveBeenCalled() expect(startRecordingSpy).not.toHaveBeenCalled() expect(await telemetry.hasEvents()).toEqual(false) rumInit() @@ -112,7 +113,7 @@ describe('makeRecorderApi', () => { const { triggerOnDomLoaded } = mockDocumentReadyState() rumInit() - expect(loadRecorderSpy).toHaveBeenCalled() + expect(importRecorderSpy).toHaveBeenCalled() expect(startRecordingSpy).not.toHaveBeenCalled() expect(await telemetry.hasEvents()).toEqual(false) @@ -127,11 +128,11 @@ describe('makeRecorderApi', () => { describe('with manual start', () => { it('does not start recording when init() is called', async () => { setupRecorderApi({ startSessionReplayRecordingManually: true }) - expect(loadRecorderSpy).not.toHaveBeenCalled() + expect(importRecorderSpy).not.toHaveBeenCalled() expect(startRecordingSpy).not.toHaveBeenCalled() expect(await telemetry.hasEvents()).toEqual(false) rumInit() - expect(loadRecorderSpy).not.toHaveBeenCalled() + expect(importRecorderSpy).not.toHaveBeenCalled() expect(startRecordingSpy).not.toHaveBeenCalled() expect(await telemetry.hasEvents()).toEqual(false) }) @@ -140,11 +141,11 @@ describe('makeRecorderApi', () => { setupRecorderApi({ startSessionReplayRecordingManually: true }) const { triggerOnDomLoaded } = mockDocumentReadyState() rumInit() - expect(loadRecorderSpy).not.toHaveBeenCalled() + expect(importRecorderSpy).not.toHaveBeenCalled() expect(startRecordingSpy).not.toHaveBeenCalled() expect(await telemetry.hasEvents()).toEqual(false) triggerOnDomLoaded() - expect(loadRecorderSpy).not.toHaveBeenCalled() + expect(importRecorderSpy).not.toHaveBeenCalled() expect(startRecordingSpy).not.toHaveBeenCalled() expect(await telemetry.hasEvents()).toEqual(false) }) @@ -183,7 +184,7 @@ describe('makeRecorderApi', () => { rumInit() recorderApi.start() - expect(loadRecorderSpy).not.toHaveBeenCalled() + expect(importRecorderSpy).not.toHaveBeenCalled() expect(startRecordingSpy).not.toHaveBeenCalled() }) @@ -194,7 +195,7 @@ describe('makeRecorderApi', () => { }) rumInit() recorderApi.start() - expect(loadRecorderSpy).not.toHaveBeenCalled() + expect(importRecorderSpy).not.toHaveBeenCalled() expect(startRecordingSpy).not.toHaveBeenCalled() }) @@ -232,7 +233,7 @@ describe('makeRecorderApi', () => { setupRecorderApi({ loadRecorderError: true }) rumInit() - expect(loadRecorderSpy).toHaveBeenCalled() + expect(importRecorderSpy).toHaveBeenCalled() await new Promise((resolve) => setTimeout(resolve, 1000)) @@ -247,7 +248,7 @@ describe('makeRecorderApi', () => { createDeflateWorkerSpy.and.throwError('Crash') recorderApi.start() - expect(loadRecorderSpy).toHaveBeenCalled() + expect(importRecorderSpy).toHaveBeenCalled() await collectAsyncCalls(createDeflateWorkerSpy, 1) expect(startRecordingSpy).not.toHaveBeenCalled() @@ -264,7 +265,7 @@ describe('makeRecorderApi', () => { setupRecorderApi({ startSessionReplayRecordingManually: true }) rumInit() recorderApi.start() - expect(loadRecorderSpy).toHaveBeenCalled() + expect(importRecorderSpy).toHaveBeenCalled() await collectAsyncCalls(startRecordingSpy, 1) mockWorker.dispatchErrorEvent() @@ -315,7 +316,7 @@ describe('makeRecorderApi', () => { rumInit() recorderApi.start() - expect(loadRecorderSpy).not.toHaveBeenCalled() + expect(importRecorderSpy).not.toHaveBeenCalled() expect(startRecordingSpy).not.toHaveBeenCalled() }) }) @@ -336,7 +337,7 @@ describe('makeRecorderApi', () => { setupRecorderApi({ startSessionReplayRecordingManually: true }) recorderApi.start() rumInit() - expect(loadRecorderSpy).not.toHaveBeenCalled() + expect(importRecorderSpy).not.toHaveBeenCalled() expect(startRecordingSpy).not.toHaveBeenCalled() }) }) @@ -361,7 +362,7 @@ describe('makeRecorderApi', () => { recorderApi.stop() triggerOnDomLoaded() - await collectAsyncCalls(loadRecorderSpy, 1) + await collectAsyncCalls(importRecorderSpy, 1) expect(startRecordingSpy).not.toHaveBeenCalled() }) @@ -399,7 +400,7 @@ describe('makeRecorderApi', () => { lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED) lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED) - expect(loadRecorderSpy).not.toHaveBeenCalled() + expect(importRecorderSpy).not.toHaveBeenCalled() expect(startRecordingSpy).not.toHaveBeenCalled() }) }) @@ -415,7 +416,7 @@ describe('makeRecorderApi', () => { lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED) lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED) - expect(loadRecorderSpy).not.toHaveBeenCalled() + expect(importRecorderSpy).not.toHaveBeenCalled() expect(startRecordingSpy).not.toHaveBeenCalled() expect(stopRecordingSpy).not.toHaveBeenCalled() }) @@ -431,7 +432,7 @@ describe('makeRecorderApi', () => { lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED) lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED) - expect(loadRecorderSpy).not.toHaveBeenCalled() + expect(importRecorderSpy).not.toHaveBeenCalled() expect(startRecordingSpy).not.toHaveBeenCalled() expect(stopRecordingSpy).not.toHaveBeenCalled() }) @@ -451,7 +452,7 @@ describe('makeRecorderApi', () => { lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED) expect(stopRecordingSpy).toHaveBeenCalled() lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED) - expect(loadRecorderSpy).toHaveBeenCalledTimes(1) + expect(importRecorderSpy).toHaveBeenCalledTimes(1) expect(startRecordingSpy).toHaveBeenCalledTimes(1) }) @@ -463,7 +464,7 @@ describe('makeRecorderApi', () => { lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED) lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED) triggerOnDomLoaded() - expect(loadRecorderSpy).toHaveBeenCalled() + expect(importRecorderSpy).toHaveBeenCalled() expect(startRecordingSpy).not.toHaveBeenCalled() }) }) @@ -481,7 +482,7 @@ describe('makeRecorderApi', () => { lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED) expect(stopRecordingSpy).toHaveBeenCalled() lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED) - expect(loadRecorderSpy).toHaveBeenCalledTimes(1) + expect(importRecorderSpy).toHaveBeenCalledTimes(1) expect(startRecordingSpy).toHaveBeenCalledTimes(1) }) }) @@ -500,7 +501,7 @@ describe('makeRecorderApi', () => { lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED) await collectAsyncCalls(startRecordingSpy, 2) - expect(loadRecorderSpy).toHaveBeenCalledTimes(2) + expect(importRecorderSpy).toHaveBeenCalledTimes(2) expect(startRecordingSpy).toHaveBeenCalledTimes(2) }) @@ -512,7 +513,7 @@ describe('makeRecorderApi', () => { expect(stopRecordingSpy).toHaveBeenCalledTimes(1) lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED) lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED) - expect(loadRecorderSpy).toHaveBeenCalledTimes(1) + expect(importRecorderSpy).toHaveBeenCalledTimes(1) expect(startRecordingSpy).toHaveBeenCalledTimes(1) expect(stopRecordingSpy).toHaveBeenCalledTimes(1) }) @@ -541,7 +542,7 @@ describe('makeRecorderApi', () => { sessionManager.setTrackedWithSessionReplay() lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED) lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED) - expect(loadRecorderSpy).not.toHaveBeenCalled() + expect(importRecorderSpy).not.toHaveBeenCalled() expect(startRecordingSpy).not.toHaveBeenCalled() expect(stopRecordingSpy).not.toHaveBeenCalled() }) @@ -557,7 +558,7 @@ describe('makeRecorderApi', () => { sessionManager.setTrackedWithoutSessionReplay() lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED) lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED) - expect(loadRecorderSpy).not.toHaveBeenCalled() + expect(importRecorderSpy).not.toHaveBeenCalled() expect(startRecordingSpy).not.toHaveBeenCalled() expect(stopRecordingSpy).not.toHaveBeenCalled() }) @@ -572,7 +573,7 @@ describe('makeRecorderApi', () => { rumInit() lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED) lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED) - expect(loadRecorderSpy).not.toHaveBeenCalled() + expect(importRecorderSpy).not.toHaveBeenCalled() expect(startRecordingSpy).not.toHaveBeenCalled() expect(stopRecordingSpy).not.toHaveBeenCalled() }) diff --git a/packages/rum/src/boot/recorderApi.ts b/packages/rum/src/boot/recorderApi.ts index d00abf23a0..54de5719bc 100644 --- a/packages/rum/src/boot/recorderApi.ts +++ b/packages/rum/src/boot/recorderApi.ts @@ -22,11 +22,10 @@ import { startDeflateWorker, } from '../domain/deflate' import { isBrowserSupported } from './isBrowserSupported' -import type { StartRecording } from './postStartStrategy' import { createPostStartStrategy } from './postStartStrategy' import { createPreStartStrategy } from './preStartStrategy' -export function makeRecorderApi(loadRecorder: () => Promise): RecorderApi { +export function makeRecorderApi(): RecorderApi { if ((canUseEventBridge() && !bridgeSupports(BridgeCapability.RECORDS)) || !isBrowserSupported()) { return { start: noop, @@ -101,7 +100,6 @@ export function makeRecorderApi(loadRecorder: () => Promise