Jak si přehledně uspořádat složku s JavaScriptem a nezbláznit se

Javascript

Co je adresář JavaScript kódu

Adresář JavaScript kódu je v podstatě obyčejná složka v souborovém systému projektu, do které se ukládají soubory s příponou .js, případně .mjs nebo .cjs, pokud se v projektu pracuje s moduly v jejich čistší podobě. Na první pohled jde o naprosto triviální věc – vytvoříte si složku, pojmenujete ji třeba js, scripts nebo src, a tam házíte veškerý kód, který má v aplikaci něco dělat. Ve skutečnosti ale tato zdánlivě banální organizační jednotka tvoří páteř celého projektu a způsob, jakým je tento adresář strukturovaný, výrazně ovlivňuje čitelnost, udržovatelnost i rychlost vývoje.

V praxi se s takovým adresářem setkáte prakticky v každém webovém projektu, ať už jde o jednoduchou statickou stránku s pár interaktivními prvky, nebo o rozsáhlou aplikaci postavenou na frameworcích typu React, Vue či Angular. Rozdíl je především v míře komplexnosti – zatímco u malého projektu vám bohatě postačí jeden soubor main.js umístěný v jediné složce, u větších aplikací se adresář JavaScript kódu postupně rozrůstá do podoby promyšlené hierarchie podsložek, kde každá odpovídá určité logické části aplikace.

Typická struktura takového adresáře často obsahuje oddělené složky pro komponenty, pro pomocné funkce (utils nebo helpers), pro práci s API a daty, pro konfigurační soubory, případně pro testy. Díky tomu se v kódu dokáže zorientovat nejen autor samotný, ale i kdokoliv další, kdo se k projektu později připojí. Je to podobné jako s uspořádáním věcí v domácnosti – pokud máte vše naházené v jedné místnosti, najít cokoliv trvá dlouho a je to frustrující, zatímco jasně oddělené regály a poličky vám umožní okamžitě vědět, kam sáhnout.

Důležitým aspektem je také to, že adresář JavaScript kódu bývá úzce provázaný s nástroji pro sestavování aplikace, tedy s tzv. bundlery jako Webpack, Vite nebo Rollup. Tyto nástroje očekávají určitou konvenci v umístění souborů a na základě ní pak generují výsledný, optimalizovaný kód určený pro nasazení do produkčního prostředí. Pokud je adresářová struktura chaotická nebo nekonzistentní, může to zbytečně komplikovat konfiguraci těchto nástrojů a prodlužovat čas potřebný k sestavení celé aplikace.

Nezanedbatelnou roli hraje i verzovací systém Git, kde se právě adresář s JavaScriptem často stává centrem veškerých změn a commitů. Díky přehledné struktuře je mnohem snazší sledovat historii úprav, identifikovat, kde došlo k chybě, a provádět code review v týmu. Mnoho vývojářů si navíc oblíbilo doplnění tohoto adresáře o soubory s konfigurací lintování a formátování kódu, díky čemuž si celý tým udržuje jednotný styl psaní bez ohledu na to, kdo konkrétní soubor vytvořil.

Typická struktura složky s JS soubory

Když se podíváme na typický JavaScriptový projekt, jen málokdy narazíme na strukturu, kde by všechny soubory ležely volně v jednom kořenovém adresáři. Vývojáři si postupem času vypracovali konvence, které usnadňují orientaci a spolupráci v týmu, a tak se v naprosté většině projektů setkáváme s obdobným rozvržením složek. Nejdůležitějším místem bývá adresář nazvaný src (zkratka pro „source“), kam se ukládá veškerý zdrojový kód aplikace. Uvnitř tohoto adresáře se pak kód dále dělí podle logiky dané aplikace – mohou zde být podsložky pro komponenty uživatelského rozhraní, pro pomocné funkce, pro konfigurační soubory nebo pro práci s daty.

Pokud se jedná o frontendový projekt postavený na některém z moderních frameworků, typicky narazíme na složku components, kde jsou uloženy jednotlivé znovupoužitelné části rozhraní, každá často ve svém vlastním souboru nebo dokonce ve vlastní podsložce obsahující kromě samotného JavaScriptu i styly a testy. Vedle toho bývá k nalezení adresář utils nebo helpers, kam vývojáři ukládají drobné pomocné funkce, které se v projektu opakovaně využívají a nemá smysl je psát znovu na více místech. Časté je také rozdělení podle typu souborů, kdy existuje samostatná složka pro styly, samostatná pro obrázky a jiná statická aktiva a samostatná právě pro skripty psané v JavaScriptu.

U rozsáhlejších aplikací se často objevuje i oddělení podle funkčních celků, takzvaných modulů nebo featur, kdy každá část aplikace – třeba přihlašování uživatele, košík v e-shopu nebo administrace – má svoji vlastní složku obsahující veškerý potřebný kód, včetně JavaScriptových souborů, které se k dané funkci vážou. Tento přístup se označuje jako modulární struktura a je oblíbený zejména v projektech, kde na kódu pracuje více lidí najednou, protože umožňuje pracovat na jednotlivých částech nezávisle na sobě.

