Éditeur de CV basé sur Canvas : Retours d'expérience avec Monorepo et Rspack

Mise en place d'un Monorepo avec PNPM

L'adoption d'un monorepo s'est avérée bénéfique pour la gestion de projets modulaires. Confronté à des problèmes de TreeShaking incorrect lors de la publication d'un éditeur de texte riche comme package NPM, il est apparu que gérer plusieurs packages indépendants mais interdépendants dans un dépôt unique simplifiait considérablement la maintenance et la cohérence des builds. Cette approche évite les pièges des dépendances non résolues et des versions multiples de bibliothèques comme React, qui peuvent survenir lors de la consommation de packages indépendants.

PNPM excelle dans ce domaine grâce à son modèle de stockage basé sur des liens symboliques et son fichier pnpm-workspace.yaml. Ce dernier définit les espaces de travail, par exemple en désignant tous les sous-dossiers dans packages/ comme des projets autonomes au sein du monorepo.

La structure du projet « Éditeur de CV » en découle directement :

  • packages/core : Moteur principal gérant le rendu Canvas, l'état, l'historique et les opérations de base.
  • packages/delta : Modèle de données atomique et structure DeltaSet pour décrire les opérations et l'état de l'éditeur, crucial pour l'undo/redo.
  • packages/plugin : Architecture modulaire pour les fonctionnalités (texte, image, formes) bâtie sur le modèle de données.
  • packages/react : Couche de vue pour React. Le moteur central est indépendant du framework, permettant d'imaginer des adaptateurs pour Vue ou Angular.
  • packages/utils : Fonctions utilitaires partagées dans tout l'espace de travail.

Cette organisation offre une séparation claire des préoccupations, facilite le versionnage synchronisé et permet des optimisations globales du processus de construction.

Optimisation des Configurations TypeScript et Rspack

Dans un monnorepo, le développement et le typage des sous-projets peuvent poser des défis spécifiques. Deux problèmes fréquents sont le décalage des déclarations TypeScript et la nécessité de recompiler manuellement chaque package interne après une modification.

Configuration TypeScript pour une résolution en temps réel

Pour que les changements dans les types d'un sous-projet soient immédiatement visibles par l'IDE sans compilation intermédiaire, on configure les paths dans le tsconfig.json racine. Cela redirige la résolution des imports vers les sources TypeScript directes au lieu des déclarations compilées dans node_modules.

{
  "compilerOptions": {
    "paths": {
      "cv-core": ["./packages/core/src"],
      "cv-delta": ["./packages/delta/src"],
      "cv-plugin": ["./packages/plugin/src"],
      "cv-utils": ["./packages/utils/src"]
    },
    "baseUrl": "."
  },
  "include": ["packages/*/src"]
}

Remarque : Éviter "baseUrl": "." peut prévenir des problèmes de chemin imprévisibles ; des chemins relatifs explicites sont souvent plus fiables.

Configuraton Rspack pour la compilation à chaud

Afin d'éviter la recompilation complète des packages internes lors du développement, Rspack (ou webpack) doit être configuré pour compiler directement les fichiers sources TypeScript des sous-projets. Cela se fait via des alias dans la configuration resolve.

// rspack.config.js (extrait)
const path = require('path');

module.exports = {
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
      'cv-core': path.resolve(__dirname, '../core/src'),
      'cv-delta': path.resolve(__dirname, '../delta/src'),
      'cv-plugin': path.resolve(__dirname, '../plugin/src'),
      'cv-utils': path.resolve(__dirname, '../utils/src')
    }
  }
  // ... autres configurations
};

Pour des setups basés sur Create React App (CRA) avec webpack, une configuration similaire peut être implémentée en étendant la config via customize-cra, en incluant les répertoires sources dans la compilation Babel et en désactivant les restrictions de portée des modules.

Déploiement Continu via GitHub Actions

Étant une application frontend pure, l'éditeur peut être déployé comme site statique. Un workflow GitHub Actions permet de construire automatiquement le package react et de le déployer sur GitHub Pages à chaque push sur la branche principale, offrant ainsi une démo en ligne accessible directement depuis le dépôt.

# .github/workflows/deploy.yml
name: Deploy to GitHub Pages

on:
  push:
    branches: [ main ]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      - name: Install dependencies
        run: npm install -g pnpm && pnpm install
      - name: Build application
        run: pnpm run build --filter cv-react
      - name: Deploy to Pages
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./packages/react/dist

Étiquettes: Canvas Monorepo Rspack TypeScript PNPM

Publié le 17 juin à 23h57