Így csökkentsd egy Node.js artifact méretét

A szoftverfejlesztés manapság sok esetben a meglévő építőkockák egymásra helyezéséről szól. Azonban ezt érdemes okosan csinálni, hogy az építőkockákból csak annyi dolgot használjunk, amennyire ténylegesen szükségünk van.

Ha erre nem figyelünk, könnyen úgy járhatunk, mint ahogyan az az alábbi képen látható: 

 

Remek dolog, hogy szinte már mindenre van már kész megoldás az npm-en, de azt is érdemes tudni, hogyan lehet a lehető legkisebbre csökkenteni a csomagok méretét.

Te mit tennél, ha szükséged lenne valamire, amit korábban már biztosan megcsinált valaki – például számok ezres tagolása egy input mezőben? Szerencsére erre könnyű választ adni: felmész az npm oldalára, beírod a keresőszavakat és biztosan találsz valami jó megoldást. Általánosságban is igaz, hogy szinte már nincs olyan angol főnév, amire ne készült volna npm-es csomag. Ezek után már használhatod is, ha kiadod, hogy

a “–save” rövidíthető “-S”-re, vagy újabb npm-et használva teljesen el is hagyható, úgyis beteszi a package.json-ba.

Abba most ne menjünk bele hogy az npm-et saját maga által kitalált csomagkezelővel, vagy mással (például yarn) használjuk. Általában nem az “npm i xy” szokta kitenni a fejlesztés jelentős részét, illetve megnéznék egy statisztikát arról, hogy az itt töltött 5-10-20 másodperc mekkora arányt képvisel projekt többi részéhez képest.

Függőségek felosztása

A -g kapcsolóval globálisan lehet telepíteni függőséget, így ez közvetlenül nem fogja növelni a kódbázis méretét növelni, de ez több kárt okoz, mint hasznot hoz. Előfordulhat ugyanis, hogy két fejlesztő gépén két különböző verziós globálisan telepitett holmi van, amelyek akár lényegesen eltérhetnek egymástól. Az is megtörténhet, hogy vagy egy másik fejlesztő gépén nincs is telepítve az a függőség, amit globálisan szeretnénk használni. Szóval a globális telepítés meglehetősen kockázatos is lehet, hiszen így azt kockáztatjuk, hogy másnál esetleg nem fog működni a kódunk, csak előzetes beállítások után.

A lényeg, hogy az új függőség bekerült a package.json-ba. Na de hova? dependency, vagy devDependency? Nagyon nem mindegy, mert production-re buildeléskor, csak az előbbi települ. Ezzel is lehet okosan méretet csökkenteni, de azért érdemes tisztában lenni azzal, hogy melyik függőséget mire akarjuk használni.

Kliens oldal vs. szerver oldal

A legjobb, ha ezeket külön lehet választani két külön package.json-ba. Hogy miért? Azért, mert egy kliens oldali build (pl less→css transzformáció) előállításához használt nodejs libek közül semmi sem kell a csomagba! Ezzel ellentétben, ha nodejs szervert használsz prod környezetben, akkor az ahhoz szükséges függőségek nagyon is kellenek a csomagba, mert enélkül nem fog működni.

Nem mindig a szokásos a jó

Ha emlékszel, onnan indultunk, hogy szinte mindenre van már kész megoldás. Ezt szerencsére már egészen sokan tudják, ezért a legtöbb libnek sok függősége van. Így alakulhat ki az, hogy egy viszonylag szerény funkcionalitású alkalmazás több mint egy gigabyte méretű csomagot produkál optimalizálások nélkül, hiszen több száz függőség kerül bele közvetett módon.

Mit lehet tenni ilyen esetben? Csak egyetlen konkrét példát kiragadva: ha nincs szükség sütik kezelésére, vagy sokrétű url-kezelésre, csak szeretnél egyetlenegy url-t biztosítani, ahol be lehet szólni az appnak, akkor nem biztos hogy célszerű az express modult behúzni a saját 50 függőségével együtt. Erre láthatsz egy példát itt.

Persze amint bonyolódik a helyzet, máris alkalmazkodni kell az új bonyolultabb helyzethez, és máris jobb választás lehet az express használata. A lényeg az, hogy ésszel kell csinálni a függőségek behúzását és időben kell eldöntened, hogy mit mire akarsz használni.

Ezek után ha már nagyon okosan szét- majd összeszerveztük a függőségeket, még mindig több száz megás csomagunk lehet.

Nézzünk bele, mi mindenből áll ez össze

Nos, a node-os fejlesztők nem mindig jól használják az npm-et, ezért bekerülnek olyan fájlok is, amiknek github-on vagy travis-ban van jelentősége, de letölteni egy project függőségeként már nem annyira hasznos ezeket. Erre a problémakörre szakosodott a node-prune go nyelven írt library, amivel a futtatáshoz nem szükséges fájlokat lehet eltávolítani a csomagból. Ilyen például a readme.md, amire futtatás közben semmi szükség. Ennek giten van létjogosultsága, de letöltve és a csomagba téve kevésbé…

Ezen kívül meg van még vagy 100 hasonló minta a csomagban, érdemes belenézni a forrásába is.

Azt már csak halkan jegyzem meg, hogy ezeket a mintákat felvehetjük mi is úgy, hogy kimaradjon a csomagból és máris egy go-s csomaggal kevesebbünk van.

Végül az eredmény: meddig juthatsz el, ha a fentieket mind elvégezted?

Egy konkrét esetben mi 1030 megabyte-ról indultunk és egy 27 megabyte-os csomag lett a vége. Biztos lehet még lecsipegetni belőle, de elsőre azért ez nem is rossz eredmény.