
Photo de médias sociaux par Federico Bottos sur unclash
Une petite bibliothèque toollerless avec des outils inclus. Démo en direct
Veuillez poser des questions dans le référentiel de discussions dédiées, pour aider la communauté autour de ce projet à grandir ♥
Inspirée par Vue 3 " One Piece ", UCE-Template fournit un élément <template> intégré sur mesure pour définir les composants d'une manière Vue .
< template is =" uce-template " >
< style scoped >
span { color: green }
</ style >
< the-green >
The < span > {{thing}} </ span > is green
</ the-green >
< script type =" module " >
export default {
setup ( ) {
return { thing : 'world' }
}
}
</ script >
</ template >Ajoutez cette bibliothèque à l'équation et voyez-la bootstrap tous les composants définis.
<template lazy> , pour résoudre leur définition uniquement en direct<custom-element shadow> Composants, et les styles <style shadow> Omballed éventuellement@uce virtuel, pour créerresolve(name, module) Bien qu'il soit suggéré d'installer la CLI à l'échelle mondiale, en raison d'une dépendance à la lumière non super-super, c'est toujours une commande npx :
# check all options and usage
npx uce-template --help
# works with files
npx uce-template my-component.html
# works with stdin
cat my-component.html | uce-templateC'est tout, mais bien sûr, nous devrions être sûrs que la disposition produite fonctionne toujours comme prévu?
Tout modèle qui étend uce-template doit contenir au moins un élément personnalisé, soit régulier ou intégré:
<!-- register regular-element -->
< template is =" uce-template " >
< regular-element >
regular
</ regular-element >
</ template >
<!-- register builtin-element as div -->
< template is =" uce-template " >
< div is =" builtin-element " >
builtin
</ div >
</ template > Tout modèle peut contenir une seule balise <script> , et / ou une ou plusieurs définitions <style> .
Si un composant contient des définitions {{slot.name}} , les nœuds du HTML vivant, avant que le composant ne soit mis à niveau, y sera placé une fois en direct.
Voir cet exemple en direct pour mieux comprendre.
Chaque " composant " peut se définir avec ou sans son propre contenu statique ou dynamique.
Un tel contenu sera utilisé pour rendre chaque élément personnalisé une fois " monté " (en direct) et pour chaque changement d'état réactif, mais uniquement si le modèle n'est pas vide.
Toutes les pièces dynamiques doivent être enveloppées dans les supports bouclés {{dynamic}} comme indiqué ici:
< my-counter >
< button onclick = {{dec}} > - </ button >
< span > {{state.count}} </ span >
< button onclick = {{inc}} > + </ button >
</ my-counter > Les références state , dec et inc seront transmises par le nœud de script, le cas échéant.
Chaque fois que le composant est rendu, son rappel de mise à jour est invoqué en fournissant l'élément lui-même comme contexte .
< button is =" my-button " >
I am a {{this.tagName}}
</ button >En ce qui concerne Shadowdom , son polyfill n'est pas inclus dans ce projet, mais il est possible de définir un composant à travers sa racine d'ombre en ajoutant un attribut d'ombre :
< my-counter shadow >
<!-- this content will be in the shadowRoot -->
< button onclick = {{dec}} > - </ button >
< span > {{state.count}} </ span >
< button onclick = {{inc}} > + </ button >
</ my-counter > L'attribut shadow est open par défaut, mais il peut également être spécifié sous forme shadow=closed .
En ce qui concerne {{JS}} , si l'attribut, et vous souhaitez utiliser des espaces {{ JS }} autour, l'attribut doit être en citations, sinon le modèle HTML rompt la mise en page de manière inattendue.
<!-- OK -->
< my-counter >
< button onClick = {{dec}} > - </ button >
</ my-counter >
<!-- OK -->
< my-counter >
< button onClick =" {{ dec }} " > - </ button >
</ my-counter >
<!-- IT BREAKS!!! -->
< my-counter >
< button onClick = {{ dec }} > - </ button >
</ my-counter ><!--{{interpolation}}--> casComme tout ici est principalement basé sur un comportement HTML standard, il y a des cas où une interpolation doit être enveloppée comme commentaire.
La règle de base est que si vous ne voyez pas la mise en page ou que vous lisez une mauvaise erreur de modèle , il est possible que votre interpolation ait été avalée par l'élément de modèle .
Cela se produit principalement avec des éléments tels que la table , la sélection et d'autres éléments qui n'acceptent qu'un type spécifique de nœud enfant, mais pas du texte.
<!-- ? this won't work as expected -->
< table is =" my-table " >
< tbody > {{rows}} </ tbody >
</ table >
<!-- ? this works ? -->
< table is =" my-table " >
< tbody > <!--{{rows}}--> </ tbody >
</ table > Dans le premier cas, le <tbody> ignorerait tout nœud qui n'est pas un <tr> sauf pour les commentaires , car les commentaires ne sont pas avalés ou perdus dans le processus.
Vous pouvez voir la définition de fichier dbmonster.html pour le composant <tr> ballaire <table> et personnalisé.
Un composant peut contenir un ou plusieurs styles, dans une portée spécifique:
<style> générique appliquera son contenu à l'échelle mondiale, utile pour s'adresser à my-counter + my-counter {...} , à titre d'exemple<style scoped> appliquera son contenu préfixé avec le nom de l'élément personnalisé (c'est-à my-counter span, my-counter button {...} )<style shadow> appliquera son contenu au-dessus du Shadowroot , en supposant que le composant est défini avec un attribut shadow Il n'y a rien de spécial à considérer ici, sauf que les styles globaux peuvent interférer avec IE11 s'ils sont trop envahissants, car une fois de plus, IE11 ne comprend pas le but et le comportement de l'élément <template> .
Une définition ne peut contenir qu'une seule balise de script , et ce script sera pratiquement géré comme un module .
Étant donné que IE11 n'est pas compatible avec les éléments <template> , si le type n'est pas spécifié, IE11 essaiera d'évaluer tous les scripts de la page à droite.
En conséquence, l'attribut type peut vraiment avoir n'importe quelle valeur, car il est complètement hors de propos pour cette bibliothèque, mais une telle valeur ne doit pas être compatible IE11, et module n'est qu'une valeur que IE11 ignorerait.
Le script peut contenir une default export , ou même un module.exports = ... , où une telle exportation peut avoir une méthode setup(element) { ... } qui renvoie ce que les parties dynamiques du composant attendent:
< script type =" module " >
import { reactive } from '@uce' ;
export default {
setup ( element ) {
const state = reactive ( { count : 0 } ) ;
const inc = ( ) => { state . count ++ } ;
const dec = ( ) => { state . count -- } ;
return { state , inc , dec } ;
}
} ;
</ script > L'assistance réactive @uce permet de mettre à jour automatiquement la vue chaque fois que l'une de ses propriétés change.
Pour en savoir plus sur les modifications réactives, veuillez lire ce post moyen.
setup Si une <script type="module" setup> est trouvée, le contenu du script est invoqué avec l'élément lui-même comme contexte.
Démo en direct
< x-clock > </ x-clock >
< template is =" uce-template " >
< x-clock > {{time}} </ x-clock >
< script type =" module " setup >
let id = 0 ;
export default {
get time ( ) {
return ( new Date ) . toISOString ( ) ;
}
} ;
this . connected = e => id = setInterval ( this . render , 1000 / 30 ) ;
this . disconnected = e => clearInterval ( id ) ;
</ script >
</ template > Ce raccourci est particulièrement pratique pour les composants qui n'ont pas besoin de configurer observédAttributes mais qui pourraient avoir besoin de configurer des accessoires , et pour ce dernier cas, l'attribut setup doit contenir props .
< script type =" module " setup =" props " >
// props are defined as key => defaultValue pairs
export const props = {
name : this . name || 'anonymous' ,
age : + this . age || 0
} ;
</ script > Cet objectif de section est de présenter des exemples de base à des exemples complexes via UCE-Template , où un exemple peut utiliser l'extension .uce pour limiter les composants dans leurs propres fichiers.
.uce Si vous utilisez VS Code, vous pouvez Ctrl + Shift + P , taper les paramètres JSON , choisir les paramètres ouvrir (JSON) et ajouter ce qui suit à un tel fichier afin de mettre en surbrillance les fichiers .uce
{
"other-settings" : "..." ,
"files.associations" : {
"*.uce" : "html"
}
} Si nous définissons les composants comme view/my-component.uce
Cette approche simplifie beaucoup de faisceaux, de dépendances, de ballonnements inutiles, et il peut être fait en incluant juste uce-template et le Tiny (364 octets) Uce-chargedeur comme bootstrap, définissant finalement des dépendances supplémentaires utilisées entre les composants.
import { parse , resolve } from 'uce-template' ;
import loader from 'uce-loader' ;
// optional components dependencies
import something from 'cool' ;
resolve ( 'cool' , something ) ;
// bootstrap the loader
loader ( {
on ( component ) {
// ignore uce-template itself
if ( component !== 'uce-template' )
fetch ( `view/ ${ component } .uce` )
. then ( body => body . text ( ) )
. then ( definition => {
document . body . appendChild (
parse ( definition )
) ;
} ) ;
}
} ) ;La même technique peut être utilisée directement sur n'importe quelle page HTML , écrivant un code qui pourrait également être compatible avec IE11 .
<!doctype html >
< html >
< head >
< script defer src =" //unpkg.com/uce-template " > </ script >
< script defer src =" //unpkg.com/uce-loader " > </ script >
< script defer >
addEventListener (
'DOMContentLoaded' ,
function ( ) {
uceLoader ( {
Template : customElements . get ( 'uce-template' ) ,
on : function ( name ) {
if ( name !== 'uce-template' ) {
var xhr = new XMLHttpRequest ;
var Template = this . Template ;
xhr . open ( 'get' , name + '.uce' , true ) ;
xhr . send ( null ) ;
xhr . onload = function ( ) {
document . body . appendChild (
Template . from ( xhr . responseText )
) ;
} ;
}
}
} ) ;
} ,
{ once : true }
) ;
</ script >
</ head >
< body >
< my-component >
< p slot =" content " >
Some content to show in < code > my-component </ code >
</ p >
</ my-component >
</ body >
</ html >uce-template chargé paresseuxSi la majorité de nos pages n'utilisent pas du tout des composants, l'ajout de 7k + de JS en haut de chaque page pourrait être indésirable.
Cependant, nous pouvons suivre la même approche de composants chargés de la même faille , sauf que notre chargeur sera chargé de proposer également la bibliothèque de terminale UCE , soit lorsqu'un modèle UCE lui-même est trouvé, soit tout autre composant.
import loader from 'uce-loader' ;
loader ( {
on ( component ) {
// first component found, load uce-template
if ( ! this . q ) {
this . q = [ component ] ;
const script = document . createElement ( 'script' ) ;
script . src = '//unpkg.com/uce-template' ;
document . body . appendChild ( script ) . onload = ( ) => {
// get the uce-template class to use its .from(...)
this . Template = customElements . get ( 'uce-template' ) ;
// load all queued components
for ( var q = this . q . splice ( 0 ) , i = 0 ; i < q . length ; i ++ )
this . on ( q [ i ] ) ;
} ;
}
// when uce-template is loaded
else if ( this . Template ) {
// ignore loading uce-template itself
if ( component !== 'uce-template' ) {
// load the component on demand
fetch ( `view/ ${ component } .uce` )
. then ( body => body . text ( ) )
. then ( definition => {
document . body . appendChild (
this . Template . from ( definition )
) ;
} ) ;
}
}
// if uce-template is not loaded yet
// add the component to the queue
else
this . q . push ( component ) ;
}
} ) ;En utilisant cette technique, notre charge utile JS par page serait désormais réduite à moins de 0,5k une fois ci-dessus, le code sera groupé et minifié, tandis que tout le reste ne se produira automatiquement que s'il y a des composants quelque part dans la page.
Comme la page peut contenir d'autres éléments personnalisés du tiers et des bibliothèques, il pourrait être une bonne idée de prédéfinir un ensemble bien connu de composants attendus, comme pour essayer de charger tous les éléments personnalisés possibles via la view/${...}.uce .
Les techniques de chargement paresseuses précédentes fonctionneraient déjà très bien, mais au lieu de vérifier que le nom du composant n'est pas uce-template , nous pourrions utiliser un ensemble :
loader ( {
known : new Set ( [ 'some-comp' , 'some-other' ] ) ,
on ( component ) {
if ( this . known . has ( component ) )
fetch ( `view/ ${ component } .uce` )
. then ( body => body . text ( ) )
. then ( definition => {
document . body . appendChild (
parse ( definition )
) ;
} ) ;
}
} ) ; L'avantage de cette technique est que l' ensemble known pourrait être généré dynamiquement via la liste des view/*.uce afin que rien ne se casse si le composant trouvé ne fait pas partie de la famille Uce-Template .
uce-template doit inévitablement utiliser Function pour évaluer les partiels des modèles ou les besoins en script (...) .
Il est recommandé d'augmenter la sécurité en utilisant soit le nonce ijeLM8+5uwZ7ZXFmK+H2dwIWdiKJ1A4zhZIsq2Ffqqo= ou l'attribut d'intégrité , en faisant confiance via CSP uniquement des scripts provenant de notre propre domaine.
< meta http-equiv =" Content-Security-Policy " content =" script-src 'self' 'unsafe-eval' " >
< script defer src =" /js/uce-template.js "
integrity =" sha256-ijeLM8+5uwZ7ZXFmK+H2dwIWdiKJ1A4zhZIsq2Ffqqo= "
crossorigin =" anonymous " >
</ script >Veuillez noter que ces valeurs changent à chaque version , assurez-vous d'avoir la dernière version (ce ReadMe reflète le dernier).
Comme pour UCE, si la définition contient des méthodes onEvent(){...} , celles-ci seront utilisées pour définir le composant.
Cependant, comme les états sont généralement découplés du composant lui-même, c'est une bonne idée d'utiliser un faiblemap faible pour relier n'importe quel composant avec son état et ... ne vous inquiétez pas, le faiblemap est également soutenu dans IE11 !
Démo en direct
< button is =" my-btn " >
Clicked {{times}} times!
</ button >
< script type =" module " >
const states = new WeakMap ;
export default {
setup ( element ) {
const state = { times : 0 } ;
states . set ( element , state ) ;
return state ;
} ,
onClick ( ) {
states . get ( this ) . times ++ ;
// update the current view if the
// state is not reactive
this . render ( ) ;
}
} ;
</ script >Veuillez noter que cet exemple couvre tout cas d'utilisation de l'état vs, car l'utilisation du faiblemap est une recommandation.
Si l'objet props est défini et que les accessoires * mettent à jour la vue automatiquement une fois, nous pourrions ne pas avoir besoin d'un faiblemap pour relier l'état du composant.
Démo en direct
< button is =" my-btn " > </ button >
< template is =" uce-template " >
< button is =" my-btn " >
Clicked {{this.times}} times!
</ button >
< script type =" module " >
export default {
props : { times : 0 } ,
onClick ( ) {
this . times ++ ;
}
} ;
</ script >
</ template > L'avantage de l'utilisation d'accessoires est qu'il est possible de définir un état initial via des attributs, ou via le réglage direct lorsqu'il est rendu via l'utilitaire html , de sorte qu'avoir un bouton avec times="3" , par exemple, serait rendu affichant 3 fois! tout de suite.
< button is =" my-btn " times =" 3 " > </ button > L'attribution import {ref} from '@uce' simplifie la récupération du nœud par l'attribut ref="name" .
< element-details >
< span ref =" name " > </ span >
< span ref =" description " > </ span >
</ element-details >
< template is =" uce-template " >
< element-details > </ element-details >
< script type =" module " setup >
import { ref } from '@uce' ;
const { name , description } = ref ( this ) ;
name . textContent = 'element name' ;
description . textContent = 'element description' ;
</ script >
</ template > L'assistance import {slot} from '@uce' simplifie la récupération des emplacements par son nom, renvoyant un tableau d'éléments regroupés via le même nom.
Cela peut être utilisé soit pour placer des emplacements uniques dans les interpolations, comme le montre cet exemple, soit pour placer plusieurs emplacements dans le même nœud.
Démo en direct
< filter-list >
Loading filter ...
< ul >
< li slot =" list " > some </ li >
< li slot =" list " > searchable </ li >
< li slot =" list " > text </ li >
</ ul >
</ filter-list >
< template is =" uce-template " >
< filter-list >
< div >
< input placeholder = filter oninput = {{filter}} >
</ div >
< ul >
{{list}}
</ ul >
</ filter-list >
< script type =" module " >
import { slot } from '@uce' ;
export default {
setup ( element ) {
const list = slot ( element ) . list || [ ] ;
return {
list ,
filter ( { currentTarget : { value } } ) {
for ( const li of list )
li . style . display =
li . textContent . includes ( value ) ? null : 'none' ;
}
} ;
}
} ;
</ script >
</ template >Cependant , dans les cas où l'ordre des emplacements de même nom n'est pas nécessairement visualisé séquentiellement, il est toujours possible de passer un tableau de nœuds à la place.
Autrement dit, toute valeur d'interpolation peut être un nœud DOM, une valeur ou un tableau de nœuds, la même manière que µhtml fonctionne.
Démo en direct
< howto-tabs >
< p > Loading tabs ... </ p >
< howto-tab role =" heading " slot =" tab " > Tab 1 </ howto-tab >
< howto-panel role =" region " slot =" panel " > Content 1 </ howto-panel >
< howto-tab role =" heading " slot =" tab " > Tab 2 </ howto-tab >
< howto-panel role =" region " slot =" panel " > Content 2 </ howto-panel >
</ howto-tabs >
< template is =" uce-template " >
< howto-tabs >
{{tabs}}
</ howto-tabs >
< script type =" module " >
import { slot } from '@uce' ;
export default {
setup ( element ) {
const { tab , panel } = slot ( element ) ;
const tabs = tab . reduce (
( tabs , tab , i ) => tabs . concat ( tab , panel [ i ] ) ,
[ ]
) ;
return { tabs } ;
}
} ;
</ script >
</ template > Le système de module fourni par UCE-Template est extrêmement simple et entièrement extensible, de sorte que chaque composant peut import any from 'thing'; Tant que thing a été fournie / résolue via la bibliothèque.
Si nous voulons définir un seul point d'entrée de bundle et que nous savons que chaque composant aurait besoin d'une ou plusieurs dépendances, nous pouvons effectuer ce qui suit:
import { resolve } from 'uce-template' ;
import moduleA from '3rd-party' ;
const moduleB = { any : 'value' } ;
resolve ( 'module-a' , moduleA ) ;
resolve ( 'module-b' , moduleB ) ;Une fois que cette construction a atterri en tant que point d'entrée de page Web unique, tous les composants pourraient importer tout de suite tous les modules de base / par défaut, ainsi que tous ceux pré-résolus.
Démo en direct (voir HTML et JS Panel + Console)
< my-comp > </ my-comp >
< script type =" module " >
import moduleA from 'module-a' ;
import moduleB from 'module-a' ;
export default {
setup ( ) {
console . log ( moduleA , moduleB ) ;
}
}
</ script > Dans le cas où le composant défini importe quelque chose à partir d'un fichier externe, comme import module from './js/module.js' ferait, une telle importation serait résolue paresseusement, avec tout autre module qui n'est pas encore connu, ce qui signifie que le fichier ./js/module.js pourrait contenir quelque chose comme celle-ci:
// a file used to bootstrap uce-template component
// dependencies can always use the uce-template class
const { resolve } = customElements . get ( 'uce-template' ) ;
// resolve one to many modules
resolve ( 'quite-big-module' , { ... } ) ;Un script de composant peut ensuite importer ce fichier et accéder à ses modules exportés juste après.
Démo en direct
< script type =" module " >
import './js/module.js' ;
import quiteBigModule from 'quite-big-module' ;
export default {
setup ( ) {
console . log ( quiteBigModule ) ;
}
}
</ script > Avec le composant chargé paresseux , cette approche permet d'expédier des composants qui sont entièrement basés sur une définition de fichier vue/comp.uce externe, où l'un de ces composants peut également partager un ou plusieurs fichiers .js capables de résoudre tous les modules nécessaires ici ou là-bas (dépendances partagées dans un fichier, en face des dépendances pour chaque composant décortiqué).
En tant que fichier autonome, ma taille d'éléments personnalisés est d'environ 2,1k , mais comme il est partagé presque toutes les bibliothèques que Uce utilise également, l'aggraver ressemblait à la meilleure façon de procéder, ce qui n'a cessé de 1 km supplémentaire pour un module qui s'adapte à environ 7k à 10k .
D'un autre côté, parce que le polyfill n'est pas envahissant et en fonction des détections de fonctionnalités d'exécution, cela signifie que personne ne devrait se soucier d'apporter un autre polyfill, mais aussi Chrome , Firefox et Edge , ne seront pas touchés, de sorte que chaque élément personnalisé fonctionnera nativement, étend intégré ou régulier.
Dans le cas de safari , ou basé sur WebKit , seuls des éléments personnalisés intégrés sont fournis, tandis que dans IE11 et l'ancien MS Edge , les étendus intégrés et les éléments réguliers sont corrigés.
C'est tout: ne vous inquiétez pas pour un polyfill, car tout est déjà inclus ici!
Si vous ciblez les navigateurs que vous connaissez déjà fournir des éléments personnalisés natifs V1, vous pouvez utiliser cette version ESM qui exclut tous les polyfills et inclure uniquement la logique.
Le bundle es.js actuel est en effet ~ 7k gzipped et ~ 6,5k brotli, de sorte qu'il est possible d'économiser une bande passante supplémentaire dans votre projet.
Eh bien, dans un tel cas, si c'est le seul navigateur cible, le module @ webreflection / personnalisé-éléments-builtin doit être inclus avant que le module UCE-Template atterrit sur la page.
< script defer src =" //unpkg.com/@webreflection/custom-elements-builtin " > </ script >
< script defer src =" //unpkg.com/uce-template " > </ script >Cela garantira que les étendues régulières et intégrées fonctionneront comme prévu.
Malheureusement, Shadowdom est l'une de ces spécifications impossible à polyfill, mais la bonne nouvelle est que vous aurez rarement besoin de Shadowdom dans UCE-Template , mais si votre navigateur est compatible, vous pouvez utiliser Shadowdom autant que vous le souhaitez.
Cependant , il y a au moins deux polyfills partiels possibles à considérer: PixShadow, qui est minimaliste et léger, et Shadydom, qui est plus proche des normes, mais définitivement plus lourde, bien que les deux polyfills puissent, et devraient être injectés uniquement si le navigateur actuel en a besoin, donc coller ce code au-dessus de votre page HTML apporterait un fantôme en IE11, ou d'autres.
<!-- this must be done before uce-template -->
< script >
if ( ! document . documentElement . attachShadow )
document . write ( '<script src="//unpkg.com/attachshadow"><x2fscript>' ) ;
</ script >
< script defer src =" //unpkg.com/uce-template " > </ script > Comme chaque navigateur moderne aura document.documentElement.attachShadow , le document.write ne se produira que dans IE11 sans jamais compromettre ou pénaliser les navigateurs de bureau mobiles et modernes.
Ps le <x2fscript> n'est pas une faute de frappe, il est nécessaire de ne pas avoir une étiquette de script de clôture de mise en page cassée
{{...}} au lieu de ${...} ? Autant que j'aurais aimé avoir des limites d'interpolation ${...} , IE11 se casserait si un élément du DOM contient ${...} comme attribut.
Parce que {{...}} est une alternative bien établie, j'ai décidé d'éviter les problèmes de prise de singe possibles et de respecter simplement une alternative standard de facto.
Il convient également de considérer que Vue utilise également {{...}} , et donc de nombreux autres moteurs basés sur des modèles.
Function est-elle nécessaire? Comme expliqué dans la partie " CSP & Integrity / Nonce " des exemples comment to /, il est nécessaire d'utiliser Function pour au moins deux raisons:
"use strict"; directive et passer par une instruction with(object) , nécessaire pour comprendre les interpolations sans créer un moteur JS entier à partir de zérorequire des fonctionnalités dans <script type="module"> Contenu Mais même s'il n'y avait pas Function dans l'équation, l'analyse et l'exécution d'une balise <script> pour définir des éléments personnalisés auraient été exactement le même équivalent de Function , car CSP aurait de toute façon eu besoin de règles spéciales, car l'opération est essentiellement un appel d' évaluation dans le contexte global.
Comme résumé, au lieu de tromper le navigateur avec des pratiques aussi sûres ou aussi dangereuses, en tant qu'appel de Function , j'ai simplement utilisé Function à la place, en gardant la taille du code raisonnable.
Ce projet est en tant qu'éléments personnalisés natifs comme indigènes, à l'exception du coût de définition, qui est une opération unique pour chaque classe d'élément personnalisée unique, donc sans importance à long terme, et il y a une surcharge insignifiante dans le modèle initial de l'analyse de la logique, mais son exécution répétée est aussi rapide que UHTML peut être, et si vous vérifiez le dernier statut que vous trouverez qu'il s'agit de l'une du Fast le plus rapide de son genre.
Vous pouvez consulter la démo DBMonster classique ici et voir qu'elle fonctionne bien.
Rien dans cette bibliothèque ne bloque et les modules sont résolus une seule fois, même les importations de chemin relatives.
La logique est assez simple: si le nom du module n'a pas été résolu et c'est une importation relative, une demande asynchrone sera faite et évaluée plus tard, tandis que si le module n'est pas résolu, et c'est un nom qualifié, il ne sera résolu qu'une fois qu'un code le fournit.
Tout cela, en plus de l' importation , nécessitant une résolution, est géré par l'assistance UCE-Requeve, délibérément non couplé à ce module lui-même, car il pourrait également inspirer et être utilisé par d'autres projets.
Si vous souhaitez en savoir plus sur uce-template et comment cela fonctionne, veuillez consulter cette page.