Nedílnou součástí bývá také složka tests nebo __tests__, kde se nacházejí testovací skripty ověřující funkčnost jednotlivých částí kódu. Tyto soubory mají obvykle stejnou strukturu jako testovaný kód, jen jsou doplněny o příponu naznačující, že jde o test. Mimo zdrojový kód se v kořenovém adresáři projektu obvykle nachází i složka node_modules, do které se stahují externí knihovny a závislosti spravované pomocí správce balíčků. Tato složka se však do verzovacího systému obvykle nenahrává, protože ji lze kdykoliv znovu vygenerovat na základě konfiguračního souboru.

Výsledná struktura tedy není nahodilá, ale odráží snahu o přehlednost, snadnou údržbu a možnost rychle se zorientovat i v kódu, který napsal někdo jiný. Právě díky zavedeným konvencím dokáže zkušený vývojář otevřít cizí projekt a během chvíle pochopit, kde hledat konkrétní část funkčnosti, aniž by musel procházet každý soubor zvlášť.

Rozdíl mezi zdrojovým a sestaveným kódem

Když se podíváte do libovolné složky nebo adresáře, kde jsou uloženy soubory kódu napsaného v JavaScriptu, dříve nebo později narazíte na zásadní otázku – co z toho je vlastně kód, který psal programátor, a co už je výsledkem nějakého automatizovaného procesu. Tahle otázka je mnohem důležitější, než se na první pohled zdá, protože moderní vývoj webových i serverových aplikací se bez tohoto rozlišení prakticky neobejde.

Zdrojový kód je ta podoba programu, kterou skutečně píše vývojář. Jsou to soubory s příponou .js, případně .ts, pokud se pracuje s TypeScriptem, nebo .jsx a .tsx v případě projektů postavených na Reactu. Tento kód je psán tak, aby byl čitelný pro člověka – obsahuje smysluplné názvy proměnných a funkcí, komentáře vysvětlující logiku, bývá rozdělen do menších modulů a souborů podle zodpovědnosti jednotlivých částí aplikace. Právě v této podobě se kód edituje, prochází code review, verzuje se v Gitu a je to jediná forma, kterou by měl člověk běžně upravovat.

Oproti tomu sestavený kód, často označovaný anglickým termínem build nebo bundle, vzniká až poté, co zdrojový kód projde procesem zpracování pomocí nástrojů jako Webpack, Vite, Rollup nebo esbuild. Tyto nástroje vezmou všechny jednotlivé soubory, poskládají je dohromady, odstraní nepotřebné části, přeloží modernější syntaxi do podoby srozumitelné pro starší prohlížeče a výsledek často ještě minifikují – tedy zbaví ho mezer, odřádkování a zkrátí názvy proměnných na jeden či dva znaky. Výsledkem je soubor nebo několik souborů, které jsou pro člověka prakticky nečitelné, ale pro počítač extrémně efektivní z hlediska rychlosti načítání a zpracování.

Rozdíl mezi oběma typy kódu se nejčastěji projevuje i ve struktuře projektu samotné. Zdrojové soubory bývají umístěny ve složce nazvané src, zatímco výsledek sestavení putuje do adresáře dist nebo build. Toto oddělení není náhodné – je to zavedená konvence, která umožňuje jasně rozlišit, co je potřeba udržovat a upravovat, a co je pouze dočasný výstup generovaný automaticky při každém sestavení projektu. Z tohoto důvodu se složka s výsledným sestaveným kódem téměř nikdy neverzuje v systému jako Git, protože by to vedlo ke zbytečnému duplicitnímu ukládání dat, která lze kdykoliv znovu vygenerovat ze zdrojů.

Další podstatný rozdíl spočívá v tom, že sestavený kód může obsahovat i kód z externích knihoven a závislostí, které byly do projektu přidány přes správce balíčků, typicky npm nebo yarn. Zatímco zdrojový kód obsahuje pouze to, co vývojář skutečně napsal, finální sestavení v sobě spojuje vlastní logiku aplikace s veškerým potřebným kódem třetích stran, takže vznikne jeden funkční a samostatně spustitelný celek, který lze nasadit na server nebo nahrát do prohlížeče bez nutnosti řešit jednotlivé závislosti zvlášť.

Soubory src lib a dist

Kdo se alespoň jednou podíval do struktury nějakého většího JavaScriptového projektu, určitě narazil na trojici adresářů, která se tam objevuje téměř pokaždé – src, lib a dist. Na první pohled by se mohlo zdát, že jde o libovolně pojmenované složky bez hlubšího významu, ve skutečnosti ale každá z nich plní zcela odlišnou roli v životním cyklu kódu, od jeho napsání až po nasazení do produkčního prostředí.

