Slovník pojmů
Turborepo
Turborepo koordinuje projektové úlohy napříč balíčky jednoho monorepa. Neinstaluje závislosti jako package manager a nesestavuje aplikaci jako bundler; plánuje existující scripts, jejich pořadí a cache.
Stručná definice
Orchestrace úloh nad skutečnými vazbami mezi workspace balíčky.
Monorepo ukládá více aplikací a sdílených balíčků v jednom repozitáři. Package manager workspaces určují, které adresáře jsou balíčky, instalují jejich externí závislosti a propojí interní balíčky. Turborepo nad tímto package graphem sestaví task graph a rozhodne, které scripts může spustit současně a které musí čekat na výsledek závislosti.
Úlohy jako build, test nebo lint jsou skutečné scripts v package.json jednotlivých balíčků. Soubor turbo.json popisuje jejich vazby, výstupy, vstupy a cache. Turborepo tedy není package manager, bundler ani testovací framework: koordinuje nástroje, které projekt už používá přes Node.js ekosystém.
Cache uchovává výsledek úlohy pro konkrétní otisk vstupů. Při shodě může Turborepo obnovit log a deklarované výstupy místo nového běhu. Je to optimalizace, ne záruka korektnosti: chybějící environment proměnná, generovaný vstup nebo špatné outputs mohou vrátit neodpovídající artefakt.
Jaký problém řeší
Měnící se sdílený balíček nemá spustit všechno ani přeskočit dotčenou aplikaci.
S růstem monorepa přestává být správné slepě spouštět každý build a test, ale ruční výběr dotčených kroků bývá nespolehlivý. Task graph dovolí provést jen potřebnou práci ve správném pořadí.
- build interních knihoven před buildem aplikací, které je používají
- paralelní spuštění nezávislých testů, lintů nebo buildů
- použití lokální cache při opakování stejné úlohy na jednom stroji
- volitelné sdílení výsledků přes remote cache mezi vývojáři a CI
- filtrování úloh na konkrétní package, jeho dependencies, dependents nebo změny v Gitu
- omezení práce v CI na relevantní část repozitáře při zachování skutečných vazeb
Praktický příklad
Dvě aplikace a dva sdílené balíčky
Monorepo obsahuje apps/web, apps/admin, packages/ui a packages/config. Obě aplikace deklarují interní závislost na UI a podle potřeby také na sdílené konfiguraci. Package manager workspaces balíčky rozpoznají a propojí; Turborepo z jejich vazeb vytvoří package graph.
Konfigurace níže říká, že build balíčku musí počkat na build jeho interních dependencies. Změna packages/ui proto vede nejprve k jeho buildu a následně k buildům dotčených aplikací. Web a admin mohou po dokončení společných dependencies běžet paralelně. Nezměněný výsledek se použije z cache jen tehdy, pokud odpovídá vypočtenému otisku vstupů.
Pole outputs musí odpovídat reálným výstupům použitých nástrojů. Cesta dist/** může patřit knihovně a .next/** aplikaci v Next.js; .next/cache/** se z výsledného aplikačního artefaktu vylučuje. Jiný bundler nebo framework potřebuje jiné cesty a některá úloha nemusí vytvářet žádný cachovaný soubor.
turbo.json
{
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**", "!.next/cache/**"]
},
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"]
}
}
}
Diagram task graphu
Změna packages/ui → build ui → build web a admin.
Zjednodušený tok předpokládá, že obě aplikace mají na UI skutečně deklarovanou interní závislost. Task graph spojuje package graph s pravidly v turbo.json a cache rozhoduje pro každý uzel samostatně.
- Změna packages/ui Zdrojový soubor UI vstoupí do otisku úlohy. Balíčky mimo dotčenou část grafu není nutné spouštět jen proto, že leží ve stejném repozitáři.
- Package graph Workspace konfigurace package manageru a interní dependencies ukážou, že apps/web a apps/admin používají packages/ui. Název adresáře sám vazbu nenahrazuje.
- Build ui Pravidlo dependsOn: ["^build"] řadí build interní dependency před build závislého balíčku. Pokud platný výsledek není v cache, spustí se příslušný package script.
- Build web a admin Po dokončení UI může Turborepo spustit nezávislé buildy obou aplikací paralelně. Každý uzel má vlastní stav, log a cache key.
- Lokální nebo remote cache Při cache hitu se práce přeskočí a deklarované výstupy se obnoví. Remote cache je volitelná sdílená vrstva; bez ní zůstává cache lokální pro daný stroj.
Hlavní části a koncepty
Package graph popisuje balíčky, task graph konkrétní práci.
Přesnost obou grafů rozhoduje o pořadí, paralelismu i důvěryhodnosti cache.
Apps a packages
Adresáře apps obvykle obsahují nasazované aplikace, packages sdílené knihovny nebo konfigurace. Je to užitečná konvence, ne definice monorepa ani povinná architektura Turborepa.
Package graph
Vzniká ze struktury workspaces a interních dependencies spravovaných package managerem. Turborepo jej používá k pochopení vztahů mezi balíčky, ale závislosti samo neinstaluje.
Task graph
Každá kombinace package a scriptu je uzel; dependsOn přidává pořadí mezi uzly. Prefix ^ označuje stejnou úlohu v interních dependencies, obyčejný název může vyjádřit vazbu v témže package.
Inputs, outputs a environment
Otisk musí zahrnout vše, co mění výsledek: zdroje, konfiguraci, lockfile a relevantní environment proměnné. Outputs říkají, které vzniklé soubory se mají při cache hitu obnovit.
Lokální a remote cache
Lokální cache zrychluje opakování na jednom stroji. Remote cache sdílí artefakty s týmem a CI; poskytovat ji může služba nebo kompatibilní HTTP server a vyžaduje řízení přístupu.
Filtry a incremental build
Filtr omezí spuštění na package, adresář, dependencies, dependents nebo změněnou část repozitáře. Inkrementální práce zde znamená vybrat potřebné uzly a znovu použít platné výsledky, ne automaticky částečně kompilovat vnitřek každého nástroje.
Výhody, omezení a časté chyby
Rychlost roste jen s pravdivým grafem a hermetičtějšími úlohami.
Konkrétní přínosy
- nezávislé úlohy se mohou bezpečně spustit paralelně podle grafu
- cache omezuje opakování drahých buildů a testů se stejnými vstupy
- remote cache může sdílet už hotovou práci mezi lokálním vývojem a CI
- jednotné filtry pomáhají cílit kontrolu na změněný package a jeho dependents
- konfigurace task graphu zůstává verzovaná spolu s aplikacemi
Omezení a chyby
- neuvedený vstup nebo environment proměnná může vytvořit nesprávný cache hit
- chybné outputs znamenají, že se při hitu neobnoví potřebný artefakt
- deployment nebo zápis do externí služby se nemá bezmyšlenkovitě cachovat
- nepřesné interní dependencies rozbijí pořadí i výběr dotčených úloh
- remote cache obsahuje build artefakty a logy, proto potřebuje přístupová a bezpečnostní pravidla
- režie konfigurace a monorepa nemusí přinést hodnotu malému projektu
Kdy dává smysl
Pro JavaScriptové a TypeScriptové monorepo se sdíleným kódem a dražšími úlohami.
Turborepo dává smysl, když několik aplikací skutečně sdílí balíčky, tým potřebuje konzistentní build a testy a čas lze ušetřit paralelismem nebo cache. Může koordinovat knihovny i Next.js aplikace, ale Next.js nevyžaduje Turborepo a Turborepo není webový framework ani bundler.
Package manager jako npm, pnpm nebo Yarn zůstává odpovědný za instalaci, lockfile a workspaces. Turborepo nevyžaduje Yarn a jeho použití samo nevytvoří dobře navržené monorepo. Pokud projekty nesdílejí kód, release rytmus ani vlastnictví, mohou být oddělené repozitáře jednodušší. Monorepo navíc není totéž co monolitická aplikace: jeden repozitář může obsahovat více samostatně nasazovaných služeb a jeden monolit může mít jediný package.
Na co myslet
Cache je správná pouze tehdy, když klíč zachytí všechny významné vstupy.
Před zrychlováním je potřeba ověřit hranice balíčků, skutečné dependencies a reprodukovatelnost každého scriptu.
- deklarovat interní dependencies v package manifests, ne spoléhat na umístění adresářů
- zapsat do task konfigurace relevantní outputs, environment proměnné a nestandardní inputs
- necachovat deploymenty a jiné úlohy s externím vedlejším efektem jako běžný čistý build
- ověřit cache hit také v čistém pracovním adresáři, kde chybějící output nelze zakrýt lokálním souborem
- používat jeden zvolený package manager a commitnutý lockfile pro reprodukovatelnou instalaci
- omezit oprávnění remote cache a nezahrnovat secrets do výstupů ani logů
- v CI měřit nejen dobu běhu, ale i cache hit rate, chyby a správnost vzniklých artefaktů
Časté otázky
Turborepo bez častých záměn
Je Turborepo package manager?
Ne. Package manager instaluje závislosti, spravuje lockfile a definuje workspaces. Turborepo nad balíčky a jejich scripts plánuje úlohy, paralelní běh a cache.
Vyžaduje Turborepo Yarn?
Ne. Pracuje s podporovanými package manager workspaces; projekt může podle své konfigurace používat například npm, pnpm nebo Yarn. Důležitá je konzistence jednoho zvoleného lockfile a workflow.
Je Turborepo bundler nebo součást Next.js?
Ne. Bundler vytváří frontendový výstup a Next.js je React framework. Turborepo může jejich scripts spustit a cachovat, ale neurčuje komponenty, routing ani podobu bundle.
Zaručuje cache správný build?
Ne. Cache věří deklarovaným a automaticky zjištěným vstupům. Pokud konfigurace vynechá významný soubor nebo environment proměnnou, může být klíč neúplný a obnovený výsledek chybný.
Je remote cache povinná?
Ne. Turborepo lze používat jen s lokální cache. Remote cache přidává sdílení mezi stroji a CI, ale také vyžaduje autentizaci, pravidla pro citlivé výstupy a důvěryhodného poskytovatele.
Jak navrhuji vývojový systém
Monorepo tooling má odpovídat skutečným vazbám mezi aplikacemi.
Při návrhu projektů odděluji role balíčků, buildů a CI tak, aby automatizace zrychlovala ověřený proces a neskrývala jeho vstupy.