Framework Integration
nomercy-video-player is framework-agnostic. The player mounts into a plain <div> and exposes its entire surface through methods and events, so the integration pattern is the same everywhere regardless of which framework renders the surrounding UI.
The lifecycle has three steps:
- Render a container element with a stable ID.
- Add plugins with
addPlugin(PluginClass), then call.setup(config). Plugin registration beforesetupis the conventional order that ensures plugins run in the initial lifecycle phase. - Call
player.dispose()when the component unmounts or the page navigates away.
Install
See Installation for the npm and CDN setup.
Imports
Player types and the factory come from the package root. Plugin classes come from the /plugins subpath:
import nmplayer from '@nomercy-entertainment/nomercy-video-player';
import { DesktopUiPlugin } from '@nomercy-entertainment/nomercy-video-player/plugins';
import type {
NMVideoPlayer,
VideoPlayerConfig,
VideoPlaylistItem,
} from '@nomercy-entertainment/nomercy-video-player';
Shared playlist example
Every framework guide on this site uses the same playlist shape. Here it is in one place so the per-framework pages stay focused on framework-specific wiring:
import type { VideoPlaylistItem } from '@nomercy-entertainment/nomercy-video-player';
const BASE = 'https://raw.githubusercontent.com/NoMercy-Entertainment/nomercy-media/master/Films';
const playlist: VideoPlaylistItem[] = [
{
id: 'sintel',
title: 'Sintel',
url: '/Sintel.(2010)/Sintel.(2010).NoMercy.m3u8',
image: 'https://image.tmdb.org/t/p/w780/q2bVM5z90tCGbmXYtq2J38T5hSX.jpg',
duration: 888,
subtitles: [
{
id: 'sintel-en',
label: 'English',
url: '/Sintel.(2010)/subtitles/Sintel.(2010).NoMercy.eng.full.vtt',
language: 'eng',
kind: 'subtitles',
},
],
},
{
id: 'tears-of-steel',
title: 'Tears of Steel',
url: '/Tears.of.Steel.(2012)/Tears.of.Steel.(2012).NoMercy.m3u8',
image: 'https://image.tmdb.org/t/p/w780/4TTgBp9Q4shlJLZMsuPuViBhpM2.jpg',
duration: 724,
subtitles: [
{
id: 'tos-en',
label: 'English',
url: '/Tears.of.Steel.(2012)/subtitles/Tears.of.Steel.(2012).NoMercy.eng.full.vtt',
language: 'eng',
kind: 'subtitles',
},
],
},
{
id: 'bbb',
title: 'Big Buck Bunny',
url: '/Big.Buck.Bunny.(2008)/Big.Buck.Bunny.(2008).NoMercy.m3u8',
image: 'https://image.tmdb.org/t/p/w780/uVEFQvFMMsg4e6yb03xOfVsDz0o.jpg',
duration: 596,
},
];
The baseUrl option resolves relative url paths on playlist items, so you pass it once in the config rather than embedding it in every item:
const config: VideoPlayerConfig = {
baseUrl: BASE,
playlist,
};
The mount/init/dispose lifecycle
This is the complete pattern in plain TypeScript, without any framework glue:
import nmplayer from '@nomercy-entertainment/nomercy-video-player';
import { DesktopUiPlugin } from '@nomercy-entertainment/nomercy-video-player/plugins';
// Step 1: container must already be in the DOM.
const container = document.getElementById('player')!;
// Step 2: create the player, add plugins, set up config.
const player = nmplayer('main')
.addPlugin(DesktopUiPlugin)
.setup({
baseUrl: 'https://raw.githubusercontent.com/NoMercy-Entertainment/nomercy-media/master/Films',
playlist,
});
player.on('ready', () => {
player.item(0, { autoplay: true });
});
// Step 3: clean up when done.
// Call this in your framework's unmount hook.
function cleanup() {
player.dispose();
}
Note: calling
setup()before the container element exists in the DOM will throw. Always initialise inside the framework lifecycle hook that guarantees the DOM is ready, such asonMounted,useEffect,onMount,ngAfterViewInit, orDOMContentLoaded.
Where each framework hooks in
| Framework | Init hook | Cleanup hook |
|---|---|---|
| Vue 3 | onMounted | onBeforeUnmount |
| React | useEffect (return cleanup fn) | useEffect cleanup / useRef |
| Svelte | onMount | onDestroy |
| Angular | ngAfterViewInit | ngOnDestroy |
| Vanilla JS | DOMContentLoaded | beforeunload or manual |