Adresář src, což je zkratka od anglického slova „source“, tedy zdroj, obsahuje původní zdrojové soubory tak, jak je napsal vývojář. Jsou to soubory s příponou .js, případně .jsx nebo .ts u projektů používajících TypeScript, které ještě neprošly žádnou úpravou, kompilací ani minifikací. Právě zde probíhá veškerá skutečná práce – zde se píšou nové funkce, upravuje logika aplikace, řeší chyby a testuje nová funkcionalita. Kód ve složce src bývá rozdělen do menších, logicky oddělených souborů a podsložek, aby se v něm dalo snadno orientovat. Vývojáři sem obvykle ukládají i komponenty, pomocné funkce, konfigurační soubory a vše, co souvisí s vývojem aplikace v jejím nejsyrovějším stavu.

Oproti tomu lib, zkratka slova „library“ neboli knihovna, slouží jako místo pro znovupoužitelné kusy kódu, které už jsou v nějaké míře hotové a stabilní. Může jít o vlastní pomocné funkce, moduly nebo celé mini-knihovny, které vývojář vytvořil a používá napříč různými částmi projektu, případně i v jiných projektech. Zatímco src představuje živý, neustále se měnící kód, lib bývá o něco klidnější místo – kód zde se mění méně často, protože už prošel určitým vývojem a testováním. V některých projektech se do lib ukládají i externí knihovny třetích stran, i když dnes je mnohem běžnější spravovat tyto závislosti pomocí správců balíčků, jako je npm nebo yarn, a ukládat je do složky node_modules.

Poslední ze zmíněné trojice, dist, což je zkratka pro „distribution“, tedy distribuce, obsahuje finální, zkompilovaný a optimalizovaný kód, který je připravený k nasazení. Soubory v této složce vznikají automaticky pomocí nástrojů jako Webpack, Rollup, Vite nebo Babel, které vezmou zdrojový kód ze složky src, zpracují ho, minifikují, odstraní nepotřebné komentáře a mezery, případně sloučí více souborů do jednoho, aby výsledná aplikace byla co nejrychlejší a nejefektivnější pro koncového uživatele. Právě obsah složky dist je ten, který se nakonec nahrává na server nebo se z něj generuje produkční verze webové stránky či aplikace.

Tato jasná struktura přináší do vývoje pořádek a srozumitelnost, zejména u týmových projektů, kde je důležité, aby každý vývojář věděl, kde hledat zdrojový kód, kde znovupoužitelné moduly a kde výsledný produkt. Díky oddělení src, lib a dist se také snadněji spravuje verzování, protože do repozitáře na Gitu se obvykle nenahrává obsah složky dist, jelikož jde o automaticky generovaný výstup, který lze kdykoliv znovu vytvořit ze zdrojových souborů.

Role souboru package.json

V každé složce nebo adresáři souborů kódu napsaných v jazyce JavaScript, pokud se jedná o skutečný projekt a ne jen o pár osamocených skriptů, narazíte dříve nebo později na soubor s názvem package.json. Tento soubor sice na první pohled vypadá jako obyčejný textový dokument plný závorek a dvojteček, ve skutečnosti ale funguje jako jakýsi rodný list a zároveň řídicí panel celého projektu. Je to první místo, kam se podívá jak zkušený vývojář, tak nástroj typu npm nebo yarn, když potřebuje zjistit, co se v dané složce vlastně nachází a jak s tím má zacházet.

Struktura adresáře s JavaScriptovým kódem bývá často poměrně rozvětvená – najdete v ní podsložky se zdrojovými soubory, konfigurační soubory, testy, dokumentaci a samozřejmě i soubor package.json, který leží typicky v kořenovém adresáři projektu. Právě jeho umístění není náhodné, protože nástroje pro správu balíčků očekávají, že jej najdou přesně tam, odkud se spouští příkazy jako npm install nebo npm run. Pokud by se tento soubor nacházel hlouběji ve stromové struktuře, celý systém závislostí by se zhroutil a projekt by se stal prakticky nefunkčním.

Obsahově package.json popisuje metadata projektu – jeho název, verzi, autora, licenci, ale hlavně seznam závislostí, tedy externích knihoven a balíčků, bez kterých by aplikace nemohla fungovat. Díky tomu stačí celou složku se zdrojovým kódem přenést na jiný počítač nebo nahrát na server, spustit jediný příkaz a nástroj sám stáhne a nainstaluje vše potřebné do podsložky node_modules. Bez tohoto souboru by bylo nutné všechny knihovny instalovat ručně a pamatovat si přesně, jaké verze byly použity, což by u větších projektů bylo prakticky neproveditelné.

Kromě závislostí obsahuje package.json také takzvané skripty, tedy zkratky pro často používané příkazy. Vývojář tak nemusí pamatovat dlouhé a složité sekvence příkazů pro spuštění testů, sestavení produkční verze nebo spuštění vývojového serveru – stačí napsat jednoduchý příkaz jako npm start nebo npm test a package.json se postará o to, aby se spustilo přesně to, co je potřeba. Tato vlastnost dělá ze souboru nejen technický dokument, ale i jakousi mapu toho, jak s projektem pracovat.

