Importations HTML

Inclure pour le Web

Pourquoi importer ?

Réfléchissez à la façon dont vous chargez différents types de ressources sur le Web. Pour JS, nous avons <script src>. Pour le CSS, vous pouvez utiliser <link rel="stylesheet">. Pour les images, il s'agit de <img>. La vidéo contient <video>. Audio, <audio>… Allez droit au but ! La plupart des contenus Web se chargent de manière simple et déclarative. Ce n'est pas le cas pour le code HTML. Voici les options qui s'offrent à vous:

  1. <iframe> : solution éprouvée, mais lourde. Le contenu d'un iframe réside entièrement dans un contexte distinct de celui de votre page. Bien que cette fonctionnalité soit généralement très utile, elle crée des défis supplémentaires (il est difficile de réduire la taille du cadre à son contenu, extrêmement frustrant de l'utiliser dans/hors du script et presque impossible de le styliser).
  2. AJAX : J'adore xhr.responseType="document", mais vous me dites que j'ai besoin de JS pour charger du code HTML ? Cela ne semble pas correct.
  3. CrazyHacks™ : intégrés dans des chaînes, masqués en tant que commentaires (par exemple, <script type="text/html">). Beurk !

Vous voyez l'ironie ? Le contenu le plus élémentaire du Web, le code HTML, nécessite le plus d'efforts pour être utilisé. Heureusement, les composants Web sont là pour nous remettre sur les rails.

Premiers pas

Les importations HTML, qui font partie de la caste Web Components, permettent d'inclure des documents HTML dans d'autres documents HTML. Vous n'êtes pas limité au balisage. Une importation peut également inclure du CSS, du JavaScript ou tout autre élément qu'un fichier .html peut contenir. En d'autres termes, les importations constituent un outil fantastique pour charger les éléments HTML/CSS/JS associés.

Principes de base

Incluez une importation sur votre page en déclarant un <link rel="import">:

<head>
    <link rel="import" href="/path/to/imports/stuff.html">
</head>

L'URL d'une importation est appelée emplacement d'importation. Pour charger du contenu à partir d'un autre domaine, l'emplacement d'importation doit être compatible avec le CORS:

<!-- Resources on other origins must be CORS-enabled. -->
<link rel="import" href="http://example.com/elements.html">

Détection et compatibilité des fonctionnalités

Pour détecter la compatibilité, vérifiez si .import existe sur l'élément <link>:

function supportsImports() {
    return 'import' in document.createElement('link');
}

if (supportsImports()) {
    // Good to go!
} else {
    // Use other libraries/require systems to load files.
}

La compatibilité avec les navigateurs en est encore à ses débuts. Chrome 31 a été le premier navigateur à implémenter les modules ES, mais les autres fournisseurs de navigateurs attendent de voir comment les modules ES se comportent. Toutefois, pour les autres navigateurs, le polyfill webcomponents.js fonctionne parfaitement jusqu'à ce que les éléments soient largement compatibles.

Regrouper des ressources

Les importations fournissent une convention permettant de regrouper du code HTML/CSS/JS (même d'autres importations HTML) dans un seul livrable. Il s'agit d'une fonctionnalité intrinsèque, mais puissante. Si vous créez un thème, une bibliothèque ou si vous souhaitez simplement segmenter votre application en blocs logiques, il est judicieux de fournir aux utilisateurs une seule URL. Vous pouvez même fournir une application entière via une importation. Réfléchissez-y un instant.

Bootstrap en est un exemple concret. Bootstrap se compose de fichiers individuels (bootstrap.css, bootstrap.js, polices), nécessite JQuery pour ses plug-ins et fournit des exemples de balisage. Les développeurs apprécient la flexibilité à la carte. Il leur permet d'accepter les parties du framework qu'ils souhaitent utiliser. Cela dit, je parie que le développeur Joe™ moyen prend la voie facile et télécharge l'intégralité de Bootstrap.

Les importations ont beaucoup de sens pour un élément tel que Bootstrap. Je vous présente l'avenir du chargement de Bootstrap:

<head>
    <link rel="import" href="bootstrap.html">
</head>

Les utilisateurs chargent simplement un lien d'importation HTML. Ils n'ont pas besoin de s'occuper de la dispersion des fichiers. Au lieu de cela, l'intégralité de Bootstrap est gérée et encapsulée dans une importation, bootstrap.html:

<link rel="stylesheet" href="bootstrap.css">
<link rel="stylesheet" href="fonts.css">
<script src="jquery.js"></script>
<script src="bootstrap.js"></script>
<script src="bootstrap-tooltip.js"></script>
<script src="bootstrap-dropdown.js"></script>
...

<!-- scaffolding markup -->
<template>
    ...
</template>

Laissez-moi réfléchir. C'est passionnant.

Événements de chargement/d'erreur

L'élément <link> déclenche un événement load lorsqu'une importation est chargée avec succès et onerror lorsque la tentative échoue (par exemple, si la ressource renvoie une erreur 404).

Les importations tentent d'être chargées immédiatement. Pour éviter les problèmes, utilisez simplement les attributs onload/onerror:

<script>
    function handleLoad(e) {
    console.log('Loaded import: ' + e.target.href);
    }
    function handleError(e) {
    console.log('Error loading import: ' + e.target.href);
    }
</script>

<link rel="import" href="file.html"
        onload="handleLoad(event)" onerror="handleError(event)">

Si vous créez l'importation de manière dynamique:

var link = document.createElement('link');
link.rel = 'import';
// link.setAttribute('async', ''); // make it async!
link.href = 'file.html';
link.onload = function(e) {...};
link.onerror = function(e) {...};
document.head.appendChild(link);

Utiliser le contenu

Inclure une importation sur une page ne signifie pas "placer le contenu de ce fichier ici". Cela signifie "Analyseur, allez chercher ce document pour que je puisse l'utiliser". Pour utiliser réellement le contenu, vous devez passer à l'action et écrire un script.

Un moment critique de aha! est de réaliser qu'une importation n'est qu'un document. En fait, le contenu d'une importation est appelé document d'importation. Vous pouvez manipular l'essentiel d'une importation à l'aide d'API DOM standards.

link.import

Pour accéder au contenu d'une importation, utilisez la propriété .import de l'élément de lien:

var content = document.querySelector('link[rel="import"]').import;

link.import est null dans les conditions suivantes:

  • Le navigateur n'est pas compatible avec les importations HTML.
  • <link> ne contient pas rel="import".
  • Le <link> n'a pas été ajouté au DOM.
  • Le <link> a été supprimé du DOM.
  • La ressource n'est pas compatible avec CORS.

Exemple complet

Disons que warnings.html contient:

<div class="warning">
    <style>
    h3 {
        color: red !important;
    }
    </style>
    <h3>Warning!
    <p>This page is under construction
</div>

<div class="outdated">
    <h3>Heads up!
    <p>This content may be out of date
</div>

Les importateurs peuvent récupérer une partie spécifique de ce document et la cloner sur leur page:

<head>
    <link rel="import" href="warnings.html">
</head>
<body>
    ...
    <script>
    var link = document.querySelector('link[rel="import"]');
    var content = link.import;

    // Grab DOM from warning.html's document.
    var el = content.querySelector('.warning');

    document.body.appendChild(el.cloneNode(true));
    </script>
</body>

Écrire des scripts dans les importations

Les importations ne figurent pas dans le document principal. Ils en sont satellites. Toutefois, votre importation peut toujours agir sur la page principale, même si le document principal est le plus important. Une importation peut accéder à son propre DOM et/ou au DOM de la page qui l'importe:

Exemple : import.html qui ajoute l'une de ses feuilles de style à la page principale

<link rel="stylesheet" href="http://www.example.com/styles.css">
<link rel="stylesheet" href="http://www.example.com/styles2.css">

<style>
/* Note: <style> in an import apply to the main
    document by default. That is, style tags don't need to be
    explicitly added to the main document. */
#somecontainer {
color: blue;
}
</style>
...

<script>
// importDoc references this import's document
var importDoc = document.currentScript.ownerDocument;

// mainDoc references the main document (the page that's importing us)
var mainDoc = document;

// Grab the first stylesheet from this import, clone it,
// and append it to the importing document.
    var styles = importDoc.querySelector('link[rel="stylesheet"]');
    mainDoc.head.appendChild(styles.cloneNode(true));
</script>

Remarquez ce qui se passe ici. Le script de l'importation fait référence au document importé (document.currentScript.ownerDocument) et ajoute une partie de ce document à la page d'importation (mainDoc.head.appendChild(...)). Assez complexe, si vous voulez mon avis.

