Johdanto
Miksi Monorepo?
Nykyään ohjelmistokehityksen nopeaa kehitystä ei voida kiistää. Tiimit kasvavat, projektit ovat yleensä monimutkaisempia. Yritykset käyttävät huomattavia resursseja ylläpitääkseen hajautettua koodikantaa, joka koostuu monista fragmenteista. Anna monorepo - yksi yhtenäinen arkisto, joka kokoaa yhteen kaikki koodisi. Monoreposista on suinkaan tullut trendi, vaan niistä on viime aikoina tullut arkkitehtoninen tapa sijoittaa koko koodikanta yhteen paikkaan. Tiimit saavat parannetun kontekstin jakamisen, sujuvan yhteistyön ja työkalun, joka luonnollisesti kannustaa koodin uudelleenkäyttöön.
Lankatyötilojen asettaminen
Huomautus: Aina kun tässä artikkelissa mainitaan "lanka", se viittaa erityisesti Yarn v4:ään – uusimpaan versioon, joka tarjoaa parannettuja ominaisuuksia ja parannetun suorituskyvyn.
Mitä lankatyötilat ovat?
Työtilat ovat monorepon paketteja, joita usein kutsutaan paketeiksi. Niiden avulla voit hallita useita paketteja yhdessä arkistossa vaivattomasti. Työtiloilla. voit:
Jaa riippuvuuksia helposti:
Jaa yhteiset riippuvuudet projektissasi saumattomasti.
Yksinkertaista riippuvuuden hallinta:
Lanka linkittää automaattisesti paikalliset paketit, mikä vähentää päällekkäisyyksiä ja helpottaa kehitystä.
Asennusten nopeuttaminen:
Hyödynnä Yarnin suorituskyvyn optimointia ja välimuistimekanismeja (eli sisäänrakennettu plug'n'play ).
Paranna Monorepon hallintaa:
Määritä rajoitukset (säännöt) ja käytä kymmeniä saatavilla olevia laajennuksia johdonmukaisuuden ylläpitämiseksi.
Vaikka Yarn on valittu tämän artikkelin johtaja yksinkertaisuuden, nopeuden ja laajojen konfigurointivaihtoehtojensa ansiosta, on tärkeää huomata, että oikea valinta riippuu projektisi erityistarpeista, tiimin mieltymyksistä ja yleisestä työnkulusta. Esimerkiksi PNPM ja Turborepo ovat muita moderneja työkaluja, jotka tarjoavat laajan valikoiman ominaisuuksia.
Alkukokoonpano
Langan asennus on suoraviivainen prosessi. Noudata virallista opasta asentaaksesi ja määrittääksesi langan projektiisi: Lanka-asennusopas .
Kun olet suorittanut asennuksen, siirrytään konfigurointiin. Koska käytämme plug'n'play-toimintoa, sinun on varmistettava, että IDE tunnistaa riippuvuudet oikein. Jos käytät VSCodea, suorita:
# Typescript is required for VSCode SDK to set up correctly yarn add -D typescript@^5 yarn dlx @yarnpkg/sdks vscode
Jos käytät toista koodieditoria, tarkista saatavilla olevat SDK:t täältä: Lankaeditorin SDK:t .
Tässä vaiheessa olet valmis aloittamaan langan käytön.
Monorepo-rakenteen järjestäminen
Nyt kun paketinhallinta on määritetty, on aika suunnitella skaalautuva projektiorganisaatio. Selkeä, hyvin määritelty rakenne paitsi helpottaa arkiston navigointia, myös edistää parempaa koodin uudelleenkäyttöä. Tässä esimerkissä jaamme koodikannan kolmeen pääluokkaan:
Sovellukset :
- Asiakas: Sisältää lopulliset, käyttöön otettavat asiakastuotteet.
- Palvelin: Sisältää lopulliset, käyttöön otettavat palvelintuotteet.
Ominaisuudet :
- Asiakas: erillisille käyttöliittymäwidgeteille.
- Palvelin: Itsenäisille taustajärjestelmän liikelogiikkaosille.
Libs :
Talot jaetut koodit, kuten suunnittelujärjestelmän komponentit, vakiot, resurssit ja apuohjelmat. Tämä on kontekstiton vyöhyke uudelleenkäytettävän logiikan tallentamiseen.
Osoittaaksesi tämän kansiorakenteen tehon, aloitetaan lisäämällä nämä tärkeimmät kansiot Yarnin työtilaluetteloon. Lisää root package.json -tiedostoon seuraava:
"workspaces": [ "apps/**", "features/**", "libs/**" ]
Tämä kokoonpano käskee Yarnin käsittelemään näissä kansioissa olevia paketteja paikallisina paketteina. Myöhemmät asennukset varmistavat, että kunkin paketin riippuvuudet on määritetty ja linkitetty oikein.
Bootstrapping Codebase
Tässä osiossa käymme läpi minimaalisen koodikannan esimerkin, joka havainnollistaa monorepon käynnistämistä. Sen sijaan, että sisällyttäisin täydelliset koodinpätkät, annan lyhyitä esimerkkejä linkkien kanssa erityisesti tätä artikkelia varten luodun arkiston tiedostoihin.
Bootstrapping-palvelinsovellus
Aloitamme yksinkertaisella Express API:lla käyttäjän todennusta varten. Tämä palvelinsovellus paljastaa yhden päätepisteen ( /auth/signIn
), joka käyttää toisen paketin käsittelijää.
import express from "express"; import cors from "cors"; import { signInHandler } from "@robust-monorepo-yarn-nx-changesets/sign-in-handler"; const app = express(); const port = process.env.PORT || 1234; app.use(express.json()); app.use( cors({ origin: process.env.CORS_ORIGIN || "http://localhost:3000", }) ); app.post("/auth/signIn", signInHandler); app.listen(port, () => { console.log(`Server is running at http://localhost:${port}`); });
Kuten näet, /auth/signIn
-päätepiste käyttää käsittelijää, joka on tuotu toisesta paketista. Tästä pääsemme seuraavaan komponenttiin: palvelinominaisuuteen.
Bootstrapping Server -ominaisuus
Palvelinominaisuus kapseloi todennuslogiikan. Tässä paketissa määritämme kirjautumiskäsittelijän, joka hyödyntää libsien jaettua vahvistusapuohjelmaa.
import type { RequestHandler } from "express"; import { passwordValidator, usernameValidator, } from "@robust-monorepo-yarn-nx-changesets/validator"; const signInHandler: RequestHandler = (req, res) => { if (!req.body) { res.status(422).send("Request body is missing"); return; } if (typeof req.body !== "object") { res.status(422).send("Request body expected to be an object"); return; } const { username, password } = req.body; const usernameValidationResult = usernameValidator(username); if (typeof usernameValidationResult === "string") { res .status(422) .send("Invalid username format: " + usernameValidationResult); return; } const passwordValidationResult = passwordValidator(password); if (typeof passwordValidationResult === "string") { res .status(422) .send("Invalid password format: " + passwordValidationResult); return; } // Emulate a successful sign-in if (username === "test" && password === "test1234") { res.status(200).send("Sign in successful"); return; } return res.status(422).send("Username or password is incorrect"); }; export default signInHandler;
Tämä lähestymistapa tiivistää todennuslogiikan omassa paketissaan, mikä mahdollistaa sen kehittämisen ja ylläpidon itsenäisesti. Huomaa, kuinka validointiapuohjelmat tuodaan jaetusta libistä .
Bootstrapping-asiakassovellus
Katsotaan seuraavaksi asiakaspuolta. Asiakassovelluksessamme rakennamme yksinkertaisen verkkosivuston, joka mahdollistaa käyttäjän todennuksen palvelimen API:n avulla.
"use client"; import { SignInForm } from "@robust-monorepo-yarn-nx-changesets/sign-in-form"; const API_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:1234"; export default function Home() { const handleSubmit = async (username: string, password: string) => { const response = await fetch(`${API_URL}/auth/signIn`, { method: "POST", body: JSON.stringify({ username, password }), headers: { "Content-Type": "application/json", }, }); if (response.status === 200) { alert("Sign in successful"); return; } if (response.status === 422) { alert("Sign in failed: " + (await response.text())); return; } alert("Sign in failed"); }; return ( <div className="w-full h-screen overflow-hidden flex items-center justify-center"> <SignInForm onSubmit={handleSubmit} /> </div> ); }
Tässä esimerkissä SignInForm
komponentti tuodaan asiakkaan ominaisuuspaketista, joka johtaa meidät lopulliseen komponenttiimme.
Bootstrapping Client -ominaisuus
Asiakasominaisuuspaketti tarjoaa todennuslomakkeen ja jaetun vahvistuslogiikan. Tämä välttää koodin päällekkäisyyden ja varmistaa johdonmukaisuuden.
import { passwordValidator, usernameValidator, } from "@robust-monorepo-yarn-nx-changesets/validator"; interface SignInFormProps { onSubmit: (username: string, password: string) => void; } const SignInForm = ({ onSubmit }: SignInFormProps) => { const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); const username = (event.currentTarget[0] as HTMLInputElement).value; const usernameValidationResult = usernameValidator(username); if (typeof usernameValidationResult === "string") { alert(usernameValidationResult); return; } const password = (event.currentTarget[1] as HTMLInputElement).value; const passwordValidationResult = passwordValidator(password); if (typeof passwordValidationResult === "string") { alert(passwordValidationResult); return; } onSubmit(username!, password!); }; return ( <form onSubmit={handleSubmit}> <input type="text" placeholder="Username" /> <input type="password" placeholder="Password" /> <button type="submit">Submit</button> </form> ); }; export default SignInForm;
Täällä näemme jälleen validaattorin käytön jaetuista libistämme, mikä varmistaa, että validointilogiikka on keskitetty ja helposti ylläpidettävä.
Siinä se minimaalisen koodikannan esimerkissämme. Muista, että tämä koodi on yksinkertaistettu kuva, jonka tarkoituksena on havainnollistaa sovellusten, ominaisuuksien ja lisenssien perusrakennetta ja keskinäistä yhteyttä monorepossa. Voit laajentaa näitä esimerkkejä tarpeen mukaan vastaamaan projektisi erityisvaatimuksia.
Skriptien suorittaminen NX:n kanssa
Skriptien hallinta monorepossa voi olla haastavaa. Vaikka Yarnin avulla voit ajaa skriptejä useissa paketeissa eri ehdoilla, se voi vaatia mukautettuja komentosarjoja tarkemman hallinnan saamiseksi. Tässä NX tulee esiin: se tarjoaa käyttövalmiin ratkaisun tehokkaaseen ja kohdistettuun komentosarjan suorittamiseen.
NX:n esittely
NX on koontijärjestelmä, joka on optimoitu monoreposille edistyneillä CI-ominaisuuksilla. NX:n avulla voit:
- Suorita tehtäviä tehokkaasti rinnakkain : Hyödynnä samanaikaisuutta nopeuttaaksesi rakentamistasi.
- Tunnista riippuvuussuhteet : Ymmärrä pakettien ja komentosarjojen väliset yhteydet.
- Välimuistin komentosarjan suoritustulokset : Vältä ylimääräinen työ tallentamalla tulosteet välimuistiin.
- Mukauta toimintaa laajennuksilla: Laajenna toimintoja runsaan laajennusekosysteemin avulla.
Kohdennettu komentosarjan suoritus
Hyödyntääksemme NX:n ominaisuuksia meidän on ensin luotava nx.json
-tiedosto, joka määrittää komentosarjoillemme säännöt. Alla on esimerkki kokoonpanosta:
{ "targetDefaults": { "build": { "dependsOn": [ "^build" ], "outputs": [ "{projectRoot}/dist" ], "cache": true }, "typecheck": { "dependsOn": [ "^build", "^typecheck" ] }, "lint": { "dependsOn": [ "^build", "^lint" ] } }, "defaultBase": "main" }
Selkeällä englanniksi tämä kokoonpano tarkoittaa:
Rakentaa
Paketin
build
riippuu sen riippuvuuksien onnistumisesta, ja sen tulos on välimuistissa.Typecheck
Paketin
typecheck
riippuu sekä sen riippuvuuksien koonti- että tyyppitarkistuskomentosarjasta.Nukka
Paketin
lint
-skripti riippuu sekä sen riippuvuuksien koonti- että lint-skripteistä.
Lisätään nyt komentosarjat package.json
tiedostoon:
"scripts": { "build:all": "yarn nx run-many -t build", "build:affected": "yarn nx affected -t build --base=${BASE:-origin/main} --head=${HEAD:-HEAD}", "typecheck:all": "yarn nx run-many -t typecheck", "typecheck:affected": "yarn nx affected -t typecheck --base=${BASE:-origin/main} --head=${HEAD:-HEAD}", "lint:all": "yarn nx run-many -t lint", "lint:affected": "yarn nx affected -t lint --base=${BASE:-origin/main} --head=${HEAD:-HEAD}", "quality:all": "yarn nx run-many --targets=typecheck,lint", "quality:affected": "yarn nx affected --targets=typecheck,lint --base=${BASE:-origin/main} --head=${HEAD:-HEAD}" }
Tässä määrittelemme neljä suoritusskriptityyppiä:
rakentaa: rakentaa paketin.
typecheck: Tarkistaa paketin tyypit.
nukkaa: Nukkaa paketin.
laatu: Suorittaa sekä tyyppitarkistuksen että nukkauksen.
Jokaisella skriptillä on kaksi muunnelmaa:
- all: Suorittaa komentosarjan kaikissa paketeissa.
- vaikuttaa: Suorittaa komentosarjan vain paketeissa, joihin viimeaikaiset muutokset vaikuttavat.
BASE
jaHEAD
-ympäristömuuttujien avulla voit määrittää alueen (oletuksenaorigin/main
ja nykyinenHEAD
), mikä mahdollistaa raellisen suorituksen vetopyynnöissä. Tämä voi säästää huomattavasti aikaa ja resursseja.
Pyöreän riippuvuuden hallinta
NX tarjoaa myös sisäänrakennetun komennon riippuvuuskaavion luomiseksi, mikä voi auttaa riippuvuusjaksojen havaitsemisessa. Seuraava komentosarja käyttää NX-kuvaajan lähtöä tarkistaakseen pyöreät riippuvuudet ja epäonnistuu, jos sellaisia löytyy.
Luo tiedosto osoitteessa scripts/check-circulardeps.mjs
jossa on seuraava sisältö:
import { execSync } from "child_process"; import path from "path"; import fs from "fs"; const hasCycle = (node, graph, visited, stack, path) => { if (!visited.has(node)) { visited.add(node); stack.add(node); path.push(node); const dependencies = graph.dependencies[node] || []; for (const dep of dependencies) { const depNode = dep.target; if ( !visited.has(depNode) && hasCycle(depNode, graph, visited, stack, path) ) { return true; } if (stack.has(depNode)) { path.push(depNode); return true; } } } stack.delete(node); path.pop(); return false; }; const getGraph = () => { const cwd = process.cwd(); const tempOutputFilePath = path.join(cwd, "nx-graph.json"); execSync(`nx graph --file=${tempOutputFilePath}`, { encoding: "utf-8", }); const output = fs.readFileSync(tempOutputFilePath, "utf-8"); fs.rmSync(tempOutputFilePath); return JSON.parse(output).graph; }; const checkCircularDeps = () => { const graph = getGraph(); const visited = new Set(); const stack = new Set(); for (const node of Object.keys(graph.dependencies)) { const path = []; if (hasCycle(node, graph, visited, stack, path)) { console.error("🔴 Circular dependency detected:", path.join(" → ")); process.exit(1); } } console.log("✅ No circular dependencies detected."); }; checkCircularDeps();
Tämä skripti:
- Suorittaa NX-komennon luodakseen riippuvuuskaavion.
- Lukee kaavion väliaikaisesta JSON-tiedostosta.
- Tarkistaa syklit rekursiivisesti.
- Kirjaa virheen ja poistuu, jos havaitaan pyöreä riippuvuus.
Riippuvuuksien vahvistaminen lankarajoituksilla
Projektien kasvaessa riippuvuussuhteiden johdonmukaisuuden ylläpitämisestä tulee haastavaa. Riippuvuuksia, solmuversioita ja muita kokoonpanoja koskevien tiukkojen sääntöjen noudattaminen on välttämätöntä tarpeettoman teknisen velan välttämiseksi. Lankarajoitukset tarjoavat tavan automatisoida nämä tarkistukset.
Lankarajoitusten ymmärtäminen
Lankarajoitukset ovat monorepon pakettien sääntöjä. Niiden käytön merkittävä etu on, että olet näiden sääntöjen ylläpitäjä. Voit esimerkiksi luoda säännön pakottaaksesi kaikki paketit käyttämään samaa React-versiota. Kun se on asetettu, et koskaan törmää ongelmaan, jos isäntäsovellus ei voi käyttää ominaisuutta/libiä korkeammalla React-versiolla.
Vaikka suuren monorepon siirtäminen uuteen pääversioon riippuvuudesta voi olla monimutkaista, rajoitusten käyttö tuo lopulta johdonmukaisuutta ja vakautta koko projektiin.
Johdonmukaisuuden varmistaminen
Esimerkkivarastossamme käytämmeyarn.config.cjs -tiedostoa johdonmukaisuuden varmistamiseen:
Solmun versio
Lanka versio
Riippuvuuksien versiot
Joustavuuden lisäämiseksi siirtymien aikana voit määrittää poissulkemisia ohittaaksesi väliaikaisesti tietyt tarkistukset. Esimerkiksi:
const workspaceCheckExclusions = []; const dependencyCheckExclusions = [];
Näiden vakioiden avulla voit sulkea tiettyjä työtiloja tai riippuvuuksia validointiprosessista, mikä varmistaa sujuvan siirron tarvittaessa.
Versioinnin hallinta muutosjoukkojen avulla
Toinen ongelma, jonka saatat kohdata arkiston kasvun yhteydessä, on versionhallinta ja julkaisu. Muutossarjat tarjoavat tyylikkään ratkaisun tämän prosessin automatisoimiseen ja varmistavat, että jokaista muutosta seurataan, versioidaan ja julkaistaan.
Johdanto Changesetsiin
Changesets on avoimen lähdekoodin työkalu, joka on suunniteltu hallitsemaan versiointia monorepo-tietovarastoissa. Se yksinkertaistaa muutosten seurantaa jakamalla ne pieniin, ihmisen luettavissa oleviin asiakirjoihin, jotka kuvaavat muutoksen tarkoituksen. Näitä asiakirjoja kutsutaan muutosjoukoiksi. Keskeisiä etuja ovat:
Selkeä dokumentaatio
Jokainen muutossarja hahmottelee tehdyt muutokset, mikä auttaa sekä kehittäjiä että kuluttajia ymmärtämään, mitä uutta julkaisua odottaa.
Rakeinen versionhallinta
Jokainen paketti versioitetaan itsenäisesti, mikä varmistaa, että vain kyseiset paketit päivitetään. Tämä minimoi tyhjien versiovirheiden ja riippuvuuskatkojen riskin.
Yhteistyöystävällinen
Koska jokainen muutos tallennetaan muutossarjan kautta, tiimit voivat tarkistaa ja hyväksyä päivitykset ennen varsinaista julkaisua.
Julkaisujen automatisointi
Yksi Changesetsin tehokkaimmista ominaisuuksista on kyky automatisoida prosessi. Voit integroida muutossarjat CI/CD-putkeen ja unohtaa manuaaliset versiomuutokset ja NPM-julkaisut.
Katso release.yaml -työnkulku esimerkkiarkistosta. Siinä on create-release-pull-request-or-publish
vaihe. Vaihe, jota tukee Changesets/action GitHub-toiminto luo kaiken taian. Sinun tarvitsee vain määrittää NPM_TOKEN
pakettien julkaisemista varten. Sitten jokainen työntö main
:
Tarkista, onko Changeset-asiakirjoja .
Jos muutosjoukkoasiakirjoja on, toiminto luo vetopyynnön, joka sisältää tarvittavat versiovirheet ja muutoslokipäivitykset. Jos muutoksia ei havaita, mitään ei tapahdu.
Tarkista, onko julkaisuvalmiita paketteja .
Jos paketit ovat valmiita julkaistavaksi, toiminto julkaisee uudet versiot NPM:lle käyttämällä annettua
NPM_TOKEN
. Jos julkaisuvalmiita paketteja ei ole, toiminto poistuu tekemättä muutoksia.
Automatisoimalla nämä tehtävät Changesets varmistaa, että julkaisusi ovat johdonmukaisia ja luotettavia, mikä vähentää inhimillisten virheiden mahdollisuutta ja virtaviivaistaa kehitystyönkulkua.
Työnkulun integrointi GitHub Actionsin kanssa
Tässä osiossa tarkastellaan, kuinka juuri rakentamamme arkkitehtuurin voima saadaan valloilleen. GitHub Actionsin avulla automatisoimme PR-laadun tarkistukset, kirjastojen ja ominaisuuksien versiojulkaisut sekä sovellusten käyttöönotot. Painopiste on automatisoinnin maksimoinnissa ja samalla koodin laadun ja työn tarkkuuden säilyttämisessä.
Tarkista PR-laatu
Varmistaaksemme, että vetopyyntökoodi pysyy yhtenäisenä ja vakaana, luomme oman quality.yaml -työnkulun. Tämä työnkulku suorittaa useita tehtäviä, kuten varmistaa, että manuaalisia versiomuutoksia ei tehdä (koska versiointia hallinnoi Changesets):
- id: check_version name: Check version changes run: | BASE_BRANCH=${{ github.event.pull_request.base.ref }} git fetch origin $BASE_BRANCH CHANGED_FILES=$(git diff --name-only origin/$BASE_BRANCH HEAD) VERSION_CHANGED=false for FILE in $CHANGED_FILES; do if [[ $FILE == */package.json ]]; then if [ -f "$FILE" ]; then HEAD_VERSION=$(grep '"version":' "$FILE" | awk -F '"' '{print $4}') else continue fi HEAD_VERSION=$(cat $FILE | grep '"version":' | awk -F '"' '{print $4}') if git cat-file -e origin/$BASE_BRANCH:$FILE 2>/dev/null; then BASE_VERSION=$(git show origin/$BASE_BRANCH:$FILE | grep '"version":' | awk -F '"' '{print $4}') else BASE_VERSION=$HEAD_VERSION fi if [ "$BASE_VERSION" != "$HEAD_VERSION" ]; then VERSION_CHANGED=true echo "Version change detected in $FILE" fi fi done if [ "$VERSION_CHANGED" = true ]; then echo "Manual version changes are prohibited. Use changesets instead." exit 1 fi env: GITHUB_REF: ${{ github.ref }}
Tämän tarkistuksen ohella check-quality
asentaa riippuvuuksia, vahvistaa rajoitukset, tarkistaa kiertoriippuvuudet ja varmistaa koodin yleisen laadun käyttämällä komentosarjaa, jonka määritimme aiemmin NX:n kanssa:
- id: install-dependencies name: Install dependencies run: yarn --immutable - id: check-constraints name: Check constraints run: yarn constraints - id: check-circulardeps name: Check circular dependencies run: yarn check-circulardeps:all - id: check-quality name: Check quality run: BASE=origin/${{ github.event.pull_request.base.ref }} yarn quality:affected
Laaduntarkistus on suunniteltu suoritettavaksi vain paketeissa, joihin nykyinen vetopyyntö vaikuttaa. Näiden töiden onnistunut suorittaminen merkitsee, että vetopyyntö on valmis yhdistämään (kooditarkistusten vastaanottamisen lisäksi).
Jos projekti vaatii lisätarkastuksia, voit päivittää nx.json
tiedostosi ja laatukomentosarjasi pitämällä työnkulun ennallaan.
Julkaise kirjastoja ja ominaisuuksia
Kun PR on yhdistetty, julkaisutyönkulku (kuten on kuvattu Muutossarjat-luvussa) käynnistyy. Tämä työnkulku rakentaa ongelmalliset paketit ja luo PR:n versiovirheillä. Kun tämä PR on hyväksytty ja yhdistetty, release.yaml suoritetaan uudelleen – tällä kertaa PR:n luomisen sijaan se havaitsee versiomuutokset ja julkaisee päivitetyt paketit NPM:lle:
- id: build-packages name: Build packages run: yarn build:affected - id: create-release-pull-request-or-publish name: Create Release Pull Request or Publish to NPM uses: changesets/action@v1 with: version: yarn changeset version publish: yarn release commit: "chore: publish new release" title: "chore: publish new release" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} release-apps: needs: release-libs-features uses: ./.github/workflows/release-apps.yaml with: publishedPackages: ${{ needs.release-libs-features.outputs.publishedPackages }}
Tämän jälkeen suoritetaan työ nimeltä release-apps
, joka vastaa sovellusten käyttöönotoista. Se vastaanottaa luettelon edellisen vaiheen julkaistuista paketeista ja vie meidät seuraavaan lukuun.
Julkaise sovelluksia
Julkaisuprosessin viimeinen osa sisältää sovellusten käyttöönoton (sovelluksia ei julkaista NPM:lle, koska ne on asetettu private
paketissa package.json
). release-apps.yaml- työnkulun käynnistää automaattisesti release.yaml , tai se voidaan suorittaa suoraan GitHubin Toiminnot-välilehdeltä:
name: Release Apps on: workflow_call: inputs: publishedPackages: description: "List of published packages" required: false type: string default: "[]" workflow_dispatch: inputs: publishedPackages: description: "List of published packages (optional)" required: false type: string default: "[]"
Tämä työnkulku hyväksyy publishedPackages
paketit määrittämään julkaistut paketit. Matriisistrategian avulla se tarkistaa matriisin jokaisesta sovelluksesta julkaistujen riippuvuuksien olemassaolon:
- id: check-dependency-published name: Check if any app dependency is published run: | PUBLISHED_PACKAGES="${{ inputs.publishedPackages }}" PACKAGE_NAME="${{ matrix.package }}" APP="${{ matrix.app }}" DEPENDENCIES=$(jq -r '.dependencies // {} | keys[]' "apps/$APP/package.json") for DEP in $DEPENDENCIES; do if echo "$PUBLISHED_PACKAGES" | grep -w "$DEP"; then echo "published=true" >> $GITHUB_OUTPUT exit 0 fi done echo "published=false" >> $GITHUB_OUTPUT
Tämä tarkistus on yksi ehto sovelluksen käyttöönoton aloittamiselle. Toinen ehto varmistaa, että sovelluksen versiota on muutettu (osoittaa, että uudelleenjärjestely on tarpeen, vaikka riippuvuuksia ei olisi päivitetty):
- id: check-version-change name: Check if app version has changed run: | APP="${{ matrix.app }}" PACKAGE_JSON_PATH="apps/$APP/package.json" CURRENT_VERSION=$(jq -r '.version' "$PACKAGE_JSON_PATH") PREVIOUS_VERSION=$(git show HEAD~1:"$PACKAGE_JSON_PATH" | jq -r '.version' || echo "") if [[ "$CURRENT_VERSION" == "$PREVIOUS_VERSION" ]]; then echo "changed=false" >> $GITHUB_OUTPUT else echo "changed=true" >> $GITHUB_OUTPUT fi
Lopuksi, kun on vahvistettu, että sovelluksella on joko päivitettyjä riippuvuuksia tai sen versio on muuttunut, työnkulku hakee uuden version ja jatkaa sovelluksen rakentamista ja käyttöönottoa:
- id: set-up-docker name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - id: get-app-version name: Get the app version from package.json run: echo "app-version=$(cat ./apps/${{ matrix.app }}/package.json | jq -r '.version')" >> $GITHUB_OUTPUT - id: build-image name: Build image if: steps.check-dependency-published.outputs.published == 'true' || steps.check-version-change.outputs.changed == 'true' uses: docker/build-push-action@v4 with: build-contexts: | workspace=./ context: "./apps/${{ matrix.app }}" load: true push: false tags: | ${{ matrix.app }}:v${{ steps.get-app-version.outputs.app-version }}
Tässä esimerkissä luomme Docker-kuvan työntämättä sitä rekisteriin. Korvaa tämä vaihe tuotantotyönkulussasi varsinaisella käyttöönottoprosessilla.
Johtopäätös
Yhteenveto parhaista käytännöistä
Tämän artikkelin aikana tutkimme vankan monorepon käyttöönottoa ja työkaluja, jotka auttavat hallitsemaan sitä tehokkaasti. Keskittämällä kooditietokantasi et vain yksinkertaista riippuvuuden hallintaa, vaan myös virtaviivaistat tiimien välistä yhteistyötä. Osoitimme, kuinka Lankaa voidaan hyödyntää jakamaan riippuvuuksia, nopeuttamaan asennusta PnP:n avulla ja parantamaan projektin yleistä johdonmukaisuutta. Lisäksi NX:n integrointi kohdennettuun komentosarjan suorittamiseen varmistaa, että CI on nopea ja tehokas. Muutossarjat auttoivat automatisoimaan versiointia, vähentämään manuaalisia virheitä ja virtaviivaistamaan julkaisuja. Lopuksi olemme tehneet tuotantovalmiin CI/CD-putkilinjan GitHub-toiminnoilla, joka suorittaa vain tarvittavat tehtävät.
Seuraavat vaiheet
- Kokeile ja mukauta : Aloita perustamalla pienimuotoinen monorepo testataksesi näitä parhaita käytäntöjä. Kokeile erilaisia kansiorakenteita ja laajenna asteittain lisäämään paketteja itseluottamuksesi kasvaessa.
- Integroi lisätyökaluja : Harkitse täydentävien työkalujen, kuten PNPM:n tai Turborepon, integrointia projektisi ainutlaatuisten vaatimusten ja tiimin mieltymysten perusteella.
- Paranna CI/CD-putkistoja : Hienosäädä GitHub Actions -työnkulkujasi lisäämällä laatutarkistuksia, koodin kattavuutta ja projektiisi räätälöityjä suojaustarkistuksia.
- Yhteisö ja päivitykset : Pysy ajan tasalla Yarnin, NX:n ja Changesetsin uusimmista julkaisuista. Ota yhteyttä yhteisön kanssa jakaaksesi oivalluksia ja oppiaksesi monorepo-hallinnan nousevista trendeistä.
Resurssit
Käytä tätä opasta varten luotua täydellistä esimerkkivarastoa. Tutustu projektin rakenteeseen, koodinäytteisiin ja komentosarjoihin, jotka esittelevät monorepo-kokoonpanon toiminnassa.
Tutustu varsinaiseen NPM-pakettiin, joka on julkaistu osana tätä projektia. Nämä paketit havainnollistavat artikkelissa käsiteltyjen käsitteiden todellista käyttöä ja toteutusta.