Usamos cookies para mejorar tu experiencia en el sitio
CodeWorlds

Monorepo z Turborepo - Skalowanie projektow Next.js

W rozleglej infrastrukturze Metropolii Quantum 2150, gdzie dziesiaki mikroserwisow i aplikacji frontendowych wspolpracuja ze soba, potrzebujesz narzedzia do zarzadzania kodem na wielka skale. Turborepo to system budowania dla monorepo, ktory dziala z Next.js jak precyzyjny kwantowy procesor - szybko, wydajnie i niezawodnie.

Dlaczego monorepo dla Next.js?

Monorepo to strategia przechowywania wielu projektow w jednym repozytorium. Dla ekosystemu Next.js daje to ogromne korzysci:

  • Wspoldzielenie kodu - komponenty UI, konfiguracje, typy uzywane w wielu aplikacjach
  • Atomowe zmiany - zmiana w wspoldzielonej bibliotece natychmiast widoczna wszedzie
  • Spojny tooling - jedna konfiguracja ESLint, TypeScript, Prettier
  • Uproszczone CI/CD - jeden pipeline dla calego ekosystemu
  • Lepsza wspolpraca - wszystko w jednym miejscu, latwy code review

Konfiguracja Turborepo

Inicjalizacja monorepo

1# Utworz nowe monorepo z Turborepo
2npx create-turbo@latest quantum-monorepo
3
4# Lub dodaj Turborepo do istniejacego projektu
5npm install turbo --save-dev

Struktura katalogow

1quantum-monorepo/
2  apps/
3    web/                 # Glowna aplikacja Next.js
4      package.json
5      next.config.js
6    admin/               # Panel admina Next.js
7      package.json
8      next.config.js
9    docs/                # Dokumentacja Next.js
10      package.json
11
12  packages/
13    ui/                  # Wspoldzielone komponenty React
14      package.json
15      src/
16        Button.tsx
17        Card.tsx
18        index.ts
19    config-eslint/       # Wspoldzielona konfiguracja ESLint
20      package.json
21    config-typescript/   # Wspoldzielona konfiguracja TypeScript
22      package.json
23    types/               # Wspoldzielone interfejsy TypeScript
24      package.json
25      src/
26        user.ts
27        product.ts
28
29  turbo.json             # Konfiguracja Turborepo
30  package.json           # Root package.json

Konfiguracja turbo.json

1{
2  "$schema": "https://turbo.build/schema.json",
3  "globalDependencies": ["**/.env.*local"],
4  "pipeline": {
5    "build": {
6      "dependsOn": ["^build"],
7      "outputs": [".next/**", "!.next/cache/**", "dist/**"]
8    },
9    "lint": {
10      "dependsOn": ["^build"]
11    },
12    "dev": {
13      "cache": false,
14      "persistent": true
15    },
16    "test": {
17      "dependsOn": ["^build"]
18    },
19    "type-check": {
20      "dependsOn": ["^build"]
21    }
22  }
23}

Kluczowe elementy konfiguracji:

  • dependsOn: ["^build"]
    - buduj zaleznosci zanim zbudujesz pakiet
  • outputs
    - co cachowac (foldery wynikowe)
  • cache: false
    - dev server nie powinien byc cachowany
  • persistent: true
    - procesy dlugotrwale (dev server)

Root package.json

1{
2  "name": "quantum-monorepo",
3  "private": true,
4  "workspaces": ["apps/*", "packages/*"],
5  "scripts": {
6    "build": "turbo build",
7    "dev": "turbo dev",
8    "lint": "turbo lint",
9    "test": "turbo test",
10    "type-check": "turbo type-check"
11  },
12  "devDependencies": {
13    "turbo": "^2.0.0"
14  }
15}

Wspoldzielone pakiety

Pakiet UI - komponenty React

1// packages/ui/package.json
2{
3  "name": "@quantum/ui",
4  "version": "0.1.0",
5  "main": "./src/index.ts",
6  "types": "./src/index.ts",
7  "dependencies": {
8    "react": "^18.3.0"
9  },
10  "devDependencies": {
11    "@quantum/config-typescript": "workspace:*",
12    "typescript": "^5.5.0"
13  }
14}
1// packages/ui/src/Button.tsx
2import React from 'react';
3
4interface ButtonProps {
5  children: React.ReactNode;
6  variant?: 'primary' | 'secondary' | 'danger';
7  onClick?: () => void;
8  disabled?: boolean;
9}
10
11export function Button({ children, variant = 'primary', onClick, disabled }: ButtonProps) {
12  const styles = {
13    primary: { background: '#7c4dff', color: '#fff' },
14    secondary: { background: '#64ffda', color: '#000' },
15    danger: { background: '#f44336', color: '#fff' },
16  };
17
18  return (
19    <button
20      onClick={onClick}
21      disabled={disabled}
22      style={{
23        ...styles[variant],
24        padding: '10px 24px',
25        borderRadius: '8px',
26        border: 'none',
27        cursor: disabled ? 'not-allowed' : 'pointer',
28        opacity: disabled ? 0.5 : 1,
29      }}
30    >
31      {children}
32    </button>
33  );
34}
1// packages/ui/src/index.ts
2export { Button } from './Button';
3export { Card } from './Card';

Pakiet types - wspoldzielone interfejsy

1// packages/types/src/user.ts
2export interface User {
3  id: string;
4  email: string;
5  name: string;
6  role: 'admin' | 'user' | 'moderator';
7  createdAt: string;
8}
1// packages/types/src/index.ts
2export * from './user';
3export * from './product';

Workspace dependencies

Aby uzyc wspoldzielonego pakietu w aplikacji Next.js:

1// apps/web/package.json
2{
3  "name": "@quantum/web",
4  "dependencies": {
5    "@quantum/ui": "workspace:*",
6    "@quantum/types": "workspace:*",
7    "next": "^14.2.0",
8    "react": "^18.3.0"
9  },
10  "devDependencies": {
11    "@quantum/config-typescript": "workspace:*",
12    "@quantum/config-eslint": "workspace:*"
13  }
14}

Uzycie w kodzie aplikacji:

1// apps/web/app/page.tsx
2import { Button, Card } from '@quantum/ui';
3import type { Product } from '@quantum/types';
4
5export default async function HomePage() {
6  return (
7    <div>
8      <h1>Quantum Store</h1>
9      <Button variant="primary">Dodaj do koszyka</Button>
10    </div>
11  );
12}

Cache i pipeline Turborepo

Turborepo uzywa inteligentnego systemu cache, ktory zapamietuje wyniki budowania i pomija niezmienione pakiety.

Jak dziala cache

1# Pierwsze budowanie - wszystko od zera
2npx turbo build
3# Output: 5 tasks, 0 cached, 5 not cached
4# Czas: 45s
5
6# Drugie budowanie (bez zmian) - pelny cache
7npx turbo build
8# Output: 5 tasks, 5 cached, 0 not cached
9# Czas: 0.3s

Remote Caching z Vercel

1# Polacz z Vercel Remote Cache
2npx turbo login
3npx turbo link
4
5# Teraz cache jest wspoldzielony miedzy developerami i CI

Filtrowanie budowania

1# Zbuduj tylko konkretna aplikacje
2npx turbo build --filter=@quantum/web
3
4# Zbuduj aplikacje i jej zaleznosci
5npx turbo build --filter=@quantum/web...
6
7# Zbuduj tylko to co sie zmienilo od ostatniego commita
8npx turbo build --filter=[HEAD^1]

Deploying z monorepo na Vercel

Konfiguracja next.config.js dla monorepo

1// apps/web/next.config.js
2/** @type {import('next').NextConfig} */
3const nextConfig = {
4  transpilePackages: ['@quantum/ui'],
5  output: 'standalone',
6};
7
8module.exports = nextConfig;

Opcja

transpilePackages
mowi Next.js, zeby transpilowac kod z pakietow monorepo (domyslnie Next.js nie transpiluje node_modules).

Wieloaplikacyjny deploy

Vercel automatycznie buduje tylko zmienione aplikacje. Jesli zmienisz packages/ui, aplikacje zalezne od tego pakietu zostana przebudowane, a te niezalezne - pominiete.

Najlepsze praktyki

1. Konwencje nazewnictwa pakietow

Uzywaj scope (

@nazwa-organizacji/
) dla wszystkich pakietow i aplikacji:

1@quantum/ui
2@quantum/types
3@quantum/config-eslint
4@quantum/web
5@quantum/admin

2. Wersjonowanie

Uzywaj

workspace:*
dla wewnetrznych zaleznosci - nigdy nie hardcoduj wersji:

1"@quantum/ui": "workspace:*"

3. Zarzadzanie zmiennymi srodowiskowymi

Kazda aplikacja ma wlasny plik

.env
, a
turbo.json
deklaruje globalne zaleznosci od plikow srodowiskowych.

Podsumowanie

Turborepo to potezne narzedzie do skalowania projektow Next.js w architekturze monorepo:

  1. Wspoldzielone pakiety - UI, typy, konfiguracje uzywane w wielu aplikacjach
  2. Inteligentny cache - pomijanie niezmienionych pakietow, przyspieszenie buildow
  3. Pipeline - zaleznosci miedzy zadaniami, rownolegle budowanie
  4. Workspace dependencies -
    workspace:*
    dla wewnetrznych pakietow
  5. Remote caching - wspoldzielony cache miedzy developerami i CI
  6. Deploy na Vercel - natywne wsparcie, automatyczne wykrywanie zmian

W Metropolii Quantum 2150, gdzie kazdy projekt rosnie i wymaga skalowania, Turborepo jest fundamentem architektury - pozwala zarzadzac dziesiatkami aplikacji i bibliotek z jednego miejsca.

Ir a CodeWorlds