Problem
Once player adapters are split into separate files (#228), consumers using non-native players still have to include the right <script> tag(s) manually. The library already knows which adapter is needed — it reads data-player-type on the player element at instantiation. Letting the core fetch the adapter itself would remove the manual step entirely.
Proposed direction
Once the library is distributed as ES modules (#218), the hyperaudioPlayer factory can do something like:
async function hyperaudioPlayer(playerType, instance) {
if (playerType === 'native') return new NativePlayer(instance);
const mod = await import(`./players/${playerType}.js`);
return new mod.default(instance);
}
That means:
- Consumers using SoundCloud/YouTube/Vimeo/VideoJS/Spotify can drop the extra
<script> tag from their HTML. Including the core is enough.
- Native-only consumers (the common case) never pay for adapter bytes.
- Paths are module-relative — no
document.currentScript.src discovery, no global registration shims, no consumer-configured playerPath option.
Why this needs #218 first
Without ESM, doing the same thing with classic scripts requires:
- A custom loader using dynamic
<script> injection
- Base-path discovery via
document.currentScript.src (fragile)
- A global-registration namespace for adapters to attach themselves to
- Manual error handling for failed loads
All of that gets replaced by a one-line import() once ESM is in place. Better to wait than build a loader we throw away.
Why this needs #228 first
The adapters need to be in separate files before they can be loaded separately. #228 does that refactor without changing runtime behaviour.
Compat notes
Once shipped, this changes behaviour in a few subtle ways consumers should know about:
- Constructor becomes async-ish.
new HyperaudioLite(...) returns before the adapter has loaded. instance.myPlayer won't exist for a brief window. Transcript clicks during that window need to queue (or no-op gracefully). Direct access patterns like instance.myPlayer.play() immediately after construction break.
- First-play latency. On slow connections, clicking play within the first ~200ms after page load might wait for the adapter fetch. Usually imperceptible.
- Error UX shifts to runtime. A 404 on the adapter file shows up at HAL instantiation rather than at page load. Needs a clear console error.
- YouTube API script load serialises. Currently the YouTube IFrame API script load happens during page load. With lazy loading, it's: youtube.js fetch → then YT API script fetch → then ready. Two round trips instead of one.
#217 (options-object constructor) would give a natural place to expose an onReady callback for consumers who need to know when the adapter has finished loading.
Related
- Depends on #218 — ESM/CJS distribution
- Depends on #228 — split adapters into separate files
- Touches #217 — options-object constructor (natural home for an
onReady callback)
Problem
Once player adapters are split into separate files (#228), consumers using non-native players still have to include the right
<script>tag(s) manually. The library already knows which adapter is needed — it readsdata-player-typeon the player element at instantiation. Letting the core fetch the adapter itself would remove the manual step entirely.Proposed direction
Once the library is distributed as ES modules (#218), the
hyperaudioPlayerfactory can do something like:That means:
<script>tag from their HTML. Including the core is enough.document.currentScript.srcdiscovery, no global registration shims, no consumer-configuredplayerPathoption.Why this needs #218 first
Without ESM, doing the same thing with classic scripts requires:
<script>injectiondocument.currentScript.src(fragile)All of that gets replaced by a one-line
import()once ESM is in place. Better to wait than build a loader we throw away.Why this needs #228 first
The adapters need to be in separate files before they can be loaded separately. #228 does that refactor without changing runtime behaviour.
Compat notes
Once shipped, this changes behaviour in a few subtle ways consumers should know about:
new HyperaudioLite(...)returns before the adapter has loaded.instance.myPlayerwon't exist for a brief window. Transcript clicks during that window need to queue (or no-op gracefully). Direct access patterns likeinstance.myPlayer.play()immediately after construction break.#217 (options-object constructor) would give a natural place to expose an
onReadycallback for consumers who need to know when the adapter has finished loading.Related
onReadycallback)