Skip to content

fix(react): project slider state per render - #2595

Draft
mihar-22 wants to merge 1 commit into
fix/react-committed-callback-refsfrom
fix/react-slider-render-local
Draft

fix(react): project slider state per render#2595
mihar-22 wants to merge 1 commit into
fix/react-committed-callback-refsfrom
fix/react-slider-render-local

Conversation

@mihar-22

@mihar-22 mihar-22 commented Sep 2, 2026

Copy link
Copy Markdown
Member

Refs #1679

Depends on #2594.

Summary

#2589 left SliderCore, TimeSliderCore and VolumeSliderCore retained because useSlider's callbacks mutate them and TimeSliderCore carries drag intent. This finishes that conversion without touching the public useSlider, Slider.Root callback, or computeState contracts: the render-derived projection (props, media, locale, ARIA, value mapping, CSS vars) is now a render-local core built per render, while the interaction machinery stays retained and reads only committed values.

Changes

  • Slider.Root, TimeSlider.Root, VolumeSlider.Root: build the core per render (new *Core(props)) instead of useState(() => new *Core()) plus setProps/setFormatLocale in render. computeState still calls setInput/setMedia on that core, but the core now belongs to the render that created it, so no other render can observe the mutation. The syncStyles subscription re-projects through the committed render's computeState for CSS var updates that bypass React, exactly as before.
  • useSlider: optionsRef is a useCommittedRef, so the retained createSlider binder only ever reaches committed callbacks and cores; adjustPercent is read through the ref at call time instead of being captured from the first render (the captured version would have pinned the first render's core). The mount-time useForceRender layout effect is gone: edge alignment is applied by syncStyles() from a layout effect on mount and whenever thumbAlignment changes, which also covers a render that adjusted percents through the previously committed options.
  • TimeSlider.Root: the render-local core projects props and media; a separate retained dragCore owns the pause-on-drag intent, with pauseOnDrag committed from a layout effect and startDrag/endDrag (including the unmount resume) driven from committed refs. mediaRef is replaced by the committed options closure.
  • VolumeSlider.Root: the retained createWheelStep handler reads the committed core, volume and disabled state through useCommittedRef (previously getStepPercent captured the first render's core).
  • Geometry math stays in core: React still calls core.adjustPercentForAlignment and slider.adjustForAlignment.

What remains retained and why

  • createSlider (SliderApi): pointer capture, drag threshold, throttling, keyboard stepping and the input state store are interaction state that must outlive renders; its callbacks read committed options through useCommittedRef.
  • dragCore (TimeSliderCore) in TimeSlider.Root: only holds whether a drag paused playback so endDrag can resume it (also on unmount). Its single input, pauseOnDrag, is committed in a layout effect rather than written during render.
  • createWheelStep in VolumeSlider.Root: a listener attached through a callback ref; reads committed refs only.
  • The press-based controls lock from fix(packages): restore ejected player registration and slider press locking #2505 (onPressStart/onPressEnd in useSlider) is unchanged.
  • Thumb ARIA during drag is unchanged: the root still reads slider.input.current on each render, so aria-valuenow/aria-valuetext follow the pointer whenever the root re-renders during a drag (covered by a new test). Splitting motion from semantic state (refactor(react)!: separate slider render and motion state #2327) remains out of scope.

Notes

  • Pre-existing bug found while testing, not fixed here: VolumeSliderCore.getWheelStepPercent() returns NaN because SliderCore.setProps uses defaults(props, SliderCore.defaultProps), which drops wheelStep. Both the React and HTML volume sliders call setVolume(NaN) on wheel. Worth a separate core fix with a core test.

Testing

  • slider.test.tsx: an abandoned re-render inside MockErrorBoundary does not change what the retained slider projects (getPercent, isDisabled) or which onValueChange it calls; StrictMode replay projects the latest committed props into ARIA, CSS vars and callbacks; dragging updates data-dragging and thumb ARIA and value callbacks map through the latest committed range; the controls lock is held across re-renders during a press; switching thumbAlignment to edge applies adjusted CSS vars in the same commit.
  • time-slider.test.tsx: thumb announces the pointer position while dragging; onValueCommit seeks through the committed media; abandoned re-render keeps the committed projection; existing pauseOnDrag tests cover dragCore, including unmount resume.
  • volume-slider.test.tsx: committed step/disabled projection, abandoned re-render, and wheel disabled handling under StrictMode.
  • The three abandoned-render tests were verified to fail against the previous retained-core sources.
  • pnpm -F @videojs/react test: 76 files, 596 tests passed
  • pnpm build --filter=@videojs/react
  • pnpm typecheck
  • pnpm lint:fix:file on touched files and git diff --check

🤖 Generated with Claude Code

Slider.Root, TimeSlider.Root and VolumeSlider.Root kept a component-
lifetime core in useState and wrote each render's props, media and
input into it during render, so a speculative or abandoned render could
leave the committed slider callbacks reading another render's values.
Build the projection core per render instead, route useSlider's retained
binder callbacks through useCommittedRef so only committed renders reach
them, and keep the genuinely retained pieces (pointer and drag state in
createSlider, the pause-on-drag intent, the wheel handler and the press
based controls lock) commit-synchronized. Edge alignment now re-applies
committed CSS vars from a layout effect instead of forcing a re-render.

Refs #1679

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
v10-sandbox Ready Ready Preview Sep 2, 2026 11:06pm UTC

Request Review

@pkg-pr-new

pkg-pr-new Bot commented Sep 2, 2026

Copy link
Copy Markdown
@videojs/core

pnpm add https://pkg.pr.new/@videojs/core@2595

@videojs/element

pnpm add https://pkg.pr.new/@videojs/element@2595

@videojs/html

pnpm add https://pkg.pr.new/@videojs/html@2595

@videojs/media

pnpm add https://pkg.pr.new/@videojs/media@2595

@videojs/react

pnpm add https://pkg.pr.new/@videojs/react@2595

@videojs/spf

pnpm add https://pkg.pr.new/@videojs/spf@2595

@videojs/store

pnpm add https://pkg.pr.new/@videojs/store@2595

@videojs/utils

pnpm add https://pkg.pr.new/@videojs/utils@2595

commit: a362cb8

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

📦 Bundle Size Report

🎨 @videojs/html — no changes
Presets (7)
Entry Initial Lazy
/video (default) 62.05 kB 56.87 kB
/video (default + hls) 200.93 kB 56.87 kB
/video (minimal) 61.78 kB 56.87 kB
/video (minimal + hls) 200.76 kB 56.87 kB
/audio (default) 51.81 kB 56.87 kB
/audio (minimal) 47.89 kB 56.87 kB
/background 11.52 kB 56.87 kB
Media (18)
Entry Initial
/media/mux-video 142.40 kB
/media/mux-audio 142.23 kB
/media/background-video 1.16 kB
/media/cloudflare-video 6.28 kB
/media/dash-video 211.61 kB
/media/hls-audio 22.09 kB
/media/hls-background-video 16.80 kB
/media/hls-video 28.04 kB
/media/hlsjs-video 141.22 kB
/media/mux-background-video 16.83 kB
/media/native-hls-video 7.57 kB
/media/shaka-video 199.18 kB
/media/spotify-audio 6.27 kB
/media/tiktok-video 6.33 kB
/media/twitch-video 6.22 kB
/media/vimeo-video 13.05 kB
/media/wistia-video 60.23 kB
/media/youtube-video 6.81 kB
Extensions (2)
Entry Initial
/extensions/google-cast 6.52 kB
/extensions/mux-data 26.94 kB
Players (5)
Entry Initial Lazy
/video/player 9.70 kB 56.87 kB
/audio/player 6.14 kB 56.87 kB
/background/player 4.46 kB 56.87 kB
/live-video/player 9.06 kB 56.87 kB
/live-audio/player 6.15 kB 56.87 kB
Skins (29)
Entry Type Initial Lazy
/video/minimal-skin.css css 6.63 kB
/video/skin.css css 6.45 kB
/video/minimal-skin js 60.28 kB 56.87 kB
/video/minimal-skin2 js 7.19 kB
/video/skin js 60.54 kB 56.87 kB
/video/skin2 js 7.04 kB
/audio/minimal-skin.css css 4.95 kB
/audio/skin.css css 4.88 kB
/audio/minimal-skin js 46.43 kB 56.87 kB
/audio/minimal-skin2 js 5.36 kB
/audio/skin js 50.32 kB 56.87 kB
/audio/skin2 js 5.32 kB
/background/skin.css css 145 B
/background/skin js 9.77 kB 56.87 kB
/background/skin2 js 190 B
/live-video/minimal-skin.css css 6.63 kB
/live-video/skin.css css 6.45 kB
/live-video/minimal-skin js 54.40 kB 56.87 kB
/live-video/minimal-skin2 js 7.19 kB
/live-video/skin js 56.99 kB 56.87 kB
/live-video/skin2 js 7.04 kB
/live-audio/minimal-skin.css css 4.95 kB
/live-audio/skin.css css 4.88 kB
/live-audio/minimal-skin js 39.72 kB 56.87 kB
/live-audio/minimal-skin2 js 5.36 kB
/live-audio/skin js 43.33 kB 56.87 kB
/live-audio/skin2 js 5.32 kB
/global.css css 190 B
/shared.css css 118 B
UI Components (50)
Entry Initial Lazy
/ui/airplay-button 11.26 kB 56.87 kB
/ui/alert-dialog 9.44 kB 56.87 kB
/ui/audio-track-radio-group 11.34 kB 56.87 kB
/ui/buffering-indicator 8.61 kB 56.87 kB
/ui/captions-button 11.51 kB 56.87 kB
/ui/captions-radio-group 11.43 kB 56.87 kB
/ui/cast-button 11.25 kB 56.87 kB
/ui/container 9.47 kB 56.87 kB
/ui/controls 8.81 kB 56.87 kB
/ui/controls-backdrop 1.69 kB 56.87 kB
/ui/controls-content 1.67 kB 56.87 kB
/ui/dialog 9.35 kB 56.87 kB
/ui/dialog-backdrop 1.70 kB 56.87 kB
/ui/dialog-close 2.06 kB 56.87 kB
/ui/dialog-description 1.69 kB 56.87 kB
/ui/dialog-popup 1.90 kB 56.87 kB
/ui/dialog-title 1.70 kB 56.87 kB
/ui/error-dialog 13.01 kB 56.87 kB
/ui/fullscreen-button 11.27 kB 56.87 kB
/ui/gesture 9.56 kB 56.87 kB
/ui/hotkey 9.97 kB 56.87 kB
/ui/live-button 9.74 kB 56.87 kB
/ui/menu 20.06 kB 56.87 kB
/ui/mute-button 11.28 kB 56.87 kB
/ui/pip-button 11.22 kB 56.87 kB
/ui/play-button 11.23 kB 56.87 kB
/ui/playback-rate-button 11.32 kB 56.87 kB
/ui/playback-rate-radio-group 11.34 kB 56.87 kB
/ui/popover 8.56 kB 56.87 kB
/ui/poster 8.67 kB 56.87 kB
/ui/quality-radio-group 11.94 kB 56.87 kB
/ui/seek-button 11.27 kB 56.87 kB
/ui/seek-indicator 12.69 kB 56.87 kB
/ui/seek-indicator-value 1.10 kB
/ui/slider 12.12 kB 56.87 kB
/ui/status-announcer 10.59 kB 56.87 kB
/ui/status-indicator 13.03 kB 56.87 kB
/ui/status-indicator-value 1.10 kB
/ui/thumbnail 9.84 kB 56.87 kB
/ui/time 10.87 kB 56.87 kB
/ui/time-slider 15.04 kB 56.87 kB
/ui/time-slider-chapter-title 8.79 kB 56.87 kB
/ui/time-slider-chapters 9.76 kB 56.87 kB
/ui/title 8.17 kB 56.87 kB
/ui/tooltip 9.95 kB 56.87 kB
/ui/volume-indicator 13.03 kB 56.87 kB
/ui/volume-indicator-fill 1.11 kB
/ui/volume-indicator-value 1.10 kB
/ui/volume-popover 14.72 kB 56.87 kB
/ui/volume-slider 12.79 kB 56.87 kB
⚛️ @videojs/react — 25 small size changes
Path Base initial PR initial Initial diff Lazy diff
/video/minimal-skin 48.46 kB 48.42 kB -47 B (-0.1%) 0 B
/video/minimal-skin.tailwind 55.34 kB 55.32 kB -26 B (-0.0%) 0 B
/video/skin 48.36 kB 48.32 kB -46 B (-0.1%) 0 B
/video/skin.tailwind 55.24 kB 55.15 kB -87 B (-0.2%) 0 B
/audio/minimal-skin 37.69 kB 37.59 kB -97 B (-0.3%) 0 B
/audio/minimal-skin.tailwind 42.83 kB 42.79 kB -37 B (-0.1%) 0 B
/audio/skin 37.62 kB 37.53 kB -91 B (-0.2%) 0 B
/audio/skin.tailwind 42.72 kB 42.67 kB -54 B (-0.1%) 0 B
/live-video/minimal-skin 40.53 kB 40.50 kB -26 B (-0.1%) 0 B
/live-video/minimal-skin.tailwind 47.25 kB 47.18 kB -66 B (-0.1%) 0 B
/live-video/skin 40.59 kB 40.54 kB -56 B (-0.1%) 0 B
/live-video/skin.tailwind 47.16 kB 47.15 kB -8 B (-0.0%) 0 B
/live-audio/minimal-skin 29.48 kB 29.43 kB -45 B (-0.1%) 0 B
/live-audio/minimal-skin.tailwind 33.46 kB 33.39 kB -74 B (-0.2%) 0 B
/live-audio/skin 29.55 kB 29.43 kB -120 B (-0.4%) 0 B
/live-audio/skin.tailwind 33.55 kB 33.53 kB -12 B (-0.0%) 0 B
/ui/slider 12.76 kB 12.67 kB -94 B (-0.7%) 0 B
/ui/time-slider 14.19 kB 14.17 kB -29 B (-0.2%) 0 B
/ui/volume-slider 12.16 kB 12.11 kB -51 B (-0.4%) 0 B
/video (default) 48.45 kB 48.48 kB +28 B (+0.1%) 0 B
/video (default + hls) 186.49 kB 186.20 kB -299 B (-0.2%) 0 B
/video (minimal) 48.53 kB 48.46 kB -68 B (-0.1%) 0 B
/video (minimal + hls) 186.47 kB 186.46 kB -19 B (-0.0%) 0 B
/audio (default) 37.71 kB 37.63 kB -84 B (-0.2%) 0 B
/audio (minimal) 37.74 kB 37.73 kB -12 B (-0.0%) 0 B
Presets (7)
Entry Initial Lazy
/video (default) 48.48 kB 56.87 kB
/video (default + hls) 186.20 kB 56.87 kB
/video (minimal) 48.46 kB 56.87 kB
/video (minimal + hls) 186.46 kB 56.87 kB
/audio (default) 37.63 kB 56.87 kB
/audio (minimal) 37.73 kB 56.87 kB
/background 581 B 56.87 kB
Media (22)
Entry Initial
/media/mux-video/hls-js 140.79 kB
/media/mux-video/spf 27.39 kB
/media/mux-audio/hls-js 140.56 kB
/media/mux-audio/spf 21.35 kB
/media/background-video 402 B
/media/cloudflare-video 4.42 kB
/media/dash-video 210.23 kB
/media/hls-audio 20.39 kB
/media/hls-background-video 16.49 kB
/media/hls-video 26.38 kB
/media/hlsjs-video 139.63 kB
/media/mux-audio 140.58 kB
/media/mux-background-video 16.48 kB
/media/mux-video 140.69 kB
/media/native-hls-video 5.84 kB
/media/shaka-video 197.66 kB
/media/spotify-audio 4.29 kB
/media/tiktok-video 4.26 kB
/media/twitch-video 4.38 kB
/media/vimeo-video 11.28 kB
/media/wistia-video 60.05 kB
/media/youtube-video 4.94 kB
Extensions (2)
Entry Initial
/extensions/google-cast 5.40 kB
/extensions/mux-data 25.75 kB
Players (5)
Entry Initial Lazy
/video/player 7.58 kB 56.87 kB
/audio/player 4.01 kB 56.87 kB
/background/player 2.28 kB 56.87 kB
/live-video/player 6.96 kB 56.87 kB
/live-audio/player 4.01 kB 56.87 kB
Skins (26)
Entry Type Initial Lazy
/video/minimal-skin.css css 6.52 kB
/video/skin.css css 6.35 kB
/video/minimal-skin js 48.42 kB 56.87 kB
/video/minimal-skin.tailwind js 55.32 kB 56.87 kB
/video/skin js 48.32 kB 56.87 kB
/video/skin.tailwind js 55.15 kB 56.87 kB
/audio/minimal-skin.css css 4.81 kB
/audio/skin.css css 4.74 kB
/audio/minimal-skin js 37.59 kB 56.87 kB
/audio/minimal-skin.tailwind js 42.79 kB 56.87 kB
/audio/skin js 37.53 kB 56.87 kB
/audio/skin.tailwind js 42.67 kB 56.87 kB
/background/skin.css css 90 B
/background/skin js 277 B
/live-video/minimal-skin.css css 6.52 kB
/live-video/skin.css css 6.35 kB
/live-video/minimal-skin js 40.50 kB 56.87 kB
/live-video/minimal-skin.tailwind js 47.18 kB 56.87 kB
/live-video/skin js 40.54 kB 56.87 kB
/live-video/skin.tailwind js 47.15 kB 56.87 kB
/live-audio/minimal-skin.css css 4.81 kB
/live-audio/skin.css css 4.74 kB
/live-audio/minimal-skin js 29.43 kB 56.87 kB
/live-audio/minimal-skin.tailwind js 33.39 kB 56.87 kB
/live-audio/skin js 29.43 kB 56.87 kB
/live-audio/skin.tailwind js 33.53 kB 56.87 kB
UI Components (39)
Entry Initial Lazy
/ui/airplay-button 10.43 kB 56.87 kB
/ui/alert-dialog 4.75 kB 56.87 kB
/ui/audio-track 7.92 kB 56.87 kB
/ui/audio-track-radio-group 9.10 kB 56.87 kB
/ui/buffering-indicator 7.83 kB 56.87 kB
/ui/captions-button 10.41 kB 56.87 kB
/ui/captions-radio-group 9.21 kB 56.87 kB
/ui/cast-button 10.41 kB 56.87 kB
/ui/controls 7.57 kB 56.87 kB
/ui/dialog 4.77 kB 56.87 kB
/ui/error-dialog 11.81 kB 56.87 kB
/ui/fullscreen-button 10.38 kB 56.87 kB
/ui/gesture 7.99 kB 56.87 kB
/ui/hotkey 8.38 kB 56.87 kB
/ui/live-button 8.77 kB 56.87 kB
/ui/menu 18.95 kB 56.87 kB
/ui/mute-button 10.44 kB 56.87 kB
/ui/pip-button 10.38 kB 56.87 kB
/ui/play-button 10.36 kB 56.87 kB
/ui/playback-rate 7.98 kB 56.87 kB
/ui/playback-rate-button 10.35 kB 56.87 kB
/ui/playback-rate-radio-group 9.14 kB 56.87 kB
/ui/popover 8.17 kB 56.87 kB
/ui/poster 7.57 kB 56.87 kB
/ui/quality 8.40 kB 56.87 kB
/ui/quality-radio-group 9.57 kB 56.87 kB
/ui/seek-button 10.40 kB 56.87 kB
/ui/seek-indicator 12.01 kB 56.87 kB
/ui/slider 12.67 kB 56.87 kB
/ui/status-announcer 10.11 kB 56.87 kB
/ui/status-indicator 12.32 kB 56.87 kB
/ui/thumbnail 8.71 kB 56.87 kB
/ui/time 9.76 kB 56.87 kB
/ui/time-slider 14.17 kB 56.87 kB
/ui/title 7.26 kB 56.87 kB
/ui/tooltip 8.95 kB 56.87 kB
/ui/volume-indicator 12.37 kB 56.87 kB
/ui/volume-popover 14.22 kB 56.87 kB
/ui/volume-slider 12.11 kB 56.87 kB
🧩 @videojs/core — no changes
Entries (76)
Entry Initial Lazy
. 13.02 kB
/dom 22.42 kB 56.87 kB
/vjsc 1.74 kB
/i18n 3.23 kB 56.87 kB
/i18n/locales/all 34.97 kB
/i18n/locales/ar 1.22 kB
/i18n/locales/az 1.09 kB
/i18n/locales/bg 1.29 kB
/i18n/locales/bn 1.23 kB
/i18n/locales/bs 1.00 kB
/i18n/locales/ca 1.07 kB
/i18n/locales/cs 1.07 kB
/i18n/locales/cy 1.02 kB
/i18n/locales/da 1006 B
/i18n/locales/de 1.09 kB
/i18n/locales/el 1.49 kB
/i18n/locales/en 785 B
/i18n/locales/es 1018 B
/i18n/locales/et 1.05 kB
/i18n/locales/eu 1.03 kB
/i18n/locales/fa 1.22 kB
/i18n/locales/fi 1.04 kB
/i18n/locales/fr 1.07 kB
/i18n/locales/gd 1.10 kB
/i18n/locales/gl 1022 B
/i18n/locales/he 1.14 kB
/i18n/locales/hi 1.30 kB
/i18n/locales/hr 1.02 kB
/i18n/locales/hu 1.10 kB
/i18n/locales/id 919 B
/i18n/locales/it 1.01 kB
/i18n/locales/ja 1.18 kB
/i18n/locales/ko 1.14 kB
/i18n/locales/lt 1.02 kB
/i18n/locales/lv 1.09 kB
/i18n/locales/mr 1.30 kB
/i18n/locales/nb 987 B
/i18n/locales/ne 1.29 kB
/i18n/locales/nl 1.00 kB
/i18n/locales/nn 987 B
/i18n/locales/oc 1.08 kB
/i18n/locales/pl 1.14 kB
/i18n/locales/pt 1.03 kB
/i18n/locales/pt-BR 1.03 kB
/i18n/locales/pt-PT 1.01 kB
/i18n/locales/ro 1.07 kB
/i18n/locales/ru 1.40 kB
/i18n/locales/sk 1.10 kB
/i18n/locales/sl 1.04 kB
/i18n/locales/sr 1.07 kB
/i18n/locales/sv 1.01 kB
/i18n/locales/te 1.32 kB
/i18n/locales/th 1.29 kB
/i18n/locales/tr 1.08 kB
/i18n/locales/uk 1.41 kB
/i18n/locales/vi 1.11 kB
/i18n/locales/zh 1.02 kB
/i18n/locales/zh-CN 1.02 kB
/i18n/locales/zh-TW 1.02 kB
/i18n/text/airplay 101 B
/i18n/text/buttons 137 B
/i18n/text/captions 93 B
/i18n/text/cast 114 B
/i18n/text/common 90 B
/i18n/text/container 75 B
/i18n/text/errors 285 B
/i18n/text/fullscreen 98 B
/i18n/text/live 126 B
/i18n/text/menu 249 B
/i18n/text/pip 101 B
/i18n/text/playback 80 B
/i18n/text/seek 105 B
/i18n/text/slider 65 B
/i18n/text/status 222 B
/i18n/text/time 280 B
/i18n/text/volume 133 B
🏷️ @videojs/element — no changes
Entries (2)
Entry Initial
. 1.05 kB
/context 943 B
📦 @videojs/store — no changes
Entries (3)
Entry Initial
. 1.72 kB
/html 703 B
/react 365 B
🔧 @videojs/utils — no changes
Entries (13)
Entry Initial
/array 271 B
/dom 5.02 kB
/events 320 B
/function 386 B
/i18n 249 B
/jwt 176 B
/object 535 B
/predicate 297 B
/percent 281 B
/string 239 B
/style 212 B
/time 976 B
/number 199 B

📦 @videojs/media

Path Base initial PR initial Initial diff Lazy diff
/dom/dash 209.83 kB 3.28 kB -206.54 kB (-98.4%)
/dom/wistia 60.09 kB 1.89 kB -58.20 kB (-96.9%)
Entries (23)
Entry Initial
. 1.07 kB
/dom 121 B
/dom/dash 3.28 kB
/dom/wistia 1.89 kB
/dom/audio-host 1.10 kB
/dom/cloudflare 3.69 kB
/dom/custom-media-element 2.13 kB
/dom/dash 209.83 kB
/dom/google-cast 4.06 kB
/dom/hls-js 139.16 kB
/dom/media-host 1.20 kB
/dom/media-played-ranges 576 B
/dom/mux 162.88 kB
/dom/native-hls 5.25 kB
/dom/shaka 197.02 kB
/dom/spotify 3.58 kB
/dom/tiktok 3.57 kB
/dom/twitch 3.62 kB
/dom/video-host 1.39 kB
/dom/vimeo 10.62 kB
/dom/wistia 60.09 kB
/dom/youtube 4.25 kB
/media-tracks 2.05 kB
📦 @videojs/spf — no changes
Entries (10)
Entry Initial
. 4.55 kB
/dom 6.60 kB
/hls 22.06 kB
/media-tracks 504 B
/hls-background-video 15.89 kB
/hls-audio 19.82 kB
/hls-video 25.85 kB
/mux-audio 20.76 kB
/mux-background-video 15.89 kB
/mux-video 26.67 kB

ℹ️ How to interpret

Each entry is independently bundled, minified, and brotli-compressed. Initial size includes its static import graph; lazy dynamic chunks are reported separately.

Entries are not additive because their dependency graphs overlap. Preset rows represent realistic combined bundles.

Changes of 300 B or less across initial, lazy, and total size are collapsed, not discarded.

Run pnpm size locally to check current initial sizes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant