ENbext.dev
DocumentationInclusions côté serveur

Traduction automatique depuis l’anglais. Consulter l’original.

Sur cette page

Rendu des composants

Un <bext-include> peut pointer vers un fichier de composant — bext le compile et le SSR dans son pool d'isolation V8, avec une hydratation facultative côté client via le système d'îlot.

html
<bext-include src="./components/PricingTable.tsx"
  render="v8"
  props='{"plan":"pro","locale":"fr"}'
></bext-include>

bext compile le TSX, exécute le composant exporté dans un contexte V8 avec les accessoires et émet le code HTML SSR en ligne. Pas de processus Bun, pas de framework d'exécution, pas d'étape de construction distincte.

Attributs#

Attribut Valeurs But
render v8, quickjs Quel moteur utiliser
props Chaîne JSON Accessoires transmis au composant
hydrate booléen Sortie d'enveloppe pour l'hydratation du client

Comment ça marche#

code
<bext-include src="./components/PricingTable.tsx" render="v8" props='{"plan":"pro"}'>
  ↓
1. Resolve file path relative to site root
   ↓
2. Check bundle cache
     HIT  → load cached compiled bundle
     MISS → compile with Turbopack/SWC
            · strip TypeScript types
            · resolve imports
            · bundle into IIFE
          → store in L1 mmap cache
   ↓
3. Checkout V8 isolate from pool
   ↓
4. Execute in isolate context with:
     · component module
     · props (parsed JSON)
     · request context (headers, cookies, locale)
   ↓
5. Call renderToString() → HTML
   ↓
6. Return isolate to pool
   ↓
7. Optionally wrap in <bext-island> for hydration
   ↓
8. Return HTML

Le pool V8 est préchauffé au démarrage. Temps de rendu typiques :

  • Composant simple (nav, bouton) : ~1-5ms
  • Composant moyen (liste, formulaire) : ~5-20 ms
  • Composant complexe (graphique, tableau) : ~20-100 ms

Combinez-le avec la mise en cache ttl pour amortir le coût sur de nombreuses requêtes.

Sélection du moteur#

Moteur Indicateur de fonctionnalité Utiliser quand
v8 v8 Défaut; meilleures performances sous Linux/x86
quickjs (toujours) Petite taille binaire ; plus lent mais toujours activé

Activez le moteur dont vous avez besoin :

toml
# bext.config.toml
[include.v8]
enabled = true
max_execution_ms = 500
max_memory_mb = 64
pool_size = 4

Accessoires#

Transmettez les accessoires sous forme de chaîne JSON dans l'attribut props :

html
<bext-include src="./Hero.tsx"
  render="v8"
  props='{"title":"Welcome","subtitle":"Build fast","showCta":true}'
></bext-include>

Les accessoires sont analysés au format JSON et transmis au composant :

tsx
// components/Hero.tsx
interface HeroProps {
  title: string;
  subtitle: string;
  showCta: boolean;
}

export default function Hero({ title, subtitle, showCta }: HeroProps) {
  return (
    <section>
      <h1>{title}</h1>
      <p>{subtitle}</p>
      {showCta && <a href="/signup">Sign up</a>}
    </section>
  );
}

Les accessoires sont inclus dans la clé de cache : différents accessoires produisent différentes entrées en cache.

Hydratation#

Par défaut, les rendus V8 produisent du HTML statique — pas de JavaScript côté client. Pour les composants interactifs, ajoutez hydrate :

html
<bext-include src="./Counter.tsx"
  render="v8"
  props='{"initial":0}'
  hydrate
></bext-include>

La sortie est enveloppée dans un élément <bext-island> que le système d’îlots PRISM hydrate côté client :

html
<div data-bext-island="Counter" data-props='{"initial":0}'>
  <button>Count: 0</button>
</div>
<script type="module">
  import { hydrateIsland } from '/__bext/islands/Counter.js';
  hydrateIsland(document.querySelector('[data-bext-island="Counter"]'));
</script>

Le JS côté client du composant est regroupé séparément et chargé uniquement pour les cibles insulaires. Aucun coût d'hydratation à l'échelle de la page.

Fonctions d'hôte#

Les rendus V8 ont accès aux fonctions hôtes bext — les mêmes que celles disponibles en SSR pleine page :

tsx
// components/UserDashboard.tsx
import { bext } from '@bext/platform';

export default async function UserDashboard(props) {
  const user = await bext.fetch('/api/user/me', {
    headers: { Cookie: bext.headers.cookie }
  });
  const cached = await bext.cache.get(`dashboard:${user.id}`);

  return <div>{/* ... */}</div>;
}