Důležitá je rovněž role package.json při verzování a sdílení kódu. Když vývojář nahrává projekt na platformy jako GitHub, samotná složka node_modules se obvykle nenahrává, protože by byla zbytečně objemná. Místo toho stačí, aby byl přiložen právě package.json spolu se souborem package-lock.json, který uchovává přesné verze všech závislostí. Kdokoliv jiný pak může projekt stáhnout a během chvilky obnovit celé prostředí tak, jak jej měl původní autor.

Lze tedy říct, že package.json tvoří pomyslné srdce každé moderní JavaScriptové složky, protože propojuje kód, jeho závislosti, způsob spouštění i informace o samotném projektu do jednoho přehledného a strojově čitelného dokumentu, bez kterého by se dnešní vývoj v tomto jazyce neobešel.

Moduly a jejich organizace do složek

Organizace JavaScriptového kódu do složek patří mezi ty dovednosti, které se naučíte spíš praxí a vlastními chybami než čtením nějaké příručky. Když si vezmete prakticky jakýkoliv seriózní projekt, ať už jde o jednoduchou webovou aplikaci nebo rozsáhlý backendový systém v Node.js, vždy narazíte na nějakou formu adresářové struktury, která odděluje jednotlivé moduly podle jejich funkce. Je to podobné jako v papírové kanceláři, kde si také nedáváte všechny dokumenty do jedné hromady, ale třídíte je do šanonů podle témat.

Modul je v podstatě samostatný soubor nebo skupina souborů, které obsahují určitou logicky uzavřenou funkcionalitu a kterou lze pomocí příkazů import a export znovu použít v jiných částech aplikace. Místo toho, abyste měli tisíce řádků kódu v jednom souboru, rozdělíte si aplikaci na menší, přehlednější celky. Jeden modul se třeba stará o komunikaci s databází, jiný o validaci formulářů, další o práci s datumy a podobně. Tahle modularita je jedním ze základních pilířů moderního JavaScriptu a bez ní by se dnešní komplexní aplikace prakticky nedaly udržovat.

Co se týče samotné organizace do složek, existuje několik přístupů, které se v praxi běžně používají. Jedním z nejrozšířenějších je takzvané dělení podle typu souboru, kdy máte samostatnou složku pro komponenty, jinou pro služby, další pro utility funkce, pomocné nástroje nebo konfigurace. Tento přístup funguje dobře u menších projektů, kde se dá snadno zorientovat, i když je počet souborů v jednotlivých složkách poměrně nízký.

Druhým oblíbeným způsobem je dělení podle funkčnosti nebo domény, tedy podle toho, čeho se daná část aplikace vlastně týká. Pokud píšete třeba e-shop, budete mít složku pro vše, co souvisí s objednávkami, jinou pro uživatele, další pro produkty a tak dále. Uvnitř každé takové složky pak najdete komponenty, logiku i pomocné soubory, které se k danému tématu vztahují. Tento přístup se v posledních letech stal preferovanou volbou u větších a komplexnějších projektů, protože při úpravě jedné funkcionality nemusíte skákat mezi desítkami různých složek roztroušených po celém projektu.

Důležitou roli hraje také soubor, který bývá označován jako index nebo vstupní bod složky. Tento soubor často slouží k tomu, aby shromáždil a znovu exportoval obsah celé složky, takže ostatní části aplikace mohou importovat potřebné věci jedním jednoduchým příkazem, aniž by musely znát přesnou vnitřní strukturu dané složky. Je to podobné jako rejstřík na začátku knihy, díky kterému nemusíte procházet celý obsah, abyste našli to, co hledáte.

Nelze opomenout ani oddělení testovacích souborů, které se buď umisťují přímo vedle testovaného modulu, nebo do samostatné složky s testy, podle preferencí týmu a zvoleného nástroje pro testování. Stejně tak je dobrým zvykem mít oddělenou složku pro konfigurační soubory a proměnné prostředí, aby nedošlo k míchání nastavení s produkčním kódem aplikace.

JavaScriptová složka je jako skicář programátora – plná nedokončených nápadů, zapomenutých funkcí a jednoho souboru, který se nikdo neodváží smazat, protože by se mohlo něco rozbít.

Bohumil Krejčí

Konvence pojmenování souborů a adresářů

Konvence pojmenování souborů a adresářů v JavaScriptových projektech nejsou nikde striktně nařízeny zákonem ani oficiální specifikací jazyka, přesto se v průběhu let v komunitě ustálily zvyklosti, které usnadňují orientaci v kódu a spolupráci v týmu. Když se podíváte na libovolný modernější projekt postavený na frameworcích jako React, Vue nebo Angular, všimnete si, že struktura adresářů i názvy souborů se řídí poměrně konzistentními pravidly, byť se mezi jednotlivými komunitami mírně liší.

