Turbo build system monorepo

Kas iš tikrųjų yra Turbo ir kodėl jis tapo tokiu populiarus

Jei dirbate su moderniais JavaScript projektais, tikriausiai jau girdėjote apie Turbo arba Turborepo. Tai nėra dar vienas hipsteriškas įrankis, kuris po metų dings iš radarų – tai rimtas sprendimas, kurį sukūrė Jared Palmer ir jo komanda, o vėliau įsigijo Vercel. Turborepo iš esmės yra build sistema, sukurta specifiškai monorepo struktūroms, ir ji tikrai žino, kaip sutaupyti jūsų laiko.

Pagrindinis Turbo privalumas – tai greitis. Ne tas greitis, kurį matote marketingo skrajutėse su užrašu „iki 10x greičiau”, o realus, apčiuopiamas skirtumas. Kai turite monorepo su keliolika paketų, kur kiekvienas turi savo testus, linterius, build procesus, tradicinės sistemos tiesiog sprogsta. Turbo šią problemą sprendžia trimis pagrindiniais būdais: protingu kešavimu, paralelizavimu ir priklausomybių grafo optimizavimu.

Kas įdomu – Turbo parašytas Go kalba, o ne JavaScript. Tai reiškia, kad pats įrankis yra neįtikėtinai greitas ir efektyvus. Jis nesuvartoja pusės jūsų RAM tik tam, kad paleidžiant build procesą.

Monorepo struktūra ir kodėl ji vis dar aktuali

Prieš kalbant apie Turbo, verta suprasti, kodėl apskritai naudojame monorepo. Yra dvi pagrindinės filosofijos: monorepo (viskas vienoje repozitorijoje) ir polyrepo (kiekvienas paketas atskiroje repozitorijoje). Abi turi savo privalumų ir trūkumų, bet monorepo tampa vis populiaresnis didelėse organizacijose.

Google, Facebook, Microsoft – visi šie gigantai naudoja monorepo struktūras. Kodėl? Nes kai turite šimtus ar tūkstančius tarpusavyje susijusių projektų, viena repozitorija leidžia lengviau valdyti priklausomybes, daryti atomic commits keliuose paketuose vienu metu, ir bendrai turėti geresnę visų projekto dalių matomumą.

Tačiau monorepo turi ir didelį minusą – build laikas. Kai jūsų repozitorija auga, build procesai tampa vis lėtesni. Čia ir įsikiša Turbo. Jis supranta jūsų projekto struktūrą, žino, kurie paketai priklauso vieni nuo kitų, ir gali protingai nuspręsti, ką reikia perkompiliuoti, o ką galima praleisti.

Kaip Turbo kešavimas veikia praktikoje

Turborepo kešavimo sistema yra tikra magija, bet ji nėra juodoji magija – viskas pagrįsta logika. Kai paleidžiate komandą per Turbo, jis apskaičiuoja hash’ą, pagrįstą keliais faktoriais: failų turiniu, aplinkos kintamaisiais, komandos argumentais ir priklausomybių versijomis. Jei šis hash’as jau egzistuoja kešo sistemoje, Turbo tiesiog grąžina rezultatus iš kešo.

Štai konkretus pavyzdys. Tarkime, turite paketą `@myapp/utils` ir `@myapp/frontend`, kuris naudoja utils. Jei pakeisite ką nors frontend’e, bet ne utils, Turbo žinos, kad utils perkompiliuoti nereikia. Jis tiesiog panaudos ankstesnį build rezultatą. Tai gali sutaupyti minutes ar net valandas per dieną, ypač dideliuose projektuose.

{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"]
    },
    "test": {
      "dependsOn": ["build"],
      "outputs": []
    }
  }
}

Šis `turbo.json` failas apibrėžia, kaip jūsų taskų pipeline’as turėtų veikti. `^build` reiškia „paleisk build visose priklausomybėse pirmiau”. `outputs` nurodo, kurie failai turėtų būti kešuojami.

Remote kešavimas ir komandinis darbas

Vienas iš galingiausių Turbo feature’ų yra remote kešavimas. Lokalus kešavimas yra puiku, bet kas nutinka, kai jūsų kolega jau sukompiliavo tą patį kodą? Tradicinėse sistemose jūs vis tiek turėtumėte kompiliuoti viską iš naujo savo mašinoje. Su Turbo remote kešu, jūs galite pasidalinti build rezultatais su visa komanda.

Vercel siūlo savo Turbo infrastruktūrą kešavimui, bet galite naudoti ir savo sprendimus. Tai veikia taip: kai kas nors iš komandos sukompiliuoja projektą, rezultatai įkeliami į bendrą kešo saugyklą. Kai kitas žmogus patraukia tuos pačius pakeitimus ir bando kompiliuoti, Turbo patikrina remote kešą ir, jei randa atitinkantį hash’ą, tiesiog parsisiunčia gatavus failus.

Tai ypač naudinga CI/CD pipeline’uose. Įsivaizduokite: jūsų CI sistema gali panaudoti build rezultatus iš developer’io mašinos arba iš ankstesnio CI run’o. Tai gali sumažinti CI laiką nuo 20 minučių iki 2 minučių.

Paralelizavimas ir dependency grafas

Turbo automatiškai analizuoja jūsų monorepo struktūrą ir sukuria dependency grafą. Tai reiškia, kad jis žino, kurie paketai gali būti kompiliuojami lygiagrečiai, o kurie turi laukti kitų. Jei turite 8 branduolių procesorių, Turbo panaudos visus juos efektyviai.

Tradicinės sistemos dažnai kompiliuoja viską nuosekliai arba reikalauja, kad patys nustatytumėte paralelizavimo logiką. Turbo tai daro automatiškai. Jis pažiūri į jūsų `package.json` failus, supranta priklausomybes ir sukuria optimalų vykdymo planą.

Praktiškai tai atrodo taip: jei turite tris paketus A, B ir C, kur B priklauso nuo A, o C yra nepriklausomas, Turbo kompiliuos A pirmiausia, tada B ir C lygiagrečiai. Jums nereikia nieko konfigūruoti – tai veikia out of the box.

turbo run build --concurrency=10

Šia komanda galite kontroliuoti, kiek taskų gali būti vykdoma vienu metu. Tai naudinga, jei norite apriboti resursų naudojimą.

Integracijos su esamais įrankiais

Vienas iš dalykų, kuris man asmeniškai labiausiai patinka Turbo, yra tai, kad jis nėra invazyvus. Jums nereikia perprogramuoti viso projekto ar keisti build sistemų. Turbo veikia kaip orkestravimo sluoksnis virš jūsų esamų įrankių.

Naudojate Webpack? Puiku. Vite? Dar geriau. esbuild? Veikia. Turbo tiesiog koordinuoja, kada ir kaip šie įrankiai yra paleidžiami. Jūsų `package.json` scriptai lieka tokie patys, tik juos paleidžiate per Turbo.

Štai kaip tai atrodo praktikoje. Vietoj `npm run build`, paleidžiate `turbo run build`. Turbo pažiūri į visus workspace’us, suranda visus paketus, kurie turi build scriptą, ir juos vykdo protinga tvarka su kešavimu ir paralelizavimu.

Integracijos su CI sistemomis taip pat yra paprastos. Turbo veikia su GitHub Actions, GitLab CI, CircleCI, Jenkins – su viskuo. Tiesiog įdiekite Turbo kaip dependency ir naudokite jį vietoj įprastų npm/yarn komandų.

Realūs performance gerinimo pavyzdžiai

Kalbėkime apie skaičius. Viename projekte, su kuriuo dirbau, turėjome monorepo su 15 paketų. Pilnas build su testais užtrukdavo apie 12 minučių naudojant Lerna. Po migracijos į Turbo, pirmasis build užtruko 8 minutes, o visi paskesni (su kešu) – apie 45 sekundes. Tai yra 16x greičiau.

Kitas pavyzdys: CI pipeline’e, kur ankščiau kiekvienas commit’as reiškė 20 minučių laukimą, dabar vidutiniškai užtrunka 3-4 minutes. Tai todėl, kad dauguma pakeitimų paliečia tik vieną ar du paketus, o Turbo žino, kad kitų perkompiliuoti nereikia.

