2026 Builds front sur Mac distant :
modules natifs esbuild et swc, optionalDependencies et matrice de décision pour reconstruire proprement
Public : full-stack et front sur Vite, Next ou monorepo via Mac loué SSH. esbuild et swc livrent des binaires natifs ; les optionalDependencies choisissent darwin arm64. Si Node, libc++ (Xcode/CLT) ou cache CI divergent, dlopen casse le runner malgré une session locale propre. L’objectif est une « décision reproductible » : tracer l’ABI, figer l’image et refuser les restaurations silencieuses qui mélangent Rosetta et Apple Silicon natif. Vous obtenez un tableau de symptômes, une matrice locale contre CI, des commandes, des clés de cache node_modules et une FAQ. Liens : SSR Next/Nuxt, Import Maps ESM, Vite/webpack Safari.
Friction : (1) node_modules Linux réhydraté sur macOS ; (2) Node x64 Rosetta vs arm64 ; (3) pnpm/npm trop parallèles, extractions esbuild corrompues.
01 Tableau de correspondance des symptômes
| Symptôme observé | Cause probable | Premier geste |
|---|---|---|
| ELF invalide ou mauvaise architecture au require | Mauvaise tranche CPU/OS (cache, tarball). | uname -m vs node -p process.arch ; bust cache ; lockfile. |
| NODE_MODULE_VERSION | Majeur Node changé, addon ancien ABI. | .nvmrc = CI ; pas de cache lockfile seul. |
| dyld libc++ | Xcode/CLT runner ≠ build binaire. | Image figée ; pas de mix entre générations. |
| Vite instable | Postinstall optionnels en course. | Moins de parallélisme ; workspaces natifs sérialisés. |
Citable : process.versions.modules = ABI ; Apple Silicon arm64. esbuild et swc tirent des optionnels plateforme : une tranche fausse bloque le compilateur derrière des erreurs bundler floues.
En pratique, documentez dans le README du dépôt la paire Node plus Xcode validée par la CI et refusez les merges lorsque la sonde native échoue, même si les tests unitaires JavaScript passent encore : le signal est structurel, pas fonctionnel.
02 Matrice architecture locale contre CI
| Dimension | Session sur Mac distant | Job CI sur Mac distant |
|---|---|---|
| CPU et Node | arm64 courant ; piège Node x64 Rosetta. | Label runner ; même Node que les laptops. |
| optionalDependencies | Retries masquent archives partielles. | Logs headless ; échec rapide sur stderr postinstall. |
| libc++ | Suit Xcode local / xcode-select. | Catalogue image ; OS bump sans reinstall casse binaires cachés. |
| Disque | SSH coûte les gros hoists. | Plus de contention ; suffixer store par job. |
Sur un runner partagé, la fenêtre entre deux jobs est courte : toute archive optionnelle partiellement extraite peut sembler valide jusqu’au premier require réel ; d’où l’intérêt de séparer les workspaces et de journaliser l’empreinte machine dans chaque artefact de build.
Acceptation concurrence CI
- Limiter maxsockets / child-concurrency si postinstall domine.
- Pas de pnpm-store partagé sans suffixe par job matrice.
- Prévol
require('esbuild')etrequire('@swc/core')avant Vite. - Artefacts logs npm/pnpm si sonde KO.
- Runtimes mixtes : Bun Node Deno cache.
03 Liste des commandes de reconstruction
Shell Mac distant = runner CI ; même gestionnaire de paquets que le YAML.
uname -m
node -p "[process.platform, process.arch, process.versions.modules, process.version].join(' ')"
which node
npm -v || true
pnpm -v || true
rm -rf node_modules
# npm :
npm ci
# ou pnpm :
pnpm install --frozen-lockfile
node -e "require('esbuild'); console.log('esbuild ok')"
node -e "require('@swc/core'); console.log('swc ok')"
Règle : sonde KO ⇒ rebuild natif avant code métier ; lockfile vérifié dans le même job que l’install.
04 Clés de cache et stratégie de nettoyage node_modules
node_modules non portable : OS, arch, majeur Node, libc. Clé = lockfile hash + arch + Node semver + digest image / Xcode.
- Préfixe
darwin-arm64-node20-, pas lockfile seul. - Montée Xcode ⇒ sel manuel pour bust libc.
- Dimension drift ⇒
rm -rf node_modulescomplet. - Diff lockfile : surveiller optionnels plateforme.
Heuristique : restore rapide + tests natifs verts ⇒ gardez sondes esbuild/swc ou suspectez cache empoisonné.
05 Foire aux questions
esbuild OK en local, KO en CI ?
Arbre réhydraté hors arch/ABI ⇒ dlopen. Aligner Node, arch, clés ; npm ci / pnpm install --frozen-lockfile.
Épingiller esbuild/swc ?
Oui pour logs reproductibles ; vérifiez optionnels darwin arm64 dans le lockfile pour outils imbriqués.
Rosetta et optionalDependencies ?
Node x64 Rosetta annonce x64 ; mélange de shells décale les optionnels. Agents en arm64 natif sauf besoin x64 assumé.
Même Node, arm64, libc++ portable / Mac distant / CI. Bust cache si ABI bouge. Sondes esbuild + swc avant bundle.
Louez un Mac distant avec même Xcode et majeur Node que la CI pour figer les optionalDependencies. Suite : index blog, accueil.
Louez un builder Apple Silicon aligné sur votre Node CI
Mac distant arm64 + toolchain = CI : validez esbuild et swc avant merge. Tarifs, aide SSH/VNC, achat ou location.