Pro samotné soubory s kódem se nejčastěji používá camelCase nebo kebab-case. V camelCase zápisu první slovo začíná malým písmenem a každé další slovo velkým, takže vznikají názvy jako userController.js nebo fetchData.js. Kebab-case naproti tomu odděluje slova pomlčkou a všechna písmena jsou malá, což dává názvy typu user-controller.js nebo fetch-data.js. Oba přístupy mají své zastánce a často záleží na konvenci konkrétního frameworku nebo stylového průvodce, který tým používá. U komponent v Reactu se zase často setkáte s PascalCase, kde každé slovo začíná velkým písmenem, protože samotný název souboru odpovídá názvu exportované komponenty, například UserProfile.jsx nebo NavigationBar.jsx.

Pokud jde o testovací soubory, zavedeným zvykem je přidávat k původnímu názvu souboru příponu jako .test.js nebo .spec.js, díky čemuž testovací nástroje snadno rozpoznají, které soubory mají spouštět, a vývojář hned vidí, k jakému zdrojovému souboru test patří.

Co se týče adresářové struktury, složka nebo adresář souborů kódu napsaných v jazyce JavaScript bývá typicky pojmenována jednoduše src, což je zkratka od slova source. Uvnitř této složky se pak kód dále dělí podle logiky aplikace, nejčastěji na podsložky jako components, utils, services, hooks nebo helpers. Názvy těchto adresářů se téměř vždy píší malými písmeny a v množném čísle, protože obsahují více souborů podobného typu. U adresářů se stejně jako u souborů preferuje kebab-case, pokud název obsahuje více slov, takže se setkáte spíše s user-management než s userManagement jako názvem složky.

Důležitým principem je také konzistence v rámci celého projektu. Pokud si tým jednou zvolí určitou konvenci, je žádoucí ji dodržovat napříč všemi soubory a složkami, protože míšení stylů vede ke zmatku a ztěžuje orientaci novým členům týmu. Mnoho projektů proto konvence pojmenování explicitně dokumentuje v souboru README nebo v samostatném stylovém průvodci, na který se mohou přispěvatelé kdykoliv odkázat. Nástroje jako ESLint nebo Prettier navíc umožňují automatizovanou kontrolu dodržování těchto pravidel, což výrazně snižuje riziko lidské chyby a udržuje kódovou základnu přehlednou i při rozrůstání projektu do stovek nebo tisíců souborů.

Oddělení komponent testů a konfigurace

Při práci na jakémkoliv JavaScriptovém projektu se dříve nebo později ukáže, že nedbalé rozmístění souborů po adresářích se mstí na čitelnosti i udržovatelnosti celé aplikace. Jedním z principů, které se v praxi osvědčily snad nejvíc, je důsledné oddělení testovacích souborů a konfiguračních souborů od samotné produkční logiky. Jakmile se testy, mocky, konfigurace pro různá prostředí a zdrojový kód promíchají v jedné složce, hledání konkrétního souboru se mění v archeologický výzkum a nový člen týmu se v takovém projektu orientuje mnohem déle, než by bylo zdrávo.

V praxi se osvědčilo vytvořit samostatný adresář, často pojmenovaný tests, __tests__ nebo spec, který kopíruje strukturu zdrojového kódu, ale obsahuje výhradně testovací soubory. Díky tomu lze snadno dohledat, ke kterému modulu daný test patří, aniž by bylo nutné procházet desítky souborů v jedné složce. Některé týmy preferují umísťovat testy přímo vedle testovaného souboru s příponou jako .test.js nebo .spec.js – i tento přístup je naprosto legitimní, pokud je dodržován konzistentně napříč celým projektem. Důležité je, aby si tým zvolil jeden přístup a ten pak striktně dodržoval, protože nekonzistence v organizaci souborů bývá jedním z nejčastějších zdrojů zmatků při code review i při onboardingu nových vývojářů.

Stejně pečlivě je potřeba zacházet i s konfiguračními soubory. Nastavení pro buildovací nástroje, proměnné prostředí, konfigurace pro linter nebo formátovač kódu a nastavení CI/CD pipeline by neměly být roztroušené mezi zdrojovými soubory aplikace. Mnoho projektů proto využívá kořenový adresář výhradně pro konfigurační soubory, případně vytváří samostatnou složku config, kde se soustředí veškerá nastavení týkající se prostředí, ve kterém aplikace běží. Tento přístup má praktickou výhodu i v tom, že se konfigurace snadno odlišuje od byznysové logiky a nehrozí, že se citlivé údaje nebo nastavení prostředí omylem dostanou do míst, kde by neměly být.

