Migration
Venir de Form.io
Migrer un portefeuille de formulaires est en général la raison pour laquelle on
repousse une migration d’un an. convertFormioForm existe pour la rendre
incrémentale : il convertit ce qu’il peut, signale ce qu’il ne peut pas, et ne
lève jamais d’exception — vous pouvez donc le passer sur une centaine de
formulaires et obtenir une liste de tâches plutôt qu’une stack trace.
Convertir une définition
Section intitulée « Convertir une définition »-
Donnez-lui une définition de formulaire Form.io.
migrate.ts import { convertFormioForm } from '@streamline-pulse/formkrafter-core'const formioJson = JSON.parse(await readFile('./legacy-form.json', 'utf8'))const { spec, warnings } = convertFormioForm(formioJson) -
Passez les avertissements en revue. Les composants inconnus sont ignorés et listés ici plutôt que d’interrompre la conversion.
for (const warning of warnings) console.warn(warning)// ex. 'button "submit" skipped — FormKrafter renders its own submit action' -
Stockez le spec obtenu, ou ouvrez-le dans le builder pour une passe manuelle.
Ce qui est mappé
Section intitulée « Ce qui est mappé »| Form.io | FormKrafter |
|---|---|
| Composants de champ (textfield, email, number, day, select, radio, selectboxes, checkbox, textarea, phone, url, signature, address, …) | Les bricks de saisie correspondantes, inputMask compris |
| Layout : panels, columns, tables, tabs, fieldsets | Bricks de layout |
Wizard (display: "wizard") |
stepper avec validation par étape |
| datagrid / editgrid | data-grid avec validation par ligne |
validate.* (required, min/max, longueurs, pattern, JS personnalisé) |
Validateurs ; le JS personnalisé est automatiquement enveloppé pour le bac à sable (data/row deviennent dataMap) |
conditional (show/when/eq) et déclencheurs logic JavaScript |
Règles ; un conditional prend le pas sur un drapeau toujours caché |
Select dataSrc: url / json |
Options distantes ou statiques (valueProperty → valueKey, gabarits d’item → labelKey, chemins pointés supportés). Les listes de simples chaînes ou nombres deviennent des paires libellé/valeur identiques |
Composants de fichier (storage: url, multiple) |
Brick file avec les configs uploadUrl / multiple |
Composants form imbriqués |
Bricks nested-form avec specRef |
| Composants Content / HTML | Bricks content, conditionals préservés |
Le convertisseur est testé en régression contre de vrais formulaires Form.io de production — wizards, uploads de fichiers conditionnels, selects en cascade et validateurs personnalisés.
Ce que vous gagnez en poids
Section intitulée « Ce que vous gagnez en poids »Méthodologie : octets gzippés qu’une page télécharge réellement. FormKrafter
v0.16.0 mesuré sous Chromium headless contre le bundle publié à chargement
paresseux, JS et CSS confondus ; Form.io @formio/js v5.5.0 mesuré depuis ses
bundles CDN officiels (juillet 2026).
| FormKrafter | Form.io | |
|---|---|---|
| Builder (renderer inclus) | ~130 Ko | ~470 Ko (formio.full.min.js) |
| Renderer seul | ~130 Ko | ~415 Ko (formio.form.min.js) |
| CSS nécessaire | 1,6 Ko, optionnel | 129 Ko + Bootstrap |
Les deux lignes FormKrafter sont identiques à dessein : le bundle à chargement paresseux répartit ses composants en chunks partagés, si bien qu’une page qui ne fait que rendre télécharge le même ensemble qu’une page portant le builder. Ce qui reste dehors jusqu’à l’ouverture d’un éditeur de règles ou d’options JS, c’est l’éditeur de code — une centaine de Ko gzippés à lui seul.
Ce que vous gagnez à l’exécution
Section intitulée « Ce que vous gagnez à l’exécution »Le coût de rendu reste stable là où ça compte. Mesuré sur un vrai formulaire de production converti — un wizard de 5 étapes et 93 bricks (layouts imbriqués, uploads de fichiers, selects en cascade) — puis sur des variantes synthétiques montant jusqu’à 911 bricks sur une seule page. Méthodologie : build de production FormKrafter v0.6.0, Chromium headless via Playwright, médiane des exécutions à chaud ; la latence de frappe est mesurée de l’événement input au paint suivant, elle inclut donc jusqu’à deux frames d’ordonnancement.
| Bricks sur la page | Montage | validate() |
Latence de frappe (médiane / p90) |
|---|---|---|---|
| 92 (le vrai formulaire) | 17 ms | 0,6 ms | 14 ms / 33 ms |
| 456 | 29 ms | 1,0 ms | 14 ms / 29 ms |
| 911 | 45 ms | 1,9 ms | 26 ms / 33 ms |
Le chiffre à retenir est la dernière colonne : la latence de frappe ne croît pas avec la taille du formulaire — une frappe ne paie jamais pour les bricks qu’elle ne touche pas, et même une page de 911 bricks reste dans le budget de frame à 60 fps pendant la saisie.
Gardez vos specs légers
Section intitulée « Gardez vos specs légers »Vos définitions stockées maigrissent aussi. Les exports Form.io réels traînent un lourd boilerplate — chaque composant sérialisé avec toutes ses valeurs par défaut — là où le convertisseur ne garde que ce qui porte du sens et compacte les listes d’options statiques en une chaîne à sauts de ligne dès que les libellés valent les valeurs. Mesuré sur un portefeuille de six formulaires de production :
| JSON brut | Gzippé | |
|---|---|---|
| Définitions Form.io | 277 Ko | 40 Ko |
| Specs FormKrafter convertis | 66 Ko (3 à 5,5× plus petits par formulaire) | 18 Ko |
Pour les plus grosses listes — professions, nationalités — ne les embarquez pas du tout. Le convertisseur alerte au-delà de 100 options statiques et recommande :
{ "optionsSource": "remote", "optionsUrl": "/api/professions?q={search}" }Le select interroge votre API, avec la recherche au fil de la frappe.
{ "optionsSource": "catalog", "optionsRef": "professions" }Résolu via optionSourceService : la liste est stockée une
seule fois et référencée par tous les formulaires qui en ont besoin.
Le bac à sable plutôt qu’eval
Section intitulée « Le bac à sable plutôt qu’eval »Form.io exécute les validateurs personnalisés et la logique avec du vrai
JavaScript. FormKrafter fait tourner le code converti dans un interpréteur d’AST
compatible CSP — voir règles dynamiques. Les
extraits convertis continuent de fonctionner parce que le convertisseur injecte
des alias de compatibilité (const data = dataMap; const row = dataMap;), et ils
gagnent gratuitement l’isolation du bac à sable.
Étapes suivantes
Section intitulée « Étapes suivantes »Un projet de Streamline Pulse