Skip to content

fix(html): preserve side-effect imports and fix context upgrade order#691

Closed
decepulis wants to merge 2 commits intomainfrom
docs/provider-refactor-fix
Closed

fix(html): preserve side-effect imports and fix context upgrade order#691
decepulis wants to merge 2 commits intomainfrom
docs/provider-refactor-fix

Conversation

@decepulis
Copy link
Copy Markdown
Collaborator

@decepulis decepulis commented Mar 3, 2026

Summary

Fixes two bugs introduced by PR #635 (provider/container split) that both manifest as StoreError: NO_TARGET:

  • tsdown unbundle mode strips side-effect imports — bare import './slider-fill' in composite define files gets tree-shaken away, so sub-element customElements.define() calls never run. Fixed by inlining registrations directly in composite files with customElements.get() guards.

  • @lit/context upgrade order — ES import hoisting caused <media-container> to upgrade before <video-player>, so the consumer's context-request event fired before the provider existed. Fixed by extracting MediaContainerElement class to a separate file (no auto-registration) and registering container after player.

Also removes the PlayerMixin migration doc (not needed since the site isn't public yet) and fixes the playback-rate-button demo's missing <media-container>.

Note: A third related bug (shared slider sub-elements across multiple slider types on the same page) is documented in #688 but not fixed in this PR.

Changes

Upgrade order fix:

  • New define/media/container-element.ts — class-only, no registration
  • define/media/container.ts — simplified, imports from element file
  • define/video/player.ts, define/audio/player.ts, define/background/player.ts — import from container-element, register player first, then container with guard

Inlined sub-element registrations:

  • define/ui/slider.ts, time-slider.ts, volume-slider.ts — inline customElements.define() for slider sub-elements
  • define/ui/time.ts — inline registration for time-group, time-separator
  • define/ui/controls.ts — inline registration for controls-group
  • Leaf define files (slider-fill.ts, slider-thumb.ts, etc.) reverted to original state

Docs cleanup:

  • Deleted reference/player-mixin.mdx
  • Removed sidebar entry from docs.config.ts
  • Fixed playback-rate-button demo HTML (added <media-container>)

Test plan

  • pnpm -F @videojs/html build — clean build
  • Built output confirms customElements.define() calls present for all sub-elements
  • pnpm -F @videojs/html test — all tests pass
  • pnpm typecheck — no new errors
  • Play button demo works (upgrade order fix verified)
  • Playback rate button demo works
  • Time slider sub-elements receive data-* attributes and ARIA (tree-shaking fix verified)

🤖 Generated with Claude Code

tsdown unbundle mode was stripping bare side-effect imports in composite
define files, preventing child custom elements from being registered.
Additionally, the import chain caused `<media-container>` (consumer) to
upgrade before `<video-player>` (provider), so the @lit/context handshake
failed silently — the store never attached and controls threw NO_TARGET.

Fix tree-shaking by converting bare imports to re-exports. Fix upgrade
order by extracting the container class to a separate module and
registering it after the player in each player define file.

Closes #688

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@netlify
Copy link
Copy Markdown

netlify Bot commented Mar 3, 2026

Deploy Preview for vjs10-site ready!

Name Link
🔨 Latest commit ec5d417
🔍 Latest deploy log https://app.netlify.com/projects/vjs10-site/deploys/69a74e894ee01c0008ae5ac4
😎 Deploy Preview https://deploy-preview-691--vjs10-site.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 3, 2026

📦 Bundle Size Report

Package Size Diff %
@videojs/core 10.28 kB 0 B ░░░░░░░░ 0%
@videojs/element 1.60 kB 0 B ░░░░░░░░ 0%
@videojs/html 18.36 kB 0 B ░░░░░░░░ 0%
@videojs/icons 3.79 kB 0 B ░░░░░░░░ 0%
@videojs/react 14.96 kB 0 B ░░░░░░░░ 0%
@videojs/store 1.95 kB 0 B ░░░░░░░░ 0%
@videojs/utils 2.81 kB 0 B ░░░░░░░░ 0%

Total: 53.75 kB · 0 B · 0%


Entry Breakdown

Subpath sizes are the additional bytes on top of the root entry point, measured by bundling root + subpath together and subtracting the root-only size.

@videojs/core
Entry Base PR Diff %
. 4.28 kB 4.28 kB 0 B 0%
./dom 6.01 kB 6.01 kB 0 B 0%
total 10.28 kB 10.28 kB 0 B 0%
@videojs/element
Entry Base PR Diff %
. 817 B 817 B 0 B 0%
./context 823 B 823 B 0 B 0%
total 1.60 kB 1.60 kB 0 B 0%
@videojs/html
Entry Base PR Diff %
. 15.20 kB 15.20 kB 0 B 0%
./video 1.06 kB 1.06 kB 0 B 0%
./audio 1.06 kB 1.06 kB 0 B 0%
./background 1.05 kB 1.05 kB 0 B 0%
total 18.36 kB 18.36 kB 0 B 0%
@videojs/icons
Entry Base PR Diff %
./react 2.27 kB 2.27 kB 0 B 0%
./html 1.52 kB 1.52 kB 0 B 0%
total 3.79 kB 3.79 kB 0 B 0%
@videojs/store
Entry Base PR Diff %
. 1.29 kB 1.29 kB 0 B 0%
./html 468 B 468 B 0 B 0%
./react 204 B 204 B 0 B 0%
total 1.95 kB 1.95 kB 0 B 0%
@videojs/utils
Entry Base PR Diff %
./array 104 B 104 B 0 B 0%
./dom 928 B 928 B 0 B 0%
./events 227 B 227 B 0 B 0%
./function 261 B 261 B 0 B 0%
./object 119 B 119 B 0 B 0%
./predicate 265 B 265 B 0 B 0%
./string 148 B 148 B 0 B 0%
./style 185 B 185 B 0 B 0%
./time 478 B 478 B 0 B 0%
./number 158 B 158 B 0 B 0%
total 2.81 kB 2.81 kB 0 B 0%

ℹ️ How to interpret

Sizes are minified + brotli, measured with esbuild.
Package totals are computed as root size + marginal subpath costs.
Subpath marginal cost = (root + subpath bundled together) − root alone.

Icon Meaning
No change
🔺 Increased ≤ 10%
🔴 Increased > 10%
🔽 Decreased
🆕 New (no baseline)

Run pnpm size locally to check current sizes.

@decepulis decepulis marked this pull request as draft March 3, 2026 20:44
Re-exports don't work — tsdown unbundle mode resolves re-export chains
to source modules, bypassing leaf define files and their
customElements.define() calls entirely. Instead, composite define files
now import element classes directly from source and call
customElements.define() inline with guards to prevent double
registration.

Leaf define files are reverted to their original state (import + define
only) and still work for direct imports.

Closes #688

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@decepulis
Copy link
Copy Markdown
Collaborator Author

closed in #703

@decepulis decepulis closed this Mar 4, 2026
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