Oddělení testů a konfigurace od zbytku adresářové struktury JavaScriptového projektu má také praktický dopad na nástroje, které se v projektu používají. Testovací frameworky i buildovací nástroje totiž často očekávají určitou konvenci v pojmenování a umístění souborů, a pokud se jí projekt drží, odpadá spousta zbytečného ručního nastavování. Navíc se tím usnadňuje i práce s nástroji pro kontinuální integraci, které potřebují jasně vědět, které soubory spouštět jako testy a které považovat za konfigurační.

Z dlouhodobého pohledu je tato organizace investicí, která se vyplatí zejména u větších projektů s více přispěvateli. Čistě oddělené testy, konfigurace a produkční kód totiž výrazně zjednodušují refaktoring, protože změna v jedné části aplikace nevyžaduje prohledávání celé složkové struktury, zda náhodou nedošlo k zásahu do něčeho, co s danou úpravou vůbec nesouvisí.

Využití node_modules a závislostí

Složka node_modules patří k těm nejrozpoznatelnějším adresářům, se kterými se vývojář v JavaScriptu setká hned po založení prvního projektu spravovaného přes npm nebo yarn. Jakmile se spustí instalace balíčků definovaných v souboru package.json, správce balíčků vytvoří právě tuto složku a nahrne do ní veškeré stažené knihovny včetně jejich vlastních závislostí. Výsledkem bývá struktura, která se na první pohled zdá nepřehledná, protože obsahuje desítky až tisíce vnořených podsložek, z nichž mnohé si vývojář nikdy sám nenainstaloval – jedná se o tzv. tranzitivní závislosti, tedy balíčky, které vyžadují jiné balíčky.

Velikost složky node_modules bývá pověstná a často se o ní vtipkuje jako o jedné z nejtěžších věcí na internetu. U rozsáhlejších projektů, zejména těch postavených na frameworcích jako React, Angular nebo Vue, může tato složka zabírat stovky megabajtů až jednotky gigabajtů diskového prostoru. Z tohoto důvodu se node_modules téměř vždy přidává do souboru .gitignore, aby se nedostala do verzovacího systému Git. Namísto sdílení samotných souborů se mezi vývojáři předává pouze soubor package.json a package-lock.json (případně yarn.lock), ze kterých lze celou strukturu znovu sestavit příkazem npm install nebo yarn install.

Práce se závislostmi má ale i svou méně viditelnou stránku, která souvisí s bezpečností a stabilitou projektu. Každá knihovna stažená do node_modules s sebou nese určité riziko, protože vývojář přebírá odpovědnost za kód, který sám nenapsal a často si jej ani nepročetl. Proto se doporučuje pravidelně kontrolovat závislosti pomocí nástrojů jako npm audit, které dokážou odhalit známé bezpečnostní zranitelnosti v nainstalovaných balíčcích. Stejně důležité je sledovat i to, kolik verzí stejné knihovny se v projektu nakonec nahromadí – díky tranzitivním závislostem se totiž často stává, že se v node_modules objeví hned několik různých verzí jednoho a téhož balíčku, což zbytečně zvětšuje výslednou velikost aplikace.

Soubor package-lock.json hraje v tomto ekosystému klíčovou roli, protože zajišťuje, že všichni členové týmu i produkční prostředí používají přesně stejné verze závislostí. Bez tohoto zámku by mohlo docházet k situacím, kdy aplikace funguje na jednom počítači, ale na druhém se kvůli jiné verzi nějaké knihovny chová odlišně nebo vůbec nespustí. Moderní nástroje pro sestavování aplikací, jako jsou Webpack, Vite nebo esbuild, navíc dokážou z obrovského množství souborů v node_modules vybrat jen to, co je skutečně potřeba, a zbytek do finálního balíčku vůbec nezahrnout, čímž se minimalizuje velikost výsledného kódu určeného pro nasazení do produkce.

Nástroje pro sestavení a bundlování

Ve chvíli, kdy se adresář s JavaScriptovým kódem rozroste na desítky nebo stovky souborů, rozdělených do modulů, komponent a pomocných knihoven, nelze už spoléhat na to, že prohlížeč načte každý soubor zvlášť. Právě zde nastupují nástroje pro sestavení a bundlování, které z rozptýlené struktury složek vytvoří jeden nebo několik optimalizovaných balíčků určených pro produkční nasazení. Jejich úkolem je projít celý adresářový strom, pochopit závislosti mezi jednotlivými soubory pomocí příkazů import a export, a poskládat je do výsledného souboru tak, aby pořadí načítání odpovídalo logice aplikace a nedocházelo k chybám způsobeným chybějícími referencemi.