Règles de JavaScript dans une importation:

  • Le script de l'importation est exécuté dans le contexte de la fenêtre contenant l'document d'importation. window.document fait donc référence au document de la page principale. Cela présente deux conséquences utiles :
    • Les fonctions définies dans une importation se retrouvent sur window.
    • Vous n'avez pas besoin de faire quoi que ce soit de compliqué, comme ajouter les blocs <script> de l'importation à la page principale. Le script est à nouveau exécuté.
  • Les importations ne bloquent pas l'analyse de la page principale. Toutefois, les scripts qui y sont inclus sont traités dans l'ordre. Cela signifie que vous obtenez un comportement semblable à celui de la mise en attente tout en conservant l'ordre correct des scripts. Pour en savoir plus, consultez la section ci-dessous.

Diffuser des composants Web

La conception des importations HTML se prête bien au chargement de contenu réutilisable sur le Web. En particulier, il s'agit d'un moyen idéal de distribuer des composants Web. Tout, des <template> HTML de base aux éléments personnalisés complets avec le DOM ombragé [1, 2, 3]. Lorsque ces technologies sont utilisées en tandem, les importations deviennent un #include pour les composants Web.

Inclure des modèles

L'élément "Modèle HTML" est particulièrement adapté aux importations HTML. <template> est idéal pour créer des sections de balisage que l'application d'importation peut utiliser à sa guise. Encapsuler du contenu dans un <template> présente également l'avantage de rendre le contenu inerte jusqu'à son utilisation. Autrement dit, les scripts ne s'exécutent pas tant que le modèle n'a pas été ajouté au DOM. Magnifique !

import.html

<template>
    <h1>Hello World!</h1>
    <!-- Img is not requested until the <template> goes live. -->
    <img src="world.png">
    <script>alert("Executed when the template is activated.");</script>
</template>
index.html

<head>
    <link rel="import" href="import.html">
</head>
<body>
    <div id="container"></div>
    <script>
    var link = document.querySelector('link[rel="import"]');

    // Clone the <template> in the import.
    var template = link.import.querySelector('template');
    var clone = document.importNode(template.content, true);

    document.querySelector('#container').appendChild(clone);
    </script>
</body>

Enregistrer des éléments personnalisés

Les éléments personnalisés sont une autre technologie de composants Web qui fonctionne très bien avec les importations HTML. Les importations peuvent exécuter du script. Pourquoi ne pas définir et enregistrer vos éléments personnalisés pour que les utilisateurs n'aient pas à le faire ? Appelons-le "inscription automatique".

elements.html

<script>
    // Define and register <say-hi>.
    var proto = Object.create(HTMLElement.prototype);

    proto.createdCallback = function() {
    this.innerHTML = 'Hello, <b>' +
                        (this.getAttribute('name') || '?') + '</b>';
    };

    document.registerElement('say-hi', {prototype: proto});
</script>

<template id="t">
    <style>
    ::content > * {
        color: red;
    }
    </style>
    <span>I'm a shadow-element using Shadow DOM!</span>
    <content></content>
</template>

<script>
    (function() {
    var importDoc = document.currentScript.ownerDocument; // importee

    // Define and register <shadow-element>
    // that uses Shadow DOM and a template.
    var proto2 = Object.create(HTMLElement.prototype);

    proto2.createdCallback = function() {
        // get template in import
        var template = importDoc.querySelector('#t');

        // import template into
        var clone = document.importNode(template.content, true);

        var root = this.createShadowRoot();
        root.appendChild(clone);
    };

    document.registerElement('shadow-element', {prototype: proto2});
    })();
</script>

Cette importation définit (et enregistre) deux éléments, <say-hi> et <shadow-element>. Le premier montre un élément personnalisé de base qui s'enregistre dans l'importation. Le deuxième exemple montre comment implémenter un élément personnalisé qui crée un Shadow DOM à partir d'un <template>, puis s'enregistre.

L'avantage d'enregistrer des éléments personnalisés dans une importation HTML est que l'importateur déclare simplement votre élément sur sa page. Aucune connexion n'est nécessaire.

index.html

<head>
    <link rel="import" href="elements.html">
</head>
<body>
    <say-hi name="Eric"></say-hi>
    <shadow-element>
    <div>( I'm in the light dom )</div>
    </shadow-element>
</body>

À mon avis, ce workflow seul fait des importations HTML un moyen idéal de partager des composants Web.

Gérer les dépendances et les sous-importations

Sous-importations

Il peut être utile qu'une importation inclue une autre. Par exemple, si vous souhaitez réutiliser ou étendre un autre composant, utilisez une importation pour charger l'autre ou les autres éléments.

Vous trouverez ci-dessous un exemple concret tiré de Polymer. Il s'agit d'un nouveau composant d'onglet (<paper-tabs>) qui réutilise un composant de mise en page et un composant de sélecteur. Les dépendances sont gérées à l'aide d'importations HTML.

paper-tabs.html (version simplifiée):

<link rel="import" href="iron-selector.html">
<link rel="import" href="classes/iron-flex-layout.html">

<dom-module id="paper-tabs">
    <template>
    <style>...</style>
    <iron-selector class="layout horizonta center">
        <content select="*"></content>
    </iron-selector>
    </template>
    <script>...</script>
</dom-module>

Les développeurs d'applications peuvent importer ce nouvel élément à l'aide des éléments suivants:

<link rel="import" href="paper-tabs.html">
<paper-tabs></paper-tabs>

Si un nouveau <iron-selector2> plus génial est disponible à l'avenir, vous pourrez remplacer <iron-selector> et l'utiliser immédiatement. Grâce aux importations et aux composants Web, vous ne risquez pas de perturber vos utilisateurs.

Gestion des dépendances

Nous savons tous que le chargement de JQuery plusieurs fois par page entraîne des erreurs. Cela ne va-t-il pas poser un énorme problème pour les composants Web lorsque plusieurs composants utilisent la même bibliothèque ? Pas si vous utilisez des importations HTML. Ils peuvent être utilisés pour gérer les dépendances.

En encapsulant des bibliothèques dans une importation HTML, vous supprimez automatiquement les doublons de ressources. Le document n'est analysé qu'une seule fois. Les scripts ne sont exécutés qu'une seule fois. Par exemple, supposons que vous définissiez une importation, jquery.html, qui charge une copie de JQuery.

jquery.html

<script src="http://cdn.com/jquery.js"></script>

Cette importation peut être réutilisée dans les importations ultérieures comme suit:

import2.html

<link rel="import" href="jquery.html">
<div>Hello, I'm import 2</div>
ajax-element.html

<link rel="import" href="jquery.html">
<link rel="import" href="import2.html">

<script>
    var proto = Object.create(HTMLElement.prototype);

    proto.makeRequest = function(url, done) {
    return $.ajax(url).done(function() {
        done();
    });
    };

    document.registerElement('ajax-element', {prototype: proto});
</script>

Même la page principale peut inclure jquery.html si elle a besoin de la bibliothèque:

<head>
    <link rel="import" href="jquery.html">
    <link rel="import" href="ajax-element.html">
</head>
<body>

...

<script>
    $(document).ready(function() {
    var el = document.createElement('ajax-element');
    el.makeRequest('http://example.com');
    });
</script>
</body>

Bien que jquery.html soit inclus dans de nombreux arbres d'importation différents, son document n'est extrait et traité qu'une seule fois par le navigateur. L'examen du panneau "Network" le confirme:

jquery.html est demandé une fois
jquery.html est demandé une seule fois

Considérations sur les performances

Les importations HTML sont vraiment géniales, mais comme pour toute nouvelle technologie Web, vous devez les utiliser judicieusement. Les bonnes pratiques de développement Web restent valables. Voici quelques points à prendre en compte.

Concaténer des importations

Il est toujours important de réduire les requêtes réseau. Si vous avez de nombreux liens d'importation de premier niveau, envisagez de les regrouper dans une seule ressource et d'importer ce fichier.

Vulcanize est un outil de compilation npm de l'équipe Polymer qui aplatit de manière récursive un ensemble d'importations HTML dans un seul fichier. Vous pouvez considérer cela comme une étape de compilation de concaténation pour les composants Web.

Les importations exploitent la mise en cache du navigateur

Beaucoup de gens oublient que la pile réseau du navigateur a été affinée au fil des ans. Les importations (et les sous-importations) exploitent également cette logique. L'importation http://cdn.com/bootstrap.html peut comporter des sous-ressources, mais elles seront mises en cache.

Le contenu n'est utile que lorsque vous l'ajoutez

Considérez le contenu comme inerte jusqu'à ce que vous appeliez ses services. Prenons une feuille de style normale créée dynamiquement:

var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'styles.css';

Le navigateur ne demande pas styles.css tant que link n'a pas été ajouté au DOM:

document.head.appendChild(link); // browser requests styles.css

Un autre exemple est le balisage créé de manière dynamique:

var h2 = document.createElement('h2');
h2.textContent = 'Booyah!';

Le h2 n'a pas vraiment de sens tant que vous ne l'avez pas ajouté au DOM.

Le même concept s'applique au document d'importation. Sauf si vous ajoutez son contenu au DOM, il s'agit d'une opération sans effet. En fait, la seule chose qui "s'exécute" directement dans le document d'importation est <script>. Consultez la section Écrire des scripts dans les importations.

Optimiser pour le chargement asynchrone

Importations du blocage du rendu

Les importations bloquent l'affichage de la page principale. Cela ressemble à ce que fait <link rel="stylesheet">. La raison pour laquelle le navigateur bloque le rendu des feuilles de style est de minimiser le FOUC. Les importations se comportent de manière similaire, car elles peuvent contenir des feuilles de style.

Pour être complètement asynchrone et ne pas bloquer l'analyseur ni le rendu, utilisez l'attribut async:

<link rel="import" href="/path/to/import_that_takes_5secs.html" async>

async n'est pas le paramètre par défaut pour les importations HTML, car il nécessite plus de travail de la part des développeurs. Par défaut, les importations HTML contenant des définitions d'éléments personnalisés sont chargées et mises à niveau dans l'ordre. Dans un monde entièrement asynchrone, les développeurs devraient gérer eux-mêmes cette danse et les délais de mise à niveau.

Vous pouvez également créer une importation asynchrone de manière dynamique:

var l = document.createElement('link');
l.rel = 'import';
l.href = 'elements.html';
l.setAttribute('async', '');
l.onload = function(e) { ... };

Les importations ne bloquent pas l'analyse

Les importations ne bloquent pas l'analyse de la page principale. Les scripts dans les importations sont traités dans l'ordre, mais ne bloquent pas la page d'importation. Cela signifie que vous obtenez un comportement semblable à celui de la mise en attente tout en conservant l'ordre correct des scripts. L'un des avantages de placer vos importations dans <head> est que l'analyseur peut commencer à travailler sur le contenu dès que possible. Toutefois, il est important de se rappeler que <script> dans le document principal continue de bloquer la page. Le premier <script> après une importation bloque le rendu de la page. En effet, une importation peut contenir un script qui doit être exécuté avant le script de la page principale.

<head>
    <link rel="import" href="/path/to/import_that_takes_5secs.html">
    <script>console.log('I block page rendering');</script>
</head>

En fonction de la structure de votre application et de votre cas d'utilisation, vous pouvez optimiser le comportement asynchrone de plusieurs façons. Les techniques ci-dessous permettent de limiter le blocage du rendu de la page principale.

Scénario 1 (à privilégier): vous n'avez pas de script dans <head> ni intégré dans <body>

Je vous recommande de ne pas placer <script> immédiatement après vos importations. Déplacez les scripts le plus tard possible dans le jeu. Mais vous suivez déjà cette bonne pratique, N'EST-CE PAS ? ;)

Exemple :

<head>
    <link rel="import" href="/path/to/import.html">
    <link rel="import" href="/path/to/import2.html">
    <!-- avoid including script -->
</head>
<body>
    <!-- avoid including script -->

    <div id="container"></div>

    <!-- avoid including script -->
    ...

    <script>
    // Other scripts n' stuff.

    // Bring in the import content.
    var link = document.querySelector('link[rel="import"]');
    var post = link.import.querySelector('#blog-post');

    var container = document.querySelector('#container');
    container.appendChild(post.cloneNode(true));
    </script>
</body>

Tout est en bas.

Scénario 1.5: l'importation s'ajoute automatiquement

Vous pouvez également ajouter votre propre contenu à l'importation. Si l'auteur de l'importation établit un contrat que le développeur de l'application doit suivre, l'importation peut s'ajouter à une zone de la page principale:

import.html:

<div id="blog-post">...</div>
<script>
    var me = document.currentScript.ownerDocument;
    var post = me.querySelector('#blog-post');

    var container = document.querySelector('#container');
    container.appendChild(post.cloneNode(true));
</script>
index.html

<head>
    <link rel="import" href="/path/to/import.html">
</head>
<body>
    <!-- no need for script. the import takes care of things -->
</body>

Scénario 2: vous avez un script dans <head> ou intégré dans <body>

Si l'importation prend beaucoup de temps à se charger, le premier <script> qui la suit sur la page empêche l'affichage de la page. Par exemple, Google Analytics recommande de placer le code de suivi dans le <head>. Si vous ne pouvez pas éviter de placer <script> dans le <head>, l'ajout dynamique de l'importation empêchera le blocage de la page:

<head>
    <script>
    function addImportLink(url) {
        var link = document.createElement('link');
        link.rel = 'import';
        link.href = url;
        link.onload = function(e) {
        var post = this.import.querySelector('#blog-post');

        var container = document.querySelector('#container');
        container.appendChild(post.cloneNode(true));
        };
        document.head.appendChild(link);
    }

    addImportLink('/path/to/import.html'); // Import is added early :)
    </script>
    <script>
    // other scripts
    </script>
</head>
<body>
    <div id="container"></div>
    ...
</body>

Vous pouvez également ajouter l'importation vers la fin de <body>:

<head>
    <script>
    // other scripts
    </script>
</head>
<body>
    <div id="container"></div>
    ...

    <script>
    function addImportLink(url) { ... }

    addImportLink('/path/to/import.html'); // Import is added very late :(
    </script>
</body>

Éléments à retenir

  • Le type MIME d'une importation est text/html.

  • Les ressources d'autres origines doivent être compatibles avec le protocole CORS.

  • Les importations à partir de la même URL sont récupérées et analysées une seule fois. Cela signifie que le script d'une importation n'est exécuté que la première fois qu'il est détecté.

  • Les scripts d'une importation sont traités dans l'ordre, mais ne bloquent pas l'analyse du document principal.

  • Un lien d'importation ne signifie pas "#include le contenu ici". Cela signifie "Analyseur, allez chercher ce document pour que je puisse l'utiliser plus tard". Les scripts s'exécutent au moment de l'importation, mais les feuilles de style, le balisage et d'autres ressources doivent être ajoutés explicitement à la page principale. Notez que les <style> n'ont pas besoin d'être ajoutés explicitement. Il s'agit d'une différence majeure entre les importations HTML et <iframe>, qui indique "charger et afficher ce contenu ici".

Conclusion

Les importations HTML permettent de regrouper les fichiers HTML/CSS/JS en une seule ressource. Bien qu'utile en soi, cette idée devient extrêmement puissante dans le monde des composants Web. Les développeurs peuvent créer des composants réutilisables que d'autres peuvent consommer et intégrer à leur propre application, le tout via <link rel="import">.

Les importations HTML sont un concept simple, mais elles permettent de nombreux cas d'utilisation intéressants pour la plate-forme.

Cas d'utilisation

  • Distribuez les éléments HTML/CSS/JS associés en un seul lot. Théoriquement, vous pouvez importer une application Web entière dans une autre.
  • Organisation du code : segmentez les concepts de manière logique dans différents fichiers, ce qui favorise la modularité et la réutilisation**.
  • Fournissez une ou plusieurs définitions d'élément personnalisé. Une importation peut être utilisée pour register et inclure ces éléments dans une application. Cette pratique applique de bons modèles logiciels, en séparant l'interface/la définition de l'élément de la façon dont il est utilisé.
  • Gérer les dépendances : les ressources sont automatiquement dédupliquées.
  • Scripts de bloc : avant les importations, le fichier d'une bibliothèque JS volumineuse était entièrement analysé pour pouvoir s'exécuter, ce qui était lent. Avec les importations, la bibliothèque peut commencer à fonctionner dès que le segment A est analysé. Moins de latence !
// TODO: DevSite - Code sample removed as it used inline event handlers
  • Parallélisation de l'analyse HTML : pour la première fois, le navigateur peut exécuter deux (ou plusieurs) analyseurs HTML en parallèle.

  • Permet de basculer entre les modes débogage et non débogage dans une application, simplement en modifiant la cible d'importation elle-même. Votre application n'a pas besoin de savoir si la cible d'importation est une ressource groupée/compilée ou un arbre d'importation.