Résolution des composants
Une balise capitalisée sans liaison dans la portée est un nom que le compilateur peut
résoudre. Indiquez-lui une fois où se trouve Button, et tous les templates peuvent
utiliser <Button> sans import.
// Aucun import dans ce fichier.
export function Toolbar() {
return (
<Stack gap="3">
<Button>Enregistrer</Button>
</Stack>
);
}
Ce n'est pas de l'auto-import au sens de l'éditeur : rien n'est écrit dans votre source. Le compilateur injecte l'import à la compilation, donc la sortie est exactement ce que vous auriez écrit à la main, et le bundler voit un import statique ordinaire.
Fluixi le faisait déjà pour Show, For, Portal et les composants du routeur.
resolve est le même mécanisme, ouvert.
Configuration
Les règles vivent sur le plugin, car l'origine d'un composant est la même partout dans un projet :
// vite.config.ts
import { fluixi } from '@fluixi/vite-plugin';
export default defineConfig({
plugins: [
fluixi({
resolve: [
{ components: { Button: '@ui/button', Stack: '@ui/layout' } },
],
}),
],
});
Une bibliothèque de composants fournit sa propre carte, l'adoption tient donc en une ligne :
import { uiComponents } from '@fluixi-ui/resolver';
fluixi({ resolve: [uiComponents()] });
Quand la balise et l'export diffèrent
resolve: [
{ components: { Btn: { module: '@ui/button', export: 'Button' } } },
// `export: 'default'` pour une organisation un fichier par composant
{ components: { Card: { module: './Card.js', export: 'default' } } },
];
Motifs
Une seule règle peut couvrir toute une famille. $1 et les suivants sont substitués
depuis la correspondance :
resolve: [{ match: /^Icon(.+)$/, module: '@/icons/$1' }];
<IconTrash> se résout vers @/icons/Trash. Attention à la limite décrite plus bas : les
motifs ne peuvent pas être déclarés pour TypeScript.
Un import l'emporte toujours
Écrire l'import vous-même masque la règle. La résolution ne complète que les noms sans liaison dans la portée : il n'y a donc jamais de conflit à arbitrer, et sortir un composant de la configuration reste sans danger.
Le dire à TypeScript
L'import n'existe qu'après compilation : sans aide, TypeScript signale
Cannot find name 'Button' pour chaque balise résolue — le code s'exécute, l'éditeur est
inutilisable.
Le plugin génère les déclarations pour vous. Au démarrage du serveur de développement et à
la compilation, il écrit fluixi.d.ts à la racine du projet :
// GENERATED by @fluixi/compiler — do not edit.
import * as __ui_button from '@ui/button';
declare global {
export import Button = __ui_button.Button;
}
Versionnez ce fichier. C'est lui qui permet à un clone neuf de passer le typage avant que quiconque ait lancé le serveur de développement, et à un job CI qui vérifie les types sans compiler de fonctionner.
Il doit être couvert par include dans tsconfig.json, ce qui, pour l'emplacement par
défaut, signifie le nommer à côté de src :
{ "include": ["src", "fluixi.d.ts"] }
Les projets créés par l'outil de scaffolding ont déjà cette ligne. Si le fichier atterrit là où TypeScript ne le lira pas, le plugin le signale pendant la compilation : un fichier ignoré et un fichier absent produisent des erreurs identiques, autant savoir lequel vous avez.
Placez-le ailleurs, ou désactivez-le, avec globals :
fluixi({ resolve: [...], globals: 'types/fluixi.d.ts' });
fluixi({ resolve: [...], globals: false });
Ce que le fichier généré laisse de côté
- Les noms que
lib.domrevendique déjà. Unconst Textambiant ne peut pas l'emporter sur leTextdu DOM : ceux-là sont écartés et listés dans l'en-tête, importez-les explicitement. - Les composants de paquets dont vous ne dépendez pas. Les déclarer produit un import
irrésoluble qui, sous
skipLibCheck, échoue en silence et dégrade le composant enany— pire que l'erreur qu'il remplace. - Les règles à motif. Un motif correspond à une infinité de noms : il n'y a pas de liste à émettre. Ces balises compilent, mais demandent une déclaration écrite à la main pour l'éditeur.
Dans l'éditeur
@fluixi/ts-plugin résout les mêmes noms : survol, aller à la définition et renommage
fonctionnent sur une balise résolue comme sur une balise importée — y compris dans les
templates html ``, où la balise n'est que du texte pour TypeScript.
Comme les déclarations utilisent un alias (export import Button = …) plutôt qu'une
constante typée, le survol conserve la vraie signature et sa JSDoc, et l'aller à la
définition atterrit sur la source du composant plutôt que sur le fichier généré.