Typ adresáře / složky Obvyklý název Účel Typické soubory Běžné použití
Zdrojová složka src/js nebo src/scripts Uchovává nezpracovaný (nekompilovaný) JavaScript kód psaný vývojářem .js, .jsx, .ts, .tsx Vývoj aplikací, úprava a verzování kódu
Výstupní složka dist/js nebo build/js Obsahuje zkompilovaný a minifikovaný kód připravený pro nasazení .min.js, .bundle.js Nasazení na produkční server, rychlejší načítání stránky
Složka knihoven node_modules Ukládá externí balíčky a závislosti instalované přes správce balíčků .js, .json, .ts Použití knihoven jako React, jQuery nebo Lodash
Složka skriptů na straně klienta public/js nebo assets/js Obsahuje skripty přímo odkazované v HTML souborech .js Interaktivní prvky webu, animace, validace formulářů
Složka testů tests/js nebo __tests__ Shromažďuje testovací skripty pro ověření funkčnosti kódu .test.js, .spec.js Automatizované testování pomocí nástrojů jako Jest nebo Mocha
Konfigurační složka config nebo scripts Obsahuje pomocné a konfigurační JavaScript soubory projektu .config.js, .js Nastavení build nástrojů jako Webpack nebo Vite

Mezi nejrozšířenější nástroje tohoto typu patří Webpack, který se dlouhodobě stal jakýmsi průmyslovým standardem pro komplexní projekty. Umožňuje nejen bundlování JavaScriptu, ale i zpracování CSS stylů, obrázků, fontů a dalších statických zdrojů, které se běžně nacházejí ve stejné nebo podřízené složce projektu. Díky systému loaderů a pluginů dokáže Webpack transformovat kód psaný v modernější syntaxi nebo v jazycích, které se do čistého JavaScriptu kompilují, a zároveň provádět takzvaný tree shaking, tedy odstraňování nepoužívaného kódu, což výrazně snižuje velikost výsledného balíčku.

Vedle Webpacku si oblibu získal i Vite, který se zaměřuje především na rychlost vývoje díky využití nativních ES modulů v prohlížeči během vývojové fáze a teprve při produkčním sestavení přepíná na efektivní bundlování pomocí nástroje Rollup. Tento přístup výrazně zkracuje dobu potřebnou k opětovnému načtení aplikace po každé úpravě kódu, což je obzvlášť patrné u rozsáhlejších projektů s mnoha vnořenými složkami a komponentami.

Dalším významným hráčem je esbuild, napsaný v jazyce Go, který vyniká extrémní rychlostí zpracování díky paralelnímu zpracování souborů a nízké režii. Je často využíván jako součást jiných nástrojů, ale lze jej nasadit i samostatně pro rychlé bundlování menších až středně velkých projektů. Podobně se v určitých scénářích uplatňuje i Parcel, který se prezentuje jako nástroj prakticky bez nutnosti konfigurace, schopný automaticky rozpoznat strukturu projektu a zvolit vhodný způsob zpracování souborů.

Kromě samotného bundlování plní tyto nástroje i další důležité funkce, jako je minifikace kódu, tedy odstranění zbytečných mezer, komentářů a zkrácení názvů proměnných, čímž se snižuje velikost přenášených dat. Dále umožňují takzvané code splitting, tedy rozdělení výsledného balíčku na menší části, které se načítají až ve chvíli, kdy je uživatel skutečně potřebuje, což zlepšuje výkon celé aplikace. Nezanedbatelnou roli hraje i podpora zdrojových map, díky nimž lze i v minifikovaném produkčním kódu snadno dohledat původní umístění chyby přímo ve zdrojové složce projektu.

Výběr konkrétního nástroje často závisí na velikosti projektu, požadavcích na rychlost vývoje a na tom, jaké frameworky a knihovny se v dané adresářové struktuře používají, nicméně bez některého z těchto řešení se dnes téměř žádný rozsáhlejší JavaScriptový projekt neobejde.

Doporučené postupy pro přehlednost projektu

Struktura složky s JavaScriptem je často první věc, podle které poznáte, zda se v projektu vyznáte během pěti minut, nebo zda strávíte půl dne hledáním, kde se vlastně volá ta jedna funkce, co padá v produkci. Dobře zorganizovaný adresář kódu není jen estetická záležitost pro perfekcionisty – je to investice do času, který ušetří každý další člověk, jenž se k projektu dostane, včetně vás samotných po půl roce, kdy si na vlastní rozhodnutí už nevzpomenete.

Základem je oddělit zdrojový kód od všeho ostatního. Složka src by měla obsahovat výhradně to, co se skutečně píše a upravuje – tedy samotnou logiku aplikace, zatímco vygenerované soubory, závislosti z node_modules nebo buildovací výstupy do ní rozhodně nepatří. Je dobrým zvykem mít jasně oddělenou složku dist nebo build, kam směřuje výstup kompilace, a tuto složku ignorovat ve verzovacím systému pomocí souboru .gitignore. Smíchání zdrojů s výstupy totiž dříve nebo později vede k chaosu, kdy někdo omylem upravuje zkompilovaný soubor místo originálu.

