All quizzesHard
Scheduler & Internals — Series 3
Preview — 3 of 10 questions
Why might applying will-change: transform to every animated element on a page make things worse, not better?
javascript
/* Applied indiscriminately to 200 list items, all animated on hover */
.list-item {
will-change: transform;
}Awill-change is purely a documentation hint for other developers reading the CSS — it has no actual effect on browser rendering behavior at all
Bwill-change is only valid on elements that also have position: fixed or position: absolute; applied elsewhere, it's silently ignored
Cwill-change is a signal telling the browser to promote an element onto its own GPU compositing layer ahead of time, which can make an individual animation smoother by letting the browser handle it independently of the rest of the page's paint work — but each promoted layer consumes real GPU memory, and promoting 200 elements simultaneously (rather than the handful actually being interacted with at any moment) can exhaust available GPU memory or force the browser to manage far more layers than it can efficiently composite, actually degrading performance compared to promoting only what's genuinely, currently animating
Dwill-change only affects animations defined with the Web Animations API — CSS transition/animation-based effects ignore it entirely
How does this API give more actionable information than a generic long task entry from the standard Long Tasks API?
javascript
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(entry.duration, entry.scripts) // scripts: attribution info
}
}).observe({ type: 'long-animation-frame', buffered: true })AThe Long Tasks API reports that some task blocked the main thread for over 50ms, but offers limited attribution about why — LoAF entries specifically break down a slow rendering frame into its constituent phases (style/layout work, specific script execution) and, critically, include per-script attribution (entry.scripts, identifying which specific script/function was responsible and for how long) — turning "something on this frame was slow" into "this specific script, invoked from this specific source, is responsible for this much of the frame's total duration," which is far more directly actionable for diagnosing real jank in production
BLoAF entries are functionally identical to Long Task entries — this is purely a renamed API with no additional information
CLoAF only works in a local development environment — it cannot be used to collect real user monitoring (RUM) data in production
DLoAF entries only capture CSS animation performance; JavaScript-driven visual updates aren't included
For a plugin snapshotting a store's entire state on every action (for undo/redo, as covered elsewhere), why might the choice between structuredClone and a manual shallow copy matter at scale?
javascript
// Deep clone via structuredClone — correct, but potentially expensive
const snapshot = structuredClone(toRaw(store.$state))
// Shallow copy — cheaper, but only safe if nested objects are never mutated in place
const shallowSnapshot = { ...toRaw(store.$state) }AstructuredClone and a shallow spread copy are functionally identical in every case — there's no scenario where the distinction matters
BstructuredClone performs a genuine deep clone — walking and copying every nested object/array in the state tree, which for a large or deeply-nested store, done on every single action (potentially many times per second for a busy undo/redo-tracked flow), is real, repeated CPU and memory work. A shallow copy is dramatically cheaper (only copying the top-level references), but it's only actually safe to use for undo/redo purposes if nested objects/arrays are never mutated in place afterward — since a shallow copy's nested values are still the same object references as the live state, a later in-place mutation of a nested array would retroactively "corrupt" what was supposed to be a frozen historical snapshot too. The correct choice depends on whether the app's own mutation patterns actually guarantee that nested data is always replaced (not mutated in place), which a shallow copy can safely capture, versus genuinely needing the safety of a full deep clone
CstructuredClone is strictly forbidden from being used on any object that came from a toRaw() call — this combination throws a runtime error
DA shallow copy is always the correct, sufficient choice for undo/redo, regardless of how the app mutates its own nested state
Sign up free to play
Answer all 10 questions (7 more), see explanations for every answer, and track your score.