Player em React/Next.js
Integre o player da Spalla em projetos React e Next.js (App Router).
O player da Spalla não é um pacote npm: ele é um script carregado por <script> e exposto como window.SpallaPlayer. Em React, isso significa carregar o script antes de qualquer componente que crie um player — e ler a global depois de montado.
Coloque os arquivos do player em public/vendor/.
Baixe o pacote da
release do player
e copie para dentro de public/vendor/ do seu projeto:
spalla-player.min.js(pode renomear paraspalla-player.js)spalla-player.transmuxer-worker.js— na mesma pasta do player; ele é localizado automaticamente ao lado do scriptwasm_exec.js(espalla.wasm, se o pacote o incluir) — apenas se a sua política de CSP proíbeworker-src blob:
Arquivos em public/ são servidos como estáticos pelo Next, então
/vendor/spalla-player.js resolve sem configuração adicional.
Alternativa via CDN: em vez de hospedar os arquivos, aponte o
<Script src> do próximo passo direto para
https://beyond.spalla.io/player/spalla-player.min.js, preservando a
estratégia beforeInteractive. A URL serve sempre a última versão
publicada, sem fixar versão; o player localiza os arquivos auxiliares ao
lado do script no CDN, sem copiá-los para o projeto. Para decidir quando
atualizar, prefira o bundle local de uma release específica.
Carregue o script no layout raiz com a estratégia beforeInteractive:
// app/layout.jsx
import Script from "next/script";
export default function RootLayout({ children }) {
return (
<html lang="pt-BR">
<body>
<Script src="/vendor/spalla-player.js" strategy="beforeInteractive" />
{children}
</body>
</html>
);
}Essa estratégia é essencial: garante que window.SpallaPlayer já exista
antes de qualquer componente montar. Qualquer outra (afterInteractive,
lazyOnload) arrisca uma corrida em que o componente tenta
new SpallaPlayer(...) antes do script terminar de carregar.
Crie o player num componente cliente. O componente recebe o ID do conteúdo, monta o player e — importante — o destrói na limpeza:
"use client";
import { useEffect, useRef } from "react";
export function PlayerStage({ contentId }) {
const containerRef = useRef(null);
useEffect(() => {
const instancia = new window.SpallaPlayer(containerRef.current);
instancia.load(contentId).catch(console.error);
return () => instancia.destroy();
}, [contentId]);
return <div ref={containerRef} />;
}Sem o destroy() na limpeza, trocar de tela ou desmontar o componente
deixa o player anterior tocando em segundo plano.
Skin registrada em runtime: nunca importe no topo do módulo
Uma skin personalizada estende SpallaPlayer.Skin, que só
existe depois do script carregar. Importar esse arquivo no topo de um
módulo quebra em produção: o Next também renderiza componentes
'use client' no servidor (para gerar o HTML inicial),
e lá window não existe. Importe dinamicamente, dentro de um
useEffect, depois de confirmar que está no navegador:
useEffect(() => {
import("../skins/minhaSkin.js").then(() => {
const instancia = new window.SpallaPlayer(containerRef.current, {
skin: "minha",
});
});
}, []);Como registrar a skin em si está no guia de skins personalizadas.
Onde aprofundar
O repositório do player traz dois exemplos Next.js: o
completo,
com quatro telas (controles com painel próprio, overlay personalizado, várias
instâncias na mesma página e skin registrada em runtime), e a
variante que carrega o player do CDN,
sem bundle em public/vendor/. Para criar skins e plugins próprios, veja
skins personalizadas e plugins.