Uvnitř samotné složky src se vyplatí dělit kód podle funkční oblasti, nikoliv podle typu souboru. Místo toho, aby existovala jedna složka se všemi komponentami, druhá se všemi službami a třetí se všemi styly, je přehlednější seskupovat soubory podle toho, k jaké části aplikace patří – tedy například vše související s přihlašováním uživatele na jedno místo, vše týkající se košíku v e-shopu na druhé. Tento přístup, často označovaný jako feature-based struktura, usnadňuje orientaci zejména ve větších projektech, kde by jinak jedna složka s komponentami obsahovala desítky až stovky souborů bez zjevné logiky.

Pojmenování souborů a složek by mělo být konzistentní v celém projektu. Pokud se tým rozhodne používat camelCase pro názvy souborů, neměl by se uprostřed projektu najednou objevit kebab-case nebo podtržítka. Stejně důležité je důsledně pojmenovávat soubory podle jejich obsahu – soubor s funkcemi pro validaci formulářů by měl nést jméno, které tuto funkci jasně vystihuje, nikoliv obecný název typu utils.js, pod kterým se časem nahromadí desítky nesouvisejících funkcí.

Velmi se osvědčuje také oddělovat konfigurační soubory od samotného kódu a udržovat je v kořenovém adresáři projektu, kde je každý očekává. Soubory jako package.json, .eslintrc nebo konfigurace pro webpack by neměly být zanořené hluboko ve struktuře, protože vývojáři i nástroje je potřebují najít rychle a bez zbytečného pátrání.

Neméně podstatné je psát krátký, ale výstižný soubor README, který novému členovi týmu vysvětlí, jak je projekt strukturovaný a kde hledat jednotlivé části. Dokumentace architektury sice zabere trochu času navíc, ale v konečném důsledku šetří mnohem víc hodin, než kolik jich stojí její sepsání.

Nejčastější chyby při organizaci kódu

Jednou z nejrozšířenějších chyb je snaha vměstnat veškerou logiku aplikace do jediného souboru nebo do hrstky obřích souborů, které postupem času nabobtnají na tisíce řádků. Vývojář si zpočátku říká, že si vše uspořádá později, jenže realita je taková, že čím déle se s refaktorováním čeká, tím bolestivější se nakonec stává. Soubory o několika tisících řádcích jsou prakticky neudržitelné a orientace v nich zabere mnohem více času, než kolik by zabralo jejich rozumné rozdělení hned od začátku.

Další velmi častý prohřešek je nekonzistentní pojmenovávání složek a souborů. V jedné části projektu se používá camelCase, v jiné kebab-case, někde se mísí čeština s angličtinou a názvy komponent neodpovídají tomu, co skutečně dělají. Taková nejednotnost sice na první pohled nevypadá jako závažný problém, ale v praxi výrazně zpomaluje orientaci nových členů týmu i samotného autora kódu po pár měsících od napsání. Důsledné dodržování jedné konvence napříč celým projektem je přitom záležitost, kterou lze vyřešit hned na začátku a ušetřit si tak spoustu budoucích komplikací.

Velmi problematické bývá i míchání různých vrstev aplikace do jedné složky. Pokud se v jednom adresáři ocitnou pohromadě komponenty uživatelského rozhraní, logika pro komunikaci s API, pomocné funkce a konfigurace, vzniká chaos, ve kterém je těžké rozpoznat, co kam vlastně patří. Oddělení prezentační vrstvy, byznys logiky a pomocných utilit do samostatných a jasně pojmenovaných složek dokáže výrazně zpřehlednit celý projekt a usnadnit jeho budoucí rozšiřování.

Mnoho vývojářů také podceňuje důležitost indexových souborů a reexportů, což vede k tomu, že importy v kódu jsou zbytečně dlouhé a složité, plné relativních cest typu tři tečky nahoru a pak zase dolů. Tento přístup sice funguje, ale je křehký, protože jakékoliv přesunutí souboru rozbije desítky importů napříč projektem. Řešením je promyšlené využívání absolutních cest a centrálních vstupních bodů pro jednotlivé moduly.

Opomíjeným problémem bývá také nedostatečné oddělení testů od zdrojového kódu, respektive naopak jejich roztroušení po celém projektu bez jasného systému. Když testy nejsou umístěny podle jasné logiky vedle testovaného kódu nebo ve zrcadlené struktuře, časem se stává, že se na ně zapomíná a testovací pokrytí postupně upadá.

Za zmínku stojí i chyba spočívající v tom, že se vývojáři bojí strukturu projektu v průběhu času upravovat. Projekt, který vznikal před rokem, má jiné potřeby než ten samý projekt dnes, a odmítání reorganizace ze strachu z rozbití funkčnosti vede jen k tomu, že se neduhy kumulují a jejich odstranění je stále nákladnější. Pravidelná a promyšlená revize adresářové struktury by proto měla být přirozenou součástí údržby každého delšího JavaScriptového projektu, nikoliv výjimečnou událostí, ke které se přistupuje až ve chvíli, kdy je chaos již nesnesitelný.

Našli jste v článku chybu?

Publikováno: 10. 11. 2026

Kategorie: Programování a vývoj