Bet ne viskas yra rožėmis kvepiantis. Pirmasis build su Turbo gali būti net šiek tiek lėtesnis nei be jo, nes Turbo turi sukurti dependency grafą ir inicializuoti kešą. Bet jau antrasis ir visi paskesni build’ai yra žymiai greitesni.

Taip pat verta paminėti, kad remote kešavimas tikrai veikia. Kai naujas developer’is prisijungia prie projekto ir daro pirmąjį build, jis gali panaudoti visus kešuotus rezultatus iš kitų komandos narių. Tai reiškia, kad onboarding procesas tampa žymiai greitesnis.

Praktiniai patarimai pradedantiesiems ir pažengusiems

Jei planuojate pradėti naudoti Turbo, štai keletas patarimų iš asmeninės patirties. Pirma, pradėkite mažai. Nereikia iš karto migruoti viso projekto. Galite pradėti nuo vieno workspace’o ar kelių paketų ir palaipsniui plėsti.

Antra, skirkite laiko `turbo.json` konfigūracijai. Nors Turbo veikia gerai su default nustatymais, tikrai optimali konfigūracija gali duoti dar geresnių rezultatų. Ypač svarbu teisingai nurodyti `outputs` – tai failai, kurie bus kešuojami. Jei praleisti svarbius failus, kešavimas neveiks tinkamai.

Trečia, naudokite `–dry-run` ir `–graph` flags. `turbo run build –dry-run` parodys, kas bus vykdoma be faktinio vykdymo. `turbo run build –graph` sugeneruos vizualų dependency grafo atvaizdą. Tai neįtikėtinai naudinga debuginimui ir supratimui, kaip jūsų projektas struktūruotas.

Ketvirta, jei naudojate remote kešavimą, įsitikinkite, kad jūsų CI sistema turi tinkamas teises. Turbo naudoja token’us autentifikacijai, ir jums reikės sukonfigūruoti aplinkos kintamuosius tiek lokaliose mašinose, tiek CI sistemoje.

Penkta, stebėkite kešo dydį. Laikui bėgant, lokalus kešas gali užimti nemažai vietos. Turbo turi komandas kešo valymui: `turbo prune` pašalina senus, nebereikalingus kešo įrašus.

Ką Turbo reiškia ateičiai ir kada jo nenaudoti

Turbo atstoja naują bangą build įrankių, kurie supranta, kad moderniems projektams reikia modernių sprendimų. Monorepo struktūros niekur nedings – jos tik taps populiaresnės. Ir įrankiai kaip Turbo padaro jas praktiškesnes net mažesnėms komandoms.

Tačiau būkime sąžiningi – Turbo nėra silver bullet. Jei turite mažą projektą su vienu ar dviem paketais, Turbo overhead gali būti didesnis nei nauda. Taip pat, jei jūsų build procesai yra labai specifiniai ar naudojate egzotiškus įrankius, integracija gali būti sudėtingesnė.

Turbo tikrai spindi dideliuose projektuose su daug tarpusavyje susijusių paketų. Jei jūsų komanda turi daugiau nei 5 žmones ir monorepo su bent 5-10 paketų, Turbo tikriausiai sutaupys jums daug laiko ir nervų. Ypač jei jau naudojate Vercel infrastruktūrą, integracija yra beveik triviali.

Dar vienas aspektas – mokymosi kreivė. Nors Turbo yra gana intuityvus, vis tiek reikia laiko suprasti, kaip jis veikia, kaip konfigūruoti pipeline’us, kaip debuginti problemas. Bet šis investuotas laikas tikrai atsipirks, ypač ilgalaikėje perspektyvoje.

Turborepo ekosistema auga. Vercel aktyviai investuoja į įrankį, community yra gyva, dokumentacija gera. Tai nėra eksperimentinis projektas, kuris gali būti apleistas po metų – tai rimtas enterprise-level įrankis su aiškia vizija ir roadmap. Jei dar neišbandėte Turbo savo monorepo projektams, dabar yra puikus laikas pradėti. Pradėkite su paprasta konfigūracija, eksperimentuokite su kešavimu, ir greitai pamatysite, kodėl tiek daug komandų pereina prie šio sprendimo.

Daugiau

Hetzner Cloud: Europos VPS alternatyva