Gestion de Monorepo dans Cursor : Turborepo, Nx et pnpm Workspaces

Les monorepos vous permettent de garder plusieurs packages ou applications dans un seul dépôt, partageant le code, la configuration et les outils. Cursor, un éditeur IDE propulsé par l'IA, rend la gestion de monorepo considérablement plus facile en comprenant les relations inter-packages, en générant des configurations de pipeline et en refactorant les API partagées en toute sécurité. Ce guide couvre Turborepo, Nx et pnpm workspaces, avec des techniques pratiques pour la gestion des dépendances assistée par IA et le refactoring inter-packages.
Prérequis
Avant de commencer, assurez-vous de disposer des éléments suivants :
- Cursor (dernière version recommandée) comme éditeur IDE
- Node.js 18 ou supérieur
- pnpm installé globalement (
npm install -g pnpm) - Connaissance de base des gestionnaires de packages et des workspaces
Le terminal intégré de Cursor et le support des workspaces multi-racines en font un outil idéal pour les monorepos. Ouvrez la racine du dépôt dans Cursor pour que l'IA puisse voir tous les packages à la fois. Cela donne à l'éditeur le contexte complet pour le refactoring inter-packages et l'analyse des dépendances.
Choix d'un outil de monorepo
Trois outils dominent le paysage des monorepos JavaScript et TypeScript. Chacun a des forces différentes :
| Outil | Idéal pour | Force clé |
|---|---|---|
| pnpm workspaces | Monorepos petits à moyens | Installations rapides et efficaces en disque |
| Turborepo | Monorepos centrés sur les applications | Mise en cache de tâches simple et exécutions parallèles |
| Nx | Grands monorepos riches en plugins | Génération de code puissante et graphe de dépendances |
Demandez à l'IA de Cursor de recommander un outil pour votre situation :
I have a monorepo with 2 Next.js apps, a shared React component library,
and 3 utility packages. Should I use Turborepo or Nx? Compare them.
Cursor explique les compromis et génère une configuration de démarrage pour l'outil choisi.
Configuration de pnpm Workspaces dans Cursor
Les pnpm workspaces sont la fondation de la plupart des monorepos modernes en raison de leur vitesse et de leur efficacité de disque par hard-linking. Cursor vous aide à définir le workspace et à démarrer les premiers packages.
Création de la racine du workspace
Ouvrez un nouveau dossier dans Cursor et demandez à l'IA de créer un workspace pnpm :
Create a pnpm workspace monorepo with:
- A root package.json with pnpm workspace config
- A pnpm-workspace.yaml listing apps/* and packages/*
- A shared TypeScript config package
- An .npmrc with shared-cache settings
Cursor génère les fichiers racine :
# pnpm-workspace.yaml
packages:
- 'apps/*'
- 'packages/*'
// package.json
{
"name": "cursor-monorepo",
"private": true,
"scripts": {
"dev": "pnpm -r --parallel run dev",
"build": "pnpm -r run build",
"lint": "pnpm -r run lint",
"test": "pnpm -r run test"
},
"devDependencies": {
"typescript": "^5.4.0"
}
}
# .npmrc
shared-cache-max-age=86400
auto-install-peers=true
strict-peer-dependencies=false
Création des premiers packages
Demandez à Cursor de générer un package UI partagé et une application web qui le consomme :
Create a packages/ui React component library and an apps/web Next.js app.
The web app should depend on the ui package using workspace:* protocol.
Cursor génère la structure des packages :
monorepo/
apps/
web/
package.json
src/
app/page.tsx
packages/
ui/
package.json
src/
index.ts
Button.tsx
pnpm-workspace.yaml
package.json
Le packages/ui/package.json :
{
"name": "@cursor-monorepo/ui",
"version": "0.1.0",
"main": "./src/index.ts",
"types": "./src/index.ts",
"scripts": {
"lint": "eslint .",
"build": "tsc"
},
"peerDependencies": {
"react": "^18.0.0"
}
}
Le apps/web/package.json référence le package partagé en utilisant le protocole workspace :
{
"name": "@cursor-monorepo/web",
"version": "0.1.0",
"dependencies": {
"@cursor-monorepo/ui": "workspace:*",
"next": "^14.0.0",
"react": "^18.0.0"
}
}
Installez tout depuis la racine en utilisant le terminal de Cursor :
pnpm install
pnpm crée des hard-links des dépendances, l'installation est donc rapide et efficace en disque.
Utilisez toujours le protocole workspace:* (ou workspace:^) pour référencer les packages internes. Si vous épinglez un numéro de version comme 1.0.0, pnpm tente de récupérer le package depuis le registre au lieu de résoudre le package local, causant des erreurs confuses de « package introuvable » lors de l'installation.
Intégration de Turborepo dans Cursor
Turborepo ajoute la mise en cache et l'exécution parallèle des tâches au-dessus de pnpm workspaces. Cursor génère la configuration du pipeline et vous aide à la régler.
Ajout de Turborepo à un workspace existant
Demandez à Cursor d'ajouter Turborepo à votre monorepo :
Add Turborepo to my pnpm workspace. Create a turbo.json with build,
dev, lint, and test pipelines. Configure build dependencies and caching.
Cursor installe la dépendance et génère turbo.json :
pnpm add -Dw turbo
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**", "!.next/cache/**"],
"inputs": [
"src/**",
"package.json",
"tsconfig.json"
]
},
"dev": {
"cache": false,
"persistent": true
},
"lint": {
"dependsOn": ["^build"],
"outputs": []
},
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"],
"inputs": ["src/**", "test/**", "package.json"]
}
}
}
La directive dependsOn: ["^build"] indique à Turborepo de construire les dépendances d'un package avant de construire le package lui-m ême, ce qui est critique pour les monorepos où les applications dépendent de bibliothèques partagées.
Exécution de tâches avec Turbo
Exécutez des tâches sur l'ensemble du monorepo depuis le terminal de Cursor :
# Build all packages in topological order
pnpm turbo run build
# Run dev servers in parallel
pnpm turbo run dev --parallel
# Filter to a single package and its dependents
pnpm turbo run build --filter=@cursor-monorepo/web...
Le suffixe ... signifie « ce package et tout ce qui en dépend », utile pour l'analyse d'impact lorsque vous modifiez une bibliothèque partagée.
Utilisez le flag --filter avec le préfixe ^ pour exécuter une tâche pour un package et ses dépendances uniquement. Par exemple, pnpm turbo run build --filter=^@cursor-monorepo/web construit uniquement les packages dont l'application web a besoin, en sautant le travail non pertinent. C'est inestimable pour des boucles de retour locales rapides.
Configuration de la mise en cache à distance
La mise en cache à distance permet à votre équipe de partager les résultats de build. Demandez à Cursor de configurer le cache à distance Vercel :
Configure Turborepo remote caching for my monorepo. Generate the
.nenv example and explain how to link the cache.
Cursor explique les étapes :
npx turbo login
npx turbo link
Ajoutez un indice d'environnement turbo.json pour que les clés de cache incluent les bonnes variables :
{
"globalEnv": ["NODE_ENV", "CI"]
}
Intégration de Nx dans Cursor
Nx est un outil de monorepo plus puissant avec des générateurs de code, un graphe de dépendances et un support de plugins pour de nombreux frameworks. Cursor vous aide à démarrer et à étendre les projets Nx.
Création d'un workspace Nx
Demandez à Cursor de créer un workspace Nx :
Create an Nx integrated monorepo with:
- A React app named storefront
- A Node API app named api
- A shared types library
- pnpm as the package manager
Cursor exécute le scaffolding et explique le résultat :
npx create-nx-workspace@latest cursor-nx --preset=apps --packageManager=pnpm
La structure résultante :
cursor-nx/
apps/
storefront/
api/
libs/
types/
nx.json
project.json
Génération de code avec les plugins Nx
Les plugins Nx fournissent des générateurs pour un scaffolding cohérent. Demandez à Cursor de générer une bibliothèque de composants React :
Generate a React library named ui with buildable true and
Storybook configuration using the @nx/react plugin.
npx nx g @nx/react:library ui --buildable --storybook --directory=libs/ui
Visualisation du graphe de dépendances
Nx est livré avec un visualiseur de graphe. Exécutez-le depuis le terminal de Cursor :
npx nx graph
Cela ouvre un graphe interactif dans votre navigateur montrant comment les packages dépendent les uns des autres. L'IA de Cursor peut également décrire le graphe en texte si vous le demandez :
List all packages that depend on libs/types and would break if I
renamed its default export.
Cursor lit la configuration du workspace et retourne une analyse d'impact, essentielle avant de refactorer le code partagé.
Les workspaces intégrés Nx utilisent le mappage de chemins dans tsconfig.base.json pour les imports. Si vous ajoutez une nouvelle bibliothèque, vous devez mettre à jour le mappage paths ou TypeScript ne peut pas résoudre l'import. L'IA de Cursor peut détecter les mappages de chemins manquants et suggérer la correction lorsque vous voyez des erreurs « Cannot find module ».
Gestion des dépendances assistée par IA
Maintenir la cohérence des dépendances dans un monorepo est l'une des tâches de maintenance les plus difficiles. L'IA de Cursor excelle dans ce domaine.
Audit des inadéquations de version
Demandez à Cursor de trouver les inadéquations de dépendances :
Scan all package.json files in my monorepo and report any
dependencies that have inconsistent versions across packages.
Suggest a single pinned version for each.
Cursor lit chaque package.json, liste les inadéquations et peut générer un script pour les aligner :
# Align react to 18.2.0 everywhere
pnpm -r exec pnpm add [email protected] [email protected]
Détection des dépendances inutilisées
Cursor peut détecter les packages déclarés dans package.json mais jamais importés. Demandez :
Find unused dependencies in the apps/web package by checking
imports across all source files.
Cursor signale les entrées inutilisées et suggère la commande de suppression :
pnpm --filter @cursor-monorepo/web remove unused-package-name
Gestion des dépendances de développement partagées
Remontez les outils de développement partagés (ESLint, Prettier, TypeScript) vers la racine du workspace pour éviter la dérive des versions. Cursor génère un package de configuration partagée :
Create a packages/config package that exports shared ESLint,
TypeScript, and Prettier configs so other packages can extend them.
// packages/config/package.json
{
"name": "@cursor-monorepo/config",
"version": "0.1.0",
"files": ["eslint", "tsconfig", "prettier"],
"devDependencies": {
"eslint": "^8.57.0",
"prettier": "^3.2.0"
}
}
// packages/config/eslint/base.js
module.exports = {
extends: ['next', 'prettier'],
rules: {
'no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
'no-console': ['warn', { allow: ['warn', 'error'] }],
},
};
Les autres packages étendent la configuration partagée :
{
"eslintConfig": { "extends": "@cursor-monorepo/config/eslint" }
}
Utilisez la fonctionnalité catalog de pnpm (ou Renovate) pour centraliser les numéros de version en un seul endroit. Demandez à Cursor : « Configure un catalogue pnpm pour toutes les versions de dépendances partagées », et il créera le bloc catalogue dans pnpm-workspace.yaml pour qu'une seule mise à jour de version se propage partout automatiquement.
Refactoring inter-packages avec Cursor
Refactorer une API partagée affecte chaque consommateur. L'indexation du code base de Cursor permet à l'IA de suivre les utilisations dans tout le monorepo, rendant les grands refactors sûrs.
Renommage d'un export partagé
Supposons que vous vouliez renommer le composant Button en ActionButton dans packages/ui. Demandez à l'Agent de Cursor :
Rename the Button component to ActionButton across the entire
monorepo. Update the export, the type, all imports, and the
Storybook stories. Run the build to verify nothing is broken.
Cursor effectue l'édition multi-fichiers en une seule passe :
// packages/ui/src/ActionButton.tsx
import React from 'react';
export interface ActionButtonProps {
label: string;
onClick: () => void;
variant?: 'primary' | 'secondary';
}
export const ActionButton = ({ label, onClick, variant = 'primary' }: ActionButtonProps) => (
<button className={`btn btn-${variant}`} onClick={onClick}>
{label}
</button>
);
// packages/ui/src/index.ts
export { ActionButton } from './ActionButton';
export type { ActionButtonProps } from './ActionButton';
// apps/web/src/app/page.tsx
import { ActionButton } from '@cursor-monorepo/ui';
export default function Home() {
return <ActionButton label="Get Started" onClick={() => alert('hi')} />;
}
Extraction d'un utilitaire partagé
Quand vous trouvez une logique dupliquée entre les packages, demandez à Cursor de l'extraire :
Extract the date formatting logic duplicated in apps/web and apps/api
into a new shared package called @cursor-monorepo/format. Update all
call sites to import from the new package.
Cursor crée le package, déplace le code, met à jour les imports et exécute les builds affectés pour confirmer le succès.
Après un refactor inter-packages, exécutez toujours la suite de tests complète et la vérification de type pour tout le workspace. Un seul import manqué peut compiler isolément mais échouer lorsque les packages sont composés. Exécutez pnpm -r run build && pnpm -r run test depuis la racine pour détecter ces problèmes tôt.
Configuration du workspace et des outils
Des outils cohérents entre les packages maintiennent un monorepo sain. Cursor peut générer des configurations partagées pour TypeScript, ESLint et CI.
Configuration TypeScript partagée
Create a shared tsconfig base at packages/config/tsconfig/base.json
with strict mode, path aliases, and modern lib settings.
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"strict": true,
"noUncheckedIndexedAccess": true,
"moduleResolution": "bundler",
"module": "ESNext",
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true
}
}
Chaque package l'étend :
{
"extends": "@cursor-monorepo/config/tsconfig/base.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src"
},
"include": ["src"]
}
Pipeline CI avec GitHub Actions
Demandez à Cursor de générer un pipeline CI qui exploite la mise en cache Turborepo :
Create a GitHub Actions workflow that:
- Installs pnpm and Node
- Restores the pnpm store cache
- Runs turbo run lint build test with caching
- Only runs affected tasks on pull requests
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: pnpm/action-setup@v3
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm install --frozen-lockfile
- uses: actions/cache@v4
with:
path: .turbo
key: turbo-${{ runner.os }}-${{ github.sha }}
restore-keys: turbo-${{ runner.os }}-
- run: pnpm turbo run lint build test
Résumé des meilleures pratiques
Gardez ces principes à l'esprit lors de la gestion d'un monorepo dans Cursor :
- Ouvrez la racine du workspace pour que Cursor voie tous les packages pour le contexte inter-packages.
- Utilisez le protocole workspace (
workspace:*) pour les références de packages internes. - Remontez les outils de dev partagés vers un package de configuration pour éviter la dérive des versions.
- Exploitez la mise en cache des tâches avec Turborepo ou Nx pour garder le CI rapide.
- Exécutez l'analyse d'impact avant de refactorer les API partagées.
- Centralisez les versions avec les catalogues pnpm ou Renovate.
En combinant un outil de monorepo solide avec la compréhension du code base propulsée par l'IA de Cursor, vous pouvez refactorer le code partagé en confiance, maintenir les dépendances alignées et livrer des outils cohérents à travers de nombreux packages. Décrivez clairement votre intention, laissez Cursor gérer le boilerplate et les éditions inter-fichiers, et révisez les diffs générés avant de committer.