Hogyan szervezzünk frontend csomagokat monorepóban, nyomon követjük a változásokat az összes projektben, használjuk újra a megosztott könyvtárakat, és készítsünk csomagokat egy modern összeállítási rendszerrel
A komponensek felépítése és különböző csomagokban történő újrafelhasználása arra a következtetésre jutott, hogy szükséges a projektek tartalmának megfelelő megközelítését egyetlen struktúrában megszervezni. Az építési eszközöknek azonosaknak kell lenniük, beleértve a tesztelési környezetet, a lintszabályokat és az összetevőkönyvtárak hatékony erőforrás-elosztását.
Olyan eszközöket kerestem, amelyekkel hatékony és eredményes módszereket hozhatok robusztus, erőteljes kombinációk létrehozására. És ennek eredményeként egy félelmetes trió alakult ki. Ebben a cikkben több csomagot fogunk létrehozni ezekkel az eszközökkel.
Eszközök
Mielőtt elkezdenénk, vizsgáljuk meg, hogy ezek az eszközök mit tesznek.
Lerna: JavaScript projektek kezelése több csomaggal. Optimalizálja a munkafolyamatot a többcsomagos adattárak git és npm segítségével történő kezelése körül.
Vite: építőeszköz, amely gyors hot modul cserét, azonnali ES-modul támogatást, kiterjedt szolgáltatást és bővítménytámogatást biztosít a React számára
Storybook: nyílt forráskódú eszköz a felhasználói felület összetevőinek elkülönített fejlesztésére és rendezésére, amely egyben platformként is szolgál vizuális teszteléshez és interaktív dokumentációk készítéséhez.
Lerna kezdeti beállítás
Az első lépés a Lerna projekt létrehozása lesz. Hozzon létre egy mappát a lerna_vite_monorepo
elemmel, és azon belül futtassa át a npx lerna init
terminálon – ez alapvető fontosságú a Lerna projekt számára. Két fájlt hoz létre – lerna.json
, package.json
– és egy üres mappát (packages
).
lerna.json
– ez a fájl lehetővé teszi a Lerna számára, hogy egyszerűsítse a monorepo konfigurációját, és utasításokat adjon a függőségek összekapcsolására, a csomagok megkeresésére, a verziószámítási stratégiák megvalósítására és a további feladatok végrehajtására.
Vite Initial Setup
A telepítés befejeztével elérhető lesz egy packages
mappa. Következő lépésünkben több további mappát hozunk létre packages
a mappán belül:
vite-common
footer-components
body-components
footer-components
A projektek létrehozásához a npm init vite
-t kell futtatnunk a projekt nevével. Válassza a React
keretrendszert és a Typescript
változatot. Ezek a projektek ugyanazokat a szöszszabályokat, az összeállítási folyamatot és a React verziót fogják használni.
Ez a folyamat minden csomagban egy csomó fájlt és mappát hoz létre:
├── .eslintrc.cjs ├── .gitignore ├── index.html ├── package.json ├── public │ └── vite.svg ├── src │ ├── App.css │ ├── App.tsx │ ├── assets │ │ └── react.svg │ ├── index.css │ ├── main.tsx │ └── vite-env.d.ts ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts
Mesekönyv kezdeti beállítása
Ideje minden csomagunkhoz beállítani egy mesekönyvet. Lépjen az egyik csomagmappába, és futtassa ott a npx storybook@latest init
programot a Storybook telepítéséhez. A eslint-plugin-storybook
-vel kapcsolatos kérdéshez a Y
bemenetet a telepítéshez. Ezt követően elindul a függőségek telepítésének folyamata.
Ez létrehoz egy .storybook
mappát konfigurációkkal és stories
mappát a src
mappában. Távolítsuk el a stories
mappát, mert saját összetevőket készítünk.
Most futtassa a telepítést npx sb init --builder @storybook/builder-vite
– ez segít a történetek felépítésében a Vite segítségével a gyors induláshoz és a HMR-hez.
Tételezzük fel, hogy minden mappához ugyanazok a konfigurációk. Ha a telepítés megtörtént, akkor futtathatja a yarn storybook
fájlt a csomag mappájában, és futtathatja a Storybookot.
Kezdeti konfigurációk
Az ötlet az, hogy minden csomagunknál újra felhasználjuk a közös beállításokat. Távolítsunk el néhány fájlt, amelyekre nincs szükségünk az egyes tárolókban. Végül minden egyes mappának a következő mappákat és fájlokat kell tartalmaznia:
├── package.json ├── src │ └── vite-env.d.ts ├── tsconfig.json └── vite.config.ts
Most vegyük az összes devDependencies
-et, és vágjuk ki őket a package.json
-ból az egyik csomagmappánkból, és helyezzük el mindet a devDependenices
-be a gyökérben package.json
.
Futtassa a gyökérben npx storybook@latest init
, és javítsa ki a main.js
tulajdonságban:
stories: [ "../packages/*/src/**/*..mdx", "../packages/*/src/**/*.stories.@(js|jsx|ts|tsx)" ],
És távolítsa el a gyökérből package.json
két szkriptben:
"storybook": "storybook dev -p 6006", "build-storybook": "storybook build"
Adjon hozzá components
mappát index.tsx
fájllal minden csomagmappához:
├── package.json ├── src │ ├── components │ │ └── index.tsx │ ├── index.tsx │ └── vite-env.d.ts ├── tsconfig.json └── vite.config.ts
Létrehozhatunk közös konfigurációkat, amelyek minden csomagra vonatkoznak. Ez magában foglalja a Vite, Storybook, Jest, Babel és Prettier beállításait, amelyek univerzálisan konfigurálhatók.
A gyökérmappának a következő fájlokat kell tartalmaznia:
├── .eslintrc.cjs ├── .gitignore ├── .nvmrc ├── .prettierignore ├── .prettierrc.json ├── .storybook │ ├── main.ts │ ├── preview-head.html │ └── preview.ts ├── README.md ├── babel.config.json ├── jest.config.ts ├── lerna.json ├── package.json ├── packages │ ├── vite-body │ ├── vite-common │ ├── vite-footer │ └── vite-header ├── test.setup.ts ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts
Ebben az esetben nem vesszük figyelembe a Babel, a Jest és a Prettier beállításait.
Lerna konfiguráció
Először is vizsgáljuk meg a Lerna konfigurációs fájlt, amely segít a monorepo projektünk több csomaggal történő kezelésében.
Először is, a "$schema"
struktúrát és érvényesítést biztosít a Lerna konfigurációhoz.
Ha a "useWorkspaces"
értéke true
, a Lerna fonal munkaterületeket használ a csomagok közötti jobb összekapcsolás és függőségek kezelése érdekében. Ha false
, a Lerna kezeli a csomagközi függőségeket monorepo-ban.
A "packages"
meghatározza, hogy a Lerna hol találja meg a csomagokat a projektben.
"version"
ha "independent"
-re van állítva, a Lerna lehetővé teszi, hogy a monorepon belül minden egyes csomag saját verziószámmal rendelkezzen, rugalmasságot biztosítva az egyes csomagokhoz tartozó frissítések kiadásában.
Közös Vite konfiguráció
Most vizsgáljuk meg a szükséges elemeket a vite.config.ts
fájlban.
Ez a fájl exportálja a Vite általános konfigurációit további bővítményekkel és könyvtárakkal, amelyeket minden csomagban újra felhasználunk. A defineConfig
segédfunkcióként szolgál a Vite konfigurációs fájljában. Bár közvetlenül nem hajt végre semmilyen logikát, és nem módosítja az átadott konfigurációs objektumot, elsődleges szerepe a típuskövetkeztetés javítása és az automatikus kiegészítés megkönnyítése bizonyos kódszerkesztőkben.
A rollupOptions
lehetővé teszi az egyéni összesítési beállítások megadását. A „Rollup” az a modulcsomagoló, amelyet a Vite a motorháztető alatt használ felépítési folyamatához. Azáltal, hogy közvetlenül a Rollup számára biztosít opciókat, a fejlesztők pontosabban irányíthatják az összeállítási folyamatot. A rollupOptions
external
opciója annak meghatározására szolgál, hogy mely modulokat kell külső függőségként kezelni.
Általánosságban elmondható, hogy a external
opció használata csökkentheti a köteg méretét azáltal, hogy kizárja a kódot futtató környezetben már meglévő függőségeket.
A output
opció globals: { react: "React" }
értékkel az összesítő konfigurációjában azt jelenti, hogy a generált kötegben a react
importálási utasításai a React
globális változóra cserélődnek. Lényegében azt feltételezzük, hogy az React
már jelen van a felhasználó környezetében, és globális változóként kell elérni, nem pedig a csomagban.
Az tsconfig.node.json
fájl kifejezetten a TypeScript vite.config.ts
fájllal való átültetésének szabályozására szolgál, biztosítva, hogy kompatibilis legyen a Node.js-szel. A Vite, amely a frontend eszközöket szolgálja ki és építi fel, Node.js környezetben fut. Erre a szétválasztásra azért van szükség, mert a Vite konfigurációs fájl eltérő TypeScript-beállításokat igényelhet, mint a böngészőben való futtatásra szánt előtér-kód.
Az "types": ["vite/client"]
beillesztése az tsconfig.json
-be azért szükséges, mert a Vite olyan további tulajdonságokat biztosít az import.meta
objektumon, amelyek nem részei a szabványos JavaScript- vagy TypeScript-könyvtárak, például az import.meta.env
és import.meta.glob
.
Közös mesekönyv konfiguráció
A .storybook
könyvtár határozza meg a Storybook konfigurációját, a kiegészítőket és a dekorátorokat. Ez elengedhetetlen a Storybook viselkedésének testreszabásához és konfigurálásához.
├── main.ts └── preview.ts
Az általános konfigurációkhoz itt van két fájl. Nézzük meg mindegyiket.
A main.ts
a Storybook fő konfigurációs fájlja, és lehetővé teszi a Storybook viselkedésének szabályozását. Amint látja, csak a szokásos konfigurációkat exportáljuk, amelyeket minden csomagban újra felhasználunk.
A preview.ts
lehetővé teszi, hogy a történeteket dekorátorokkal vonjuk be, amelyek segítségével kontextust biztosíthatunk, vagy stílusokat állíthatunk be történeteinkhez globálisan. Ezt a fájlt globális paraméterek konfigurálására is használhatjuk. Ezenkívül exportálja az általános konfigurációt a csomaghasználathoz.
Root package.json
Egy Lerna monorepo projektben a package.json
hasonló szerepet tölt be, mint bármely más JavaScript vagy TypeScript projektben. Néhány szempont azonban a monoreposra jellemző.
A szkriptek kezelik a monorepót. Tesztek futtatása az összes csomagon vagy az összes csomag összeállítása. Ez a package.json
magában foglalja azokat a fejlesztési függőségeket is, amelyek a monorepo több csomagja között vannak megosztva, például tesztelési könyvtárak vagy összeállítási eszközök. A private
mező általában true
-re van állítva ebben a package.json
-ban, hogy elkerülje a véletlen közzétételt.
A szkriptek természetesen kibővíthetők más csomagokkal tesztelés, építés és így tovább, például:
"start:vite-footer": "lerna run --scope vite-footer storybook --stream",
Csomagszintű konfiguráció
Ami az összes konfigurációt a gyökérből exportáltuk a konfigurációk újrafelhasználásához, alkalmazzuk őket a csomagunk szintjén.
A Vite konfiguráció a root vite konfigurációt fogja használni, ahol csak a getBaseConfig
függvényt importáljuk, és ott megadjuk a lib
függvényt. Ezt a konfigurációt arra használjuk, hogy az összetevőcsomagunkat önálló könyvtárként építsük fel. Megadja a csomagunk belépési pontját, a könyvtár nevét és a kimeneti fájl nevét. Ezzel a konfigurációval a Vite egy lefordított fájlt generál, amely a megadott könyvtárnév alatt teszi közzé a komponenscsomagunkat, lehetővé téve annak használatát más projektekben vagy külön terjesztését.
A .storybook
esetében ugyanezt a megközelítést alkalmazzuk. Csak importáljuk a commonConfigs
-et.
És nézd meg az előnézetet is.
A .storybook
mappából az utolsóhoz hozzá kell adnunk a preview-head.html
-t.
És a legjobb az egészben az, hogy van egy elég tiszta package.json
függőségek nélkül, mindannyian ezeket használjuk minden csomaghoz a gyökértől kezdve.
Az egyetlen különbség a vite-common
, ami az a függőség, amelyet a Footer
komponensben használunk.
Alkatrészek
Ha komponenscsomagjainkat ilyen módon szervezzük, könnyedén kezelhetjük és közzétehetjük az egyes csomagokat egymástól függetlenül, miközben megosztjuk a monorepo által biztosított közös függőségeket és infrastruktúrát.
Nézzük meg a Footer
komponens src
mappáját. A többi összetevő azonos lesz, de a konfiguráció csak a különbséget jelenti.
├── assets │ └── flow.svg ├── components │ ├── Footer │ │ ├── Footer.stories.tsx │ │ └── index.tsx │ └── index.ts ├── index.ts └── vite-env.d.ts
A src
mappában található vite-env.d.ts
fájl segít a TypeScript számára, hogy megértse és pontos típusellenőrzést biztosítson a Vite-hoz kapcsolódó kódhoz a projektünkben. Biztosítja, hogy a TypeScript felismerje és ellenőrizhesse a Vite-specifikus tulajdonságokat, funkciókat és szolgáltatásokat.
A src
mappában a index.ts
tartalmazza:
export * from "./components";
A vite-common
komponenst fogyasztó komponens pedig így néz ki:
Így néz ki a stories
az összetevőhöz:
Ebben a példában négy csomagot használunk, de a megközelítés ugyanaz. Miután létrehozta az összes csomagot, képesnek kell lennie önállóan összeállítani, futtatni és tesztelni őket. Mielőtt mindegyik a gyökérszintre kerülne, futtassa a yarn install
, majd a yarn build
parancsot az összes csomag összeállításához, vagy építse fel a yarn build:vite-common
-ot, és már használhatja a csomagot a többi csomagban.
Közzététel
Az összes csomag közzétételéhez a monorepo-ban használhatjuk a npx lerna publish
parancsot. Ez a parancs végigvezet minket az egyes csomagok verziószámításán és közzétételén a végrehajtott változtatások alapján.
lerna notice cli v6.6.2 lerna info versioning independent lerna info Looking for changed packages since [email protected] ? Select a new version for vite-body (currently 1.0.0) Major (2.0.0) ? Select a new version for vite-common (currently 2.0.0) Patch (2.0.1) ? Select a new version for vite-footer (currently 1.0.0) Minor (1.1.0) ? Select a new version for vite-header (currently 1.0.0) Patch (1.0.1) ❯ Minor (1.1.0) Major (2.0.0) Prepatch (1.0.1-alpha.0) Preminor (1.1.0-alpha.0) Premajor (2.0.0-alpha.0) Custom Prerelease Custom Version
A Lerna minden egyes csomagverziót megkér tőlünk, majd közzéteheti.
lerna info execute Skipping releases lerna info git Pushing tags... lerna info publish Publishing packages to npm... lerna success All packages have already been published.
Következtetés
Szilárd architektúra megoldást kerestem a frontend komponensek szervezetéhez abban a cégben, ahol dolgozom. Minden projekthez van egy hatékony, hatékony fejlesztői környezetünk általános szabályokkal, amelyek segítenek függetlenné válni. Ez a kombináció egyszerűsített függőségkezelést, elkülönített komponenstesztelést és egyszerűsített közzétételt tesz lehetővé.
Hivatkozások
Adattár: https://github.com/antonkalik/lerna-monorepo-boilerplate
Vite with Storybook: https://storybook.js.org/blog/storybook-for-vite