API disponibles :

  • bext.cache — obtenir/définir/invalider
  • bext.realtime — publier sur les chaînes
  • bext.fetch — Récupérations HTTP
  • bext.headers / bext.cookies — contexte de demande
  • bext.logger — journalisation structurée

Mise en cache du bundle#

Les bundles compilés sont mis en cache dans le magasin mmap L1, indexés par le mtime du fichier source. La modification d'un composant déclenche la recompilation ; sinon, le bundle est chargé depuis le cache à chaque requête.

code
First request to /Counter.tsx
  → source mtime = 1712000000
  → compile with Turbopack
  → store bundle at .bext/cache/bundles/{hash}.js
  → execute

Subsequent requests (file unchanged)
  → mtime check passes
  → load cached bundle from mmap (microseconds)
  → execute

You edit Counter.tsx
  → mtime changes → re-compile → update cache

Dev mode: file watcher triggers immediate invalidation

Limites de carburant#

Les rendus V8 s'exécutent sous le bac à sable de bext avec des limites d'exécution basées sur le carburant — le thread de surveillance interrompt l'exécution si elle prend trop de temps :

toml
[include.v8]
max_execution_ms = 500   # hard kill at 500ms
max_memory_mb = 64       # hard kill at 64MB

Un composant incontrôlé ne peut pas bloquer le serveur. Si l'exécution dépasse la limite, l'inclusion renvoie None et la chaîne de secours entre en jeu.

Attention

Les rendus V8 sont chers : un composant complexe peut prendre 20 à 100 ms. Associez toujours un render="v8" à un ttl pour amortir le coût. L'exécution de V8 à chaque requête sans mise en cache saturera le pool en cas de trafic réel.

Combinaison avec la mise en cache#

Les rendus V8 sont chers. Associez-le toujours avec ttl :

html
<bext-include src="./PricingTable.tsx"
  render="v8"
  props='{"plan":"pro"}'
  ttl="1h"
  vary="locale"
></bext-include>
  • Première requête : rendu V8 (~20ms).
  • Requêtes suivantes : accès au cache (~50µs).
  • Changement de paramètres régionaux : nouvelle entrée de cache ; Le rendu V8 se reproduit pour ces paramètres régionaux.

Combiner avec le streaming#

Les rendus V8 peuvent être diffusés paresseusement :

html
<bext-include src="./HeavyChart.tsx"
  render="v8"
  props='{"data":"..."}'
  loading="lazy"
  timeout="500ms"
>
  <div class="chart-skeleton"></div>
</bext-include>

Shell arrive avec le squelette. Le rendu V8 se produit en arrière-plan. Le morceau arrive lorsqu'il est prêt.

Sécurité#

Les rendus V8 s'exécutent dans un contexte isolé :

  • Pas d'accès au système de fichiers hôte (au-delà de la lecture des partiels configurés).
  • Aucun accès aux variables d'environnement sauf celles explicitement transmises.
  • à consommation limitée — pas de boucles infinies.
  • à mémoire limitée — pas d'attaques par épuisement du tas.
  • connecté au réseau : l'hôte fetch respecte une liste d'autorisation configurée par site.

Le bac à sable V8 est le même que celui utilisé pour le système de plugins de bext, qui a été audité pour l'exécution côté serveur de code non fiable.

Conseil

Le bundle compilé est mis en cache par le mtime du fichier source — la modification d'un fichier de composant déclenche la recompilation à la requête suivante. En mode développement, l'observateur de fichiers invalide immédiatement le bundle afin que vous n'ayez pas à redémarrer le serveur.

Quand utiliser les rendus V8#

Utiliser les inclusions rendues en V8 lorsque :

  • Vous disposez de composants React /JSX qui nécessiteraient autrement un processus Bun SSR distinct.
  • Vous souhaitez un SSR par fragment sans pipeline SSR pleine page.
  • Vous avez besoin de composants interactifs avec hydratation pour des parties spécifiques d'une page.
  • Vous migrez depuis un framework mais souhaitez conserver certains composants SSR.

N'utilisez pas les rendus V8 lorsque :

  • Le HTML statique est suffisant (utilisez des fichiers partiels).
  • Le contenu est purement basé sur les données (utilisez un point de terminaison qui renvoie du HTML).
  • Vous effectuez le rendu à chaque requête sans mise en cache (la V8 coûte cher).

Voir aussi#

Modifier cette page ↗Besoin d’aide ? ↗
Rechercher dans la documentation

Saisissez un sujet, une commande ou une question.