Bibliothèques de composants partagées : les stratégies qui existent quand on a 300 projets
Guide complet et sourcé des approches de partage de composants UI entre projets : paquets npm, monorepo, registre shadcn, Module Federation, Bit, Web Components, avec focus sur la propagation des correctifs et la gestion des évolutions à l'échelle.
Cet article fait suite à shadcn/ui : la bibliothèque de composants qui n’en est pas une. L’article précédent détaillait le modèle de distribution de code de shadcn ; celui-ci élargit la perspective à toutes les stratégies de partage de composants entre projets.
Tu as un design system. Des composants métier — réservation, recherche, formulaires. Des briques UI de base — boutons, modales, tableaux. Et tu as 300 projets qui implémentent chacun leur version de ces composants. La tentation est forte de mutualiser. La question est : comment ?
Il n’existe pas de réponse unique. Chaque approche fait un compromis différent entre contrôle (le consommateur décide quand et quoi mettre à jour) et cohérence (tous les projets reflètent la même version). Ce curseur détermine tout le reste : la facilité de propagation des correctifs, le risque d’introduire des régressions, et le coût de maintenance à l’échelle.
Cet article passe en revue six stratégies concrètes, avec pour chacune les mécanismes de propagation, les limites à l’échelle, et les spécificités React (composants clients) vs Astro (composants serveurs).
1. Le spectre contrôle-cohérence
Avant de comparer les outils, il faut comprendre l’axe fondamental qui les différencie :
Contrôle maximal Cohérence maximale
du consommateur de l'écosystème
│ │
▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ Code │ │ Git │ │ Paquets │ │ Monorepo │ │ Module │
│ copié │ │ submodule│ │ npm │ │ interne │ │ Federat. │
│ (shadcn) │ │ │ │ │ │ │ │ / CDN │
└──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘
À gauche, le consommateur possède le code et décide de tout. À droite, le producteur déploie et tous les consommateurs reçoivent la mise à jour instantanément.
Chaque cran vers la droite améliore la propagation des correctifs mais augmente le risque de casser 300 projets d’un coup.
2. Paquets npm sur registre privé
Le principe
Les composants sont compilés, empaquetés et publiés comme des paquets npm classiques (typiquement sous un scope @org/button, @org/dialog). Les consommateurs les installent via npm install et les importent comme n’importe quelle dépendance.
Registres disponibles
| Registre | Type | Particularité |
|---|---|---|
| npm (npmjs.com) | SaaS | Référence. Trusted publishing via OIDC depuis CI |
| GitHub Packages | SaaS | Intégré à GitHub Actions, auth via GITHUB_TOKEN |
| Verdaccio | Self-hosted | Open source, léger, proxy npm configurable |
| JFrog Artifactory | Enterprise | Multi-format, RBAC, politiques de sécurité |
Source : npm Docs, Verdaccio, GitHub Packages
Versionnage
Le standard est semver (MAJOR.MINOR.PATCH). L’outil Changesets est devenu la référence pour automatiser le workflow de publication en monorepo :
- Les contributeurs déclarent l’impact de leurs changements (major/minor/patch) via des fichiers changeset
- La CI agrège les changesets en bumps de version et génère un
CHANGELOG.md - Une GitHub Action crée des “versioning PRs” qui regroupent tous les changesets en attente
- Le publish supporte le trusted publishing OIDC (pas de tokens stockés)
Source : Changesets — GitHub
Propagation des correctifs
Les consommateurs doivent explicitement mettre à jour leur dépendance. À l’échelle de 300 projets, les organisations utilisent :
- Renovate Bot ou Dependabot pour créer automatiquement des PR de mise à jour dans chaque projet consommateur
- Les ranges semver (
^1.2.3) pour recevoir automatiquement les patchs et mineurs - Des codemods (via jscodeshift ou codemod.com) pour automatiser les migrations d’API lors des changements majeurs
Source : Automating code changes for 100+ repositories — GitNation
Évolutions et risques
Un bump majeur crée une longue traîne de migration : sur 300 consommateurs, certains resteront sur l’ancienne version pendant des mois, voire indéfiniment. C’est à la fois un avantage (pas de casse immédiate) et un problème (fragmentation).
React vs Astro
Les composants React se distribuent via npm sans problème — c’est du JS/TS standard. Les composants Astro (fichiers .astro) sont plus problématiques : ce sont des templates serveur qui dépendent du compilateur Astro, pas des modules JS standards. Astro recommande de distribuer des intégrations ou d’utiliser des composants de framework (React, Vue, Svelte) comme îlots, qui eux fonctionnent parfaitement en paquets npm.
Source : Astro Islands Architecture
À l’échelle
C’est l’approche la plus éprouvée. Atlassian publie chaque composant d’Atlaskit comme un paquet @atlaskit/* indépendant sur npm, consommé par des centaines de projets internes et externes.
Source : Atlaskit — Atlassian Frontend
En pratique, c’est le choix par défaut pour distribuer des composants à des consommateurs que l’on ne contrôle pas. Le modèle est compris de tous, les outils sont matures, et le versionnage sémantique donne un contrat explicite.
3. Monorepo avec paquets internes
Le principe
Le code des composants partagés vit dans un répertoire packages/ aux côtés des applications consommatrices dans un même dépôt. Les gestionnaires de paquets (pnpm, yarn, npm) fournissent le linking via les workspaces.
Deux patterns
Turborepo distingue deux types de paquets :
- Paquets internes : le code source est consommé directement sans compilation préalable. Référencé via le protocole
workspace:*. Le bundler de l’application consommatrice compile le paquet. Zéro configuration de build nécessaire. - Paquets publiables : le code est compilé avant publication sur npm. Nécessaire quand les consommateurs sont hors du monorepo.
Source : Turborepo — Internal Packages
Nx a des concepts analogues :
- Buildable libraries : pré-compilées pour les performances de build incrémental
- Publishable libraries : générées avec
--publishable --importPath=@myorg/lib, produisent des bundles prêts pour npm
Source : Nx — Publishable and Buildable Libraries
Propagation des correctifs
C’est le point fort du monorepo : au sein du dépôt, tous les consommateurs voient le code source à HEAD. Pas de bump de version, pas de publication. Un commit qui corrige un composant est immédiatement visible par toutes les applications.
Pour les consommateurs hors du monorepo, on retombe sur le workflow npm (section précédente).
Évolutions et risques
Au sein du monorepo, l’auteur d’un changement cassant est responsable de mettre à jour tous les consommateurs dans le même commit (changements atomiques). TypeScript détecte les erreurs de compilation immédiatement. La commande affected de Nx identifie les projets impactés.
C’est puissant, mais ça suppose que tous les consommateurs sont dans le même dépôt — ce qui est rarement le cas pour 300 projets.
React vs Astro
Les paquets internes fonctionnent bien pour les deux. Astro peut importer des composants React comme îlots. Les composants .astro peuvent être partagés comme paquets internes si tous les consommateurs utilisent Astro — le build Astro du consommateur gère la compilation. C’est l’une des rares approches où le partage de composants serveur .astro est simple.
Limites à l’échelle
On ne peut pas avoir 300 projets indépendants dans un seul monorepo sauf si tous sont possédés par la même organisation et les équipes acceptent le trunk-based development. Google le fait (2 milliards de lignes de code, 40 000 commits/jour) avec de l’outillage sur mesure (Piper, CitC, Rosie). Avec Turborepo ou Nx, les limites pratiques sont plus basses.
Source : Why Google Stores Billions of Lines of Code in a Single Repository — ACM
En pratique, le monorepo est idéal pour l’équipe qui produit la bibliothèque — développement, tests, CI intégrés. Mais la distribution aux 300 projets consommateurs passe quand même par npm.
4. Distribution de code source (modèle shadcn)
Le principe
Au lieu d’installer une dépendance, un CLI copie le code source des composants directement dans le projet consommateur. Le consommateur possède le code et peut le modifier librement. Ce modèle a été popularisé par shadcn/ui.
Pour les détails du fonctionnement interne — registre JSON, CLI, système de diff — voir l’article dédié à shadcn/ui.
Registre privé d’organisation
Le mécanisme de registre de shadcn est extensible. Une organisation peut créer son propre registre :
{
"$schema": "https://ui.shadcn.com/schema/registry.json",
"name": "my-company",
"homepage": "https://registry.company.com",
"items": [
{
"name": "booking-form",
"type": "registry:component",
"title": "Booking Form",
"description": "Formulaire de réservation standard",
"dependencies": ["@radix-ui/react-dialog", "date-fns"],
"files": [
{
"path": "registry/booking-form.tsx",
"type": "registry:component"
}
]
}
]
}
Les consommateurs installent via :
npx shadcn@latest add @mycompany/booking-form
L’authentification est configurable (Bearer token, API key, basic auth) dans le components.json du consommateur.
Source : shadcn Registry — Getting Started
Propagation des correctifs
C’est la faiblesse principale. Les correctifs ne se propagent pas automatiquement. Les options :
- Re-exécuter
npx shadcn add component --overwrite(écrase les modifications locales) - Utiliser
npx shadcn diffpour voir ce qui a changé et appliquer manuellement - Créer des wrappers au-dessus des composants shadcn non modifiés (stratégie proxy) pour pouvoir
--overwriteen toute sécurité
Il n’existe pas d’équivalent Dependabot/Renovate pour les composants distribués par registre.
Évolutions et risques
Puisque le consommateur possède le code, il n’y a pas de changement cassant au sens classique. La copie du consommateur est figée au moment de l’installation. C’est à la fois un avantage (aucune casse inattendue) et un inconvénient (aucune amélioration automatique).
Pour 300 projets, la propagation d’un correctif de sécurité ou d’accessibilité nécessite que chacun re-ajoute le composant manuellement — une opération qui ne passe pas à l’échelle.
React vs Astro
Le CLI v4 de shadcn (mars 2026) supporte nativement React et Astro. Le schéma de registre est agnostique du framework — les items spécifient leur type de fichier, et le CLI s’adapte au projet cible.
À l’échelle
La distribution scale à l’infini — c’est du HTTP servant des fichiers JSON. La propagation des mises à jour ne scale pas.
En pratique, ce modèle convient aux composants que les consommateurs vont fortement personnaliser — design system de base, composants UI fondamentaux. Il convient mal aux composants métier qui doivent se comporter de manière uniforme partout.
5. Git submodules et subtree
Le principe
Partager du code via les mécanismes natifs de Git : submodule (pointeur vers un commit d’un autre dépôt) ou subtree (fusion du code externe dans l’arborescence du consommateur).
Source : Git Subtree vs Submodule — Atlassian
Submodule vs Subtree
| Aspect | Submodule | Subtree |
|---|---|---|
| Stockage | Pointeur (SHA) vers un autre repo | Code copié dans l’arborescence |
| Clone | Nécessite --recurse-submodules | Transparent, code déjà là |
| CI/CD | Configuration supplémentaire nécessaire | Fonctionne nativement |
| Mise à jour | git submodule update --remote | git subtree pull |
| Contributions upstream | Commit dans le submodule, push | git subtree push (manuel) |
| Taille du repo | Légère (juste un pointeur) | Augmente (copie complète) |
Propagation des correctifs
Aucun automatisme. Chaque consommateur doit manuellement mettre à jour le SHA (submodule) ou puller les changements (subtree). Pas de concept de semver, pas de changelog, pas de contrat de compatibilité.
Évolutions et risques
Un git submodule update peut silencieusement introduire des changements cassants. Il n’existe aucun mécanisme d’avertissement ni outil de migration. C’est du “tout ou rien” — on met à jour au dernier commit ou on reste figé.
À l’échelle
Très mal adapté à 300 projets. Chaque consommateur gère indépendamment la relation submodule/subtree. Aucune visibilité centrale sur les versions utilisées. Les développeurs oublient régulièrement de mettre à jour les submodules, provoquant des désynchronisations silencieuses.
En pratique, les submodules sont un héritage des années où npm n’existait pas ou ne gérait pas les paquets privés. Pour le partage de composants frontend en 2026, il n’y a pas de raison de choisir cette approche.
6. Module Federation
Le principe
Module Federation permet à des applications compilées et déployées indépendamment de partager des modules au runtime via le réseau. Une application “remote” expose des composants ; une application “host” les consomme en chargeant des bundles JavaScript depuis l’URL du remote à l’exécution.
Module Federation 2.0, désormais stable (avril 2026), apporte un runtime découplé de Webpack qui fonctionne avec Webpack, Rspack, Vite et Rollup.
Source : Module Federation 2.0 Reaches Stable Release — InfoQ, module-federation.io
Fonctionnement
┌─────────────────────┐ ┌─────────────────────┐
│ App Host │ │ Remote "UI" │
│ │ HTTP │ │
│ import { Button } │◀────────│ expose: { │
│ from "ui/Button" │ runtime │ "./Button": ... │
│ │ │ } │
└─────────────────────┘ └─────────────────────┘
▲ │
│ Déployé │
│ indépendamment │
└───────────────────────────────┘
Support Vite actuel
@module-federation/vite: plugin officiel MF 2.0 pour Vite- Rspack (
rspack.rs) : support MF natif, compatible Webpack, basé sur Rust — bien plus rapide que Webpack
Source : Module Federation — Vite Plugin, Rspack — Module Federation
Propagation des correctifs
C’est la killer feature de Module Federation. Puisque les modules sont chargés au runtime depuis l’URL du remote, déployer un correctif sur le remote le propage instantanément à tous les consommateurs à leur prochain chargement de page. Aucun rebuild ni redéploiement côté consommateur.
Évolutions et risques
C’est aussi le plus gros danger. Les dépendances partagées doivent être compatibles en version. Si un remote modifie son API, les consommateurs cassent au runtime — pas au build. Les mitigations :
- URLs de remote versionnées (
https://cdn.example.com/ui/v2/remoteEntry.js) - Contract testing entre remotes et hosts
- Types TypeScript dynamiques via le mécanisme de “dynamic type hinting” de MF 2.0
- Module Federation 3.0 (2026) gère automatiquement la déduplication des dépendances au niveau du navigateur
Source : Solving Micro-Frontend Challenges with Module Federation — LogRocket
React vs Astro
- React (client) : c’est le cas d’usage principal de MF. Fonctionne parfaitement.
- Astro (serveur) : MF est fondamentalement un mécanisme runtime côté client (chargement de bundles JS dans le navigateur). Les composants
.astrorendus côté serveur ne peuvent pas être partagés via MF. Les îlots React dans Astro pourraient théoriquement consommer des modules fédérés, mais c’est un chemin peu exploré. - Server-Side MF (2025) : permet la fédération de React Server Components, où le serveur assemble du contenu rendu côté serveur depuis plusieurs remotes. C’est nouveau et en évolution.
À l’échelle
MF est conçu pour les architectures micro-frontends où les équipes déploient indépendamment. Il scale bien pour la composition runtime mais a une complexité opérationnelle importante :
- Chaque remote est un service déployé indépendamment (CI/CD, hébergement, monitoring propres)
- Latence réseau au chargement des modules distants
- Défaillances en cascade si un remote est indisponible
- La matrice de versions des dépendances partagées devient complexe
En pratique, MF est adapté aux grandes applications composées de “tranches” indépendantes (micro-frontends), pas à 300 sites web qui partagent un bouton. C’est une solution d’architecture, pas de distribution de bibliothèque.
7. Bit : le composant comme unité première
Le principe
Bit est une plateforme de développement où chaque composant est une unité indépendamment versionnée, compilée, testée et publiable. Contrairement aux outils de monorepo, Bit traite le composant — pas le paquet ni le dépôt — comme l’unité fondamentale.
Source : bit.dev
Concepts clés
- Workspace : environnement de développement local pour créer des composants
- Scope : serveur de collaboration distant (bit.cloud ou self-hosted) qui stocke et sert les composants
- Isolation : chaque composant a son propre graphe de dépendances, build isolé, tests isolés, rendu de documentation
- Versionnage : semver individuel par composant. Au tag, le composant est compilé, testé, et son graphe de dépendances verrouillé
Ripple CI : la propagation automatique
Le mécanisme distinctif de Bit est Ripple CI :
- Vous mettez à jour le composant A
- Ripple identifie automatiquement tous les composants et applications qui dépendent de A
- Il compile et teste chaque dépendant à travers tout le système
- La propagation est automatique — si A est utilisé par B, C et l’application D, tous sont reconstruits et vérifiés
- Fonctionne à travers les scopes (frontières organisationnelles)
Source : Bit — Ripple CI
Propagation des correctifs
- Dans l’écosystème Bit : Ripple CI propage automatiquement les builds aux dépendants. Les consommateurs avec des ranges semver reçoivent les mises à jour comme avec npm.
- Consommateurs externes : les composants sont publiés sur npm comme effet de bord du tag. Workflow npm standard.
Limites
- Vendor lock-in : le modèle mental est très différent de npm/git. L’adoption a un coût significatif.
- La communauté est plus petite que l’écosystème npm/Turborepo/Nx
- Pas de support Astro natif (React, Angular, Vue, Node uniquement)
- Pricing de bit.cloud à l’échelle enterprise
8. Web Components et distribution CDN : le modèle Shopify
Il existe une approche qui ne rentre pas exactement dans les catégories précédentes et qui mérite d’être mentionnée : la distribution via Web Components sur CDN.
L’exemple Polaris
Shopify a reconstruit son design system Polaris en 2025 : de React à des Web Components distribués via CDN.
<script src="https://cdn.shopify.com/shopifycloud/polaris.js"></script>
<!-- Utilisation directe dans n'importe quel framework -->
<polaris-button variant="primary">Réserver</polaris-button>
Source : Polaris Goes Stable — Shopify
Pourquoi c’est intéressant
- Agnostique du framework : fonctionne dans React, Astro, Vue, HTML statique — partout où il y a un navigateur
- Propagation instantanée : pas de version dans l’URL, toujours la dernière version. Tous les consommateurs reçoivent les correctifs immédiatement.
- Aucune installation : un tag
<script>suffit - Unifié : Admin, Checkout, POS, Customer Accounts utilisent les mêmes composants
Pourquoi c’est risqué
- Zéro contrôle côté consommateur : une régression dans Polaris casse immédiatement toutes les apps
- Pas de rollback possible pour un consommateur individuel
- Dépendance réseau : le CDN devient un SPOF
C’est viable quand le producteur et les consommateurs sont dans la même organisation et que le producteur a les moyens d’investir massivement dans les tests et le release management. Pour un écosystème de 300 projets avec des équipes hétérogènes, c’est un pari risqué.
9. Headless : la couche la plus partageable
Le constat
Quand on veut partager des composants, il faut distinguer ce qui est stable de ce qui change fréquemment :
| Couche | Stabilité | Exemples |
|---|---|---|
| Comportement (headless) | Très stable | Navigation clavier, focus, ARIA, état |
| Design tokens | Stable | Couleurs, espacement, typographie |
| Styles | Variable | CSS, Tailwind classes, CSS-in-JS |
| Composition | Très variable | Layout, arrangement, business logic |
Les bibliothèques headless — Radix UI, React Aria (Adobe), Ark UI (Chakra Systems), Base UI (MUI) — ne fournissent que la première couche. Pas de styles, pas d’opinions visuelles, juste le comportement et l’accessibilité.
Source : Radix UI, React Aria, Ark UI
Pourquoi c’est pertinent pour le partage
Pour 300 projets, les primitives headless sont la couche la plus partageable :
- Pas de conflits de style — chaque consommateur applique ses propres tokens
- API stable — le comportement change moins souvent que le design
- Bundle réduit — pas de CSS embarqué
- Composabilité — les primitives se composent, les composants stylisés se remplacent
L’architecture recommandée
┌────────────────────────────────────────────┐
│ Couche 3 : Applications (300 projets) │
│ → composent les pages, appliquent │
│ les thèmes spécifiques │
├────────────────────────────────────────────┤
│ Couche 2 : Design system d'organisation │
│ → composants stylisés utilisant │
│ la couche 1 + tokens maison │
│ → distribués via npm ou registre shadcn │
├────────────────────────────────────────────┤
│ Couche 1 : Primitives headless │
│ → Radix UI, React Aria, Ark UI │
│ → dépendances npm classiques │
└────────────────────────────────────────────┘
C’est exactement ce que shadcn/ui a démontré : Radix (couche 1) + Tailwind (couche 2) distribué comme code source. Une organisation peut répliquer ce pattern avec ses propres tokens de design.
10. React client vs Astro serveur : deux problèmes différents ?
Composants React (client)
Les composants React sont des modules JavaScript standard. Toutes les stratégies de distribution fonctionnent : npm, monorepo, registre shadcn, Module Federation.
Le composant est compilé par le bundler du consommateur (Vite, Webpack, Rspack). Le contrat est clair : on exporte des fonctions JSX, le consommateur les importe.
Composants Astro (serveur)
Les composants .astro sont des templates rendus côté serveur. Ce ne sont pas des modules JS standards — ils dépendent du compilateur Astro pour être transformés en HTML. Ça change les options :
| Stratégie | Composants React | Composants .astro |
|---|---|---|
| Paquets npm | Fonctionne nativement | Limité — nécessite qu’Astro compile |
| Monorepo interne | Fonctionne | Fonctionne (le build Astro compile) |
| Registre shadcn | Supporté (CLI v4) | Supporté (CLI v4) |
| Module Federation | Cas d’usage principal | Non supporté |
| Web Components | Fonctionne | Fonctionne |
Pour les composants .astro, les options réalistes sont :
- Monorepo avec paquets internes — le build Astro du consommateur compile les composants directement
- Paquet npm avec les composants
.astro— fonctionne, mais nécessite que tous les consommateurs utilisent Astro. Le paquet doit exporter les fichiers.astrotels quels (pas de pré-compilation). - Registre shadcn — le CLI v4 gère nativement le scaffolding pour Astro
En pratique, si les 300 projets n’utilisent pas tous Astro, la stratégie la plus flexible est de distribuer les composants métier comme des composants React utilisables en îlots Astro. Les composants purement serveur (layouts, wrappers HTML) restent dans un paquet npm ou monorepo pour les consommateurs Astro.
11. Codemods : automatiser les migrations
Quand un composant partagé change d’API — renommage de prop, modification de la signature, changement de pattern — les codemods permettent de transformer automatiquement le code des consommateurs.
Comment ça fonctionne
Un codemod est un script qui parse l’AST (Abstract Syntax Tree) du code, identifie les patterns à modifier, et applique la transformation.
# Exemple avec jscodeshift
npx jscodeshift -t transforms/rename-variant-prop.ts src/**/*.tsx
// transforms/rename-variant-prop.ts
// Renomme <Button type="primary"> en <Button variant="primary">
export default function transformer(file, api) {
const j = api.jscodeshift;
return j(file.source)
.findJSXElements("Button")
.find(j.JSXAttribute, { name: { name: "type" } })
.forEach((path) => {
path.node.name.name = "variant";
})
.toSource();
}
Source : Codemods for API Refactoring — Martin Fowler
À l’échelle
La plateforme codemod.com permet de créer, publier et exécuter des codemods. Combiné avec Renovate Bot, le workflow devient :
- La bibliothèque publie une version majeure avec un codemod associé
- Renovate crée une PR de mise à jour dans chaque consommateur
- La CI du consommateur exécute le codemod dans la PR
- L’équipe du consommateur review et merge
C’est le mécanisme qui rend la propagation des changements cassants faisable à 300 projets. Sans codemods, chaque changement d’API est un blocage.
12. Comparaison synthétique
| Critère | npm | Monorepo interne | Registre shadcn | Git submodule | Module Federation | Bit |
|---|---|---|---|---|---|---|
| Propagation des correctifs | Consommateur pull (Renovate) | Instant (même repo) | Manuel (re-add) | Manuel (update SHA) | Instant (runtime) | Ripple CI auto |
| Risque de casse | Contrôlé (semver) | Nul (atomique) | Nul (code possédé) | Non contrôlé | Runtime (dangereux) | Contrôlé (Ripple vérifie) |
| 300 consommateurs | Éprouvé | Seulement dans le monorepo | Distribution OK, mises à jour non | Très mal adapté | Conçu pour (coût opérationnel) | Conçu pour (vendor lock-in) |
| Composants React | Natif | Natif | Natif | N/A | Cas principal | Natif |
Composants .astro | Limité | Bon | Supporté (CLI v4) | N/A | Non supporté | Non supporté |
| Maturité outillage | Très haute | Haute | En croissance rapide | Stable mais manuel | MF 2.0 stable (2026) | Moyenne |
| Autonomie du consommateur | Moyenne (pin versions) | Faible (tout à HEAD) | Totale | Moyenne | Faible (couplage runtime) | Moyenne |
13. Recommandation : quelle stratégie pour quel cas
Il n’y a pas de solution universelle. Le choix dépend du type de composant et de la relation avec les consommateurs.
Composants headless / primitives d’accessibilité
Ne pas réinventer. Utiliser Radix UI, React Aria ou Ark UI directement. Ce sont des dépendances npm classiques, très stables, massivement testées. Les 300 projets les importent via npm.
Design system (boutons, modales, champs, typographie)
Registre shadcn privé + paquets npm en complément. Le registre shadcn est idéal pour la distribution initiale — les consommateurs récupèrent un point de départ solide qu’ils peuvent personnaliser. Pour les correctifs critiques (accessibilité, sécurité), un paquet npm avec versionnage sémantique et Renovate Bot assure la propagation.
Le pattern : les composants non modifiés restent en dépendance npm (mises à jour automatiques). Les composants personnalisés sont distribués via registre shadcn (mises à jour manuelles via diff).
Composants métier (formulaire de réservation, module de recherche)
Paquets npm avec Changesets + codemods. Ces composants doivent se comporter de manière uniforme à travers les 300 projets. La distribution via npm avec Renovate Bot pour les mises à jour automatiques et des codemods pour les migrations d’API est l’approche la plus fiable.
Micro-frontends (sections complètes d’application)
Module Federation si les consommateurs sont des applications web qui composent des fragments au runtime. Pertinent pour un portail composant des modules de différentes équipes, pas pour 300 projets indépendants.
L’organisation qui produit la bibliothèque
Monorepo (Turborepo ou Nx) pour le développement interne, avec publication npm pour la distribution externe. C’est le modèle d’Atlassian (Atlaskit) et de la plupart des design systems d’entreprise.
14. Pièges et limitations connus
Le “dependency hell” des composants partagés
Quand un composant partagé a lui-même des dépendances (React, date-fns, zod…), les conflits de version entre la bibliothèque et le consommateur sont inévitables. Solutions :
- Déclarer les dépendances en
peerDependencies(le consommateur fournit sa propre version) - Minimiser les dépendances transitives
- Tester contre plusieurs versions des peer dependencies en CI
La longue traîne de migration
Sur 300 projets, une migration majeure prendra des mois. Certains projets resteront sur l’ancienne version indéfiniment. Il faut planifier :
- Combien de temps la version N-1 reste maintenue
- Un mécanisme de deprecation visible (warnings en console, README)
- Des codemods pour réduire le coût de migration
L’illusion du “on va tout mettre en commun”
Le risque le plus fréquent n’est pas technique mais organisationnel. Mutualiser un composant signifie qu’une équipe en est responsable : maintenance, support, documentation, rétrocompatibilité. Sans cette responsabilité claire, le composant partagé finit abandonné ou forké dans chaque projet — ce qui est pire que de ne pas avoir mutualisé du tout.
Composants .astro : le piège de la pré-compilation
Un paquet npm contenant des fichiers .astro ne peut pas être pré-compilé — les fichiers .astro doivent être compilés par le build du consommateur. Ça signifie que le paquet doit exporter les fichiers source tels quels, ce qui crée un couplage fort avec la version d’Astro du consommateur.
15. Conclusion
Le partage de composants entre 300 projets n’est pas un problème d’outillage — c’est un problème de stratégie de propagation. L’outil ne fait que matérialiser le compromis choisi entre contrôle et cohérence.
En résumé :
- npm + Renovate + codemods est le socle éprouvé pour distribuer à grande échelle avec un contrat de compatibilité clair
- Le monorepo est optimal pour l’équipe qui produit la bibliothèque, pas pour les consommateurs
- Le modèle shadcn (distribution de code source) est puissant pour les composants personnalisables, mais la propagation des mises à jour ne scale pas
- Module Federation résout un problème différent — la composition runtime d’applications, pas la distribution de bibliothèques
- Les primitives headless sont la couche la plus partageable parce que c’est celle qui change le moins
- Chaque composant partagé nécessite un propriétaire, sinon la mutualisation est pire que la duplication
Le choix le plus fréquent en 2026 pour les organisations : un monorepo avec Turborepo ou Nx pour le développement, publication npm avec Changesets pour la distribution, Renovate Bot pour la propagation automatique des mises à jour mineures, et des codemods pour les migrations majeures. Les composants fondamentaux (design system) reposent sur des primitives headless (Radix, React Aria). Les composants hautement personnalisables sont distribués via un registre shadcn privé.
C’est moins séduisant qu’une solution unique, mais c’est ce qui fonctionne à l’échelle.