Nexanexa
Paso 10

Librerías externas y otros frameworks

¿Bootstrap, PrimeVue, un gráfico con Chart.js, un juego con Phaser, o convivir con una app entera de Quasar, Vue, React o Angular? Nexa no reemplaza nada de eso — sabe convivir con todo, con un mecanismo distinto según qué tan "viva" sea la librería.

CSS de terceros: un <link> normal

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">

Bootstrap, Tailwind por CDN, el CSS de PrimeVue/PrimeReact — Nexa nunca procesa ni entiende ese CSS, así que no hace falta ningún paso especial. Un <link rel="stylesheet"> en src/layout.tsx (para todo el sitio) o en una página puntual alcanza.

JS con build global (UMD): un <script> normal

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

function renderChart() {
    new Chart(document.getElementById("grafico"), {
        type: "bar",
        data: { labels: ["Ene", "Feb"], datasets: [{ data: [10, 20] }] }
    });
}

Bootstrap JS, Chart.js, y en general cualquier librería que se pueda cargar como <script> clásico (no type="module") deja una variable global (bootstrap, Chart, ...). Como un chunk de Nexa copia el handler tal cual, podés usar esa variable global directo en un onClick — sin declarar nada en nexa.toml.

Librerías ES module puras: el mismo [imports] que platform/stripe

# nexa.toml
[imports]
confetti = "https://esm.sh/canvas-confetti"

Si la librería solo se distribuye como módulo ES (sin build global), usá [imports] — el mismo mecanismo que ya usan platform y stripe. El chunk detecta <nombre>. en el handler y antepone el import; el import map del <head> resuelve el specifier a la URL real.

Motores y frameworks completos: como isla

<div data-nexa-island="game" data-nexa-strategy="visible">
    <p>Cargando juego…</p>
</div>

// src/islands/game.island.ts — Phaser cargado como <script> global
export default function mount(el) {
    const game = new Phaser.Game({ parent: el, width: 800, height: 600 });
    return () => game.destroy(true);
}

Para algo con ciclo de vida propio — el loop de un juego de Phaser, o un árbol de componentes con estado de Vue/Quasar/React/Angular — la respuesta es una isla, no [imports] suelto en un handler. Tu app de Quasar se compila con SU propio build (Vite, igual que siempre); Nexa nunca lee tus .vue ni tus .tsx de React, solo sirve el bundle final como cualquier otro JS. Importante: aunque la sintaxis de Nexa se parezca a React (JSX, export default function), una página Nexa NO es un componente React — se compila a HTML estático una sola vez, sin VDOM, sin hooks, sin re-render. useState/useEffect no funcionan ahí; si necesitás eso de verdad, va dentro de una isla que use React de verdad.

Vendorizar un paquete de npm real: la guía completa

mkdir vendor-build && cd vendor-build
npm install marked
echo 'export { marked } from "marked";' > entry.js
npx esbuild entry.js --bundle --format=esm --target=es2022 --outfile=marked.js
cp marked.js ../public/vendor/marked.js

# nexa.toml
[imports]
marked = "/vendor/marked.js"

Cuando el paquete tiene dependencias propias o viene en CommonJS (el caso más común, no solo ESM puro del punto anterior), hace falta un paso de bundling — instalar el paquete en cualquier lado con npm, un entry.js que re-exporte lo necesario, y esbuild --bundle --format=esm a un único archivo, copiado a public/vendor/. El proceso paso a paso, con dos ejemplos reales ya probados (con envoltorio propio, y sin ninguno), está en docs/VENDORING.md del repo de Nexa.