-
Notifications
You must be signed in to change notification settings - Fork 136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
⚡️ [RUM-6813] Lazy load session replay #3152
base: v6
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## v6 #3152 +/- ##
==========================================
- Coverage 93.49% 93.46% -0.04%
==========================================
Files 275 275
Lines 7393 7419 +26
Branches 1675 1680 +5
==========================================
+ Hits 6912 6934 +22
- Misses 481 485 +4 ☔ View full report in Codecov by Sentry. 🚨 Try these New Features:
|
test/app/webpack.config.js
Outdated
@@ -2,7 +2,7 @@ const path = require('path') | |||
|
|||
module.exports = (_env, argv) => ({ | |||
entry: './app.ts', | |||
target: ['web', 'es5'], | |||
target: ['node', 'es2018'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test app used to test if the SDK works for SSR was targeting the web. I fixed it to target node and es2018.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test app used to test if the SDK works for SSR was targeting the web.
Is it what is tested? As I understand it is used to test the npm setup and it's injected in a html:
header += html` <script type="text/javascript" src="./app.js"></script> ` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I forgot that the test app is also used for npm e2e 😭
@@ -14,3 +14,17 @@ export function runOnReadyState( | |||
const eventName = expectedReadyState === 'complete' ? DOM_EVENT.LOAD : DOM_EVENT.DOM_CONTENT_LOADED | |||
return addEventListener(configuration, window, eventName, callback, { once: true }) | |||
} | |||
|
|||
export function asyncRunOnReadyState( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now, I introduced an async version of runOnReadyState
but if we agree on this lazy loading approach I'll refactor the original runOnReadyState
to use promises.
Bundles Sizes Evolution
🚀 CPU Performance
🧠 Memory Performance
|
@@ -0,0 +1,3 @@ | |||
export function lazyLoadRecorder() { | |||
return import(/* webpackChunkName: "recorder" */ './startRecording').then((module) => module.startRecording) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❓ question: I have a doubt, does this means that customer need to use webpack as well? or is this a stupid question?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not exactly, I used the webpackChunkName
special comment to have a fixed chunk name to deploy our CDN files. For customers using NPM:
- if they use webpack: the chunk will have a fix name
- If they use another bundler this comment is ignored
})) | ||
startRecordingSpy = jasmine.createSpy('startRecording') | ||
|
||
// Workaround because using resolveTo(startRecordingSpy) is not was not working |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Workaround because using resolveTo(startRecordingSpy) is not was not working | |
// Workaround because using resolveTo(startRecordingSpy) was not working |
const doStart = async () => { | ||
const [startRecordingImpl] = await Promise.all([ | ||
loadRecorder(), | ||
asyncRunOnReadyState(configuration, 'interactive'), | ||
]) | ||
|
||
if (state.status !== RecorderStatus.Starting) { | ||
return | ||
} | ||
|
||
const deflateEncoder = getOrCreateDeflateEncoder() | ||
if (!deflateEncoder) { | ||
state = { | ||
status: RecorderStatus.Stopped, | ||
} | ||
return | ||
} | ||
|
||
const { stop: stopRecording } = startRecordingImpl( | ||
lifeCycle, | ||
configuration, | ||
sessionManager, | ||
viewHistory, | ||
deflateEncoder | ||
) | ||
|
||
state = { | ||
status: RecorderStatus.Started, | ||
stopRecording, | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💬 suggestion: As we're using promise, I'll avoid having state all over the place. maybe something like this would be a bit more clean:
const doStart = async () => {
const [startRecordingImpl] = await Promise.all([
loadRecorder(),
asyncRunOnReadyState(configuration, 'interactive'),
])
if (state.status !== RecorderStatus.Starting) {
return
}
const deflateEncoder = getOrCreateDeflateEncoder()
if (!deflateEncoder) {
throw new Error('deflate encoder not initialized!');
}
const { stop: stopRecording } = startRecordingImpl(
lifeCycle,
configuration,
sessionManager,
viewHistory,
deflateEncoder
)
return stopRecording
}
And manage the state when you use it:
doStart()
.then(stop => {
state = {
status: RecorderStatus.Started,
stopRecording: stop
}
})
.catch(() => {
state = {
status: RecorderStatus.Stopped,
}
})
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting! I'll look at it
04a8db5
to
2205ee9
Compare
Motivation
Use dynamic imports to lazy load Session Replay, reducing the bundle size by 3KB (compressed) for users without Session Replay. Transitioning from Webpack, which adds overhead via
__webpack_require__
, to a new bundler could save additional bytes.Changes
startRecording
using dynamic importTesting
I have gone over the contributing documentation.