paint-brush
Darbas su aplinkos kintamaisiais Frontend programų leidimuosepateikė@egorgrushin
40,290 skaitymai
40,290 skaitymai

Darbas su aplinkos kintamaisiais Frontend programų leidimuose

pateikė Egor Grushin11m2024/10/30
Read on Terminal Reader

Per ilgai; Skaityti

Frontend programoms tradiciškai reikia atskirų versijų kiekvienai aplinkai (kūrimui, parengimui, gamybai), nes aplinkos kintamieji įterpiami kūrimo metu, todėl pailgėja išleidimo laikas. Siūlau sprendimą vieną kartą sukurti sąsajos programą ir įterpti aplinkai būdingus kintamuosius diegimo metu, naudojant vietos rezervavimo ženklus ir scenarijų, kad jie būtų pakeisti tikrosiomis reikšmėmis diegimo metu. Šis metodas supaprastina išleidimo procesą, sumažina kūrimo laiką, užtikrina nuoseklumą įvairiose aplinkose ir sumažina su kūrimu susijusių klaidų riziką. Be to, valdant failo vardų maišą po kintamojo įterpimo, šis metodas palaiko veiksmingą naršyklės talpyklą ir bendrą programos našumą.
featured image - Darbas su aplinkos kintamaisiais Frontend programų leidimuose
Egor Grushin HackerNoon profile picture
0-item


Milijonai priekinių programų valdo su aplinka susijusias versijas. Kiekvienai aplinkai, nesvarbu, ar tai kūrimas, pastatymas ar gamyba, turi būti sukurta atskira sąsajos programos versija ir nustatyti tinkami aplinkos kintamieji. Konstracijų skaičius padaugėja, jei naudojamos kelios programos, o tai padidina nusivylimą. Tai buvo įprasta problema ilgą laiką, tačiau yra geresnis būdas tvarkyti aplinkos kintamuosius. Radau būdą, kaip supaprastinti šį procesą, o šiame straipsnyje žingsnis po žingsnio padėsiu sukurti efektyvų procesą, kuris sumažins kūrimo laiką ir padės užtikrinti projektų aplinkos nuoseklumą.


Aplinkos kintamųjų supratimas

Prieš pradėdami, manau, turėtume padaryti apibendrinimą. Žiniatinklio programos beveik visada remiasi kintamaisiais, vadinamais „aplinkos kintamaisiais “, kurie dažnai apima vidinius sistemos galutinius taškus, integravimo sistemas, mokėjimo sistemos raktus, išleidimo numerius ir pan. Žinoma, šių kintamųjų reikšmės skiriasi priklausomai nuo aplinkos, kurioje įdiegta programa.


Pavyzdžiui, įsivaizduokite programą, kuri sąveikauja su mokėjimo šliuzu. Kūrimo aplinkoje mokėjimo šliuzo URL gali nukreipti į bandymo smėlio dėžę (https://sandbox.paymentgateway.com), o gamybinėje aplinkoje – į tiesioginę paslaugą (https://live.paymentgateway.com ). Panašiai kiekvienai aplinkai naudojami skirtingi API raktai arba bet koks kitas specifinis aplinkos nustatymas, siekiant užtikrinti duomenų saugumą ir išvengti aplinkų maišymo.


Iššūkiai kuriant frontend

Kuriant pagrindines programas , tai nėra problema. Šiuos kintamuosius pakanka deklaruoti programos kode, nes šių kintamųjų reikšmės saugomos serverio aplinkoje, kurioje yra įdiegta užpakalinė programa. Tokiu būdu užpakalinė programa juos pasiekia paleidžiant.


Tačiau naudojant frontend programas viskas tampa šiek tiek sudėtingesnė. Kadangi jie vykdomi vartotojo naršyklėje, jie neturi prieigos prie konkrečių aplinkos kintamųjų reikšmių. Kad tai būtų išspręsta, šių kintamųjų reikšmės paprastai „įdedamos“ į sąsajos programą kūrimo metu. Tokiu būdu, kai programa veikia vartotojo naršyklėje, visos reikalingos reikšmės jau yra įdėtos į frontend programą.


Šis metodas, kaip ir daugelis kitų, pateikiamas su įspėjimu: kiekvienai aplinkai turite sukurti atskirą tos pačios sąsajos programos versiją, kad kiekvienoje versijoje būtų atitinkamos vertės.


Pavyzdžiui , tarkime, kad turime tris aplinkas:

  • kūrimas vidiniam testavimui;

  • integracijos testavimo etapas;

  • ir gamyba klientams.


Norėdami pateikti savo darbą testavimui, sukurkite programą ir įdiekite ją į kūrimo aplinką. Baigę vidinį testavimą, turite dar kartą sukurti programą, kad galėtumėte ją įdiegti į etapą, o tada dar kartą sukurti, kad galėtumėte įdiegti gamybinėje versijoje. Jei projekte yra daugiau nei viena priekinė programa, tokių versijų skaičius žymiai padidėja. Be to, tarp šių versijų kodų bazė nesikeičia – antroji ir trečioji versijos yra pagrįstos tuo pačiu šaltinio kodu.


Visa tai daro išleidimo procesą sudėtingą, lėtą ir brangų, taip pat kelia kokybės užtikrinimo riziką. Galbūt kūrimas buvo gerai išbandytas kūrimo aplinkoje, tačiau etapo versija yra techniškai nauja, o tai reiškia, kad dabar yra naujų klaidų.


Pavyzdys: turite dvi programas, kurių kūrimo laikas yra X ir Y sekundės. Šiose trijose aplinkose abiejų programų kūrimo laikas užtruks 3X + 3Y . Tačiau jei galėtumėte sukurti kiekvieną programą tik vieną kartą ir naudoti tą pačią versiją visose aplinkose, bendras laikas sutrumpėtų iki X + Y sekundžių, o kūrimo laikas sutrumpėtų tris kartus.

Tai gali turėti didelį skirtumą priekiniuose vamzdynuose, kur ištekliai yra riboti, o kūrimo laikas gali svyruoti nuo kelių minučių iki gerokai daugiau nei valandos. Problema yra beveik kiekvienoje priekinėje programoje visame pasaulyje ir dažnai nėra būdo jos išspręsti. Tačiau tai rimta problema, ypač verslo požiūriu.

Argi nebūtų puiku, jei užuot sukūrę tris atskiras versijas, galėtumėte sukurti vieną ir įdiegti visose aplinkose? Na, aš radau būdą, kaip tai padaryti.


Priekinės sistemos diegimo optimizavimas. Vadovas

Aplinkos kintamųjų nustatymas


  1. Pirma, savo sąsajos projekto saugykloje turite sukurti failą, kuriame bus pateikti būtini aplinkos kintamieji. Kūrėjas juos naudos vietoje. Paprastai šis failas vadinamas .env.local , kurį gali nuskaityti dauguma šiuolaikinių sąsajų sistemų. Štai tokio failo pavyzdys:


     CLIENT_ID='frontend-development' API_URL=/api/v1' PUBLIC_URL='/' COMMIT_SHA=''


    Pastaba: skirtingoms sistemoms reikia skirtingų aplinkos kintamųjų pavadinimų. Pavyzdžiui, „React“ prie kintamųjų pavadinimų turite pridėti REACT_APP_ . Šiame faile nebūtinai turi būti kintamųjų, kurie tiesiogiai veikia programą; jame taip pat gali būti naudingos derinimo informacijos. Pridėjau kintamąjį COMMIT_SHA , kurį vėliau paimsime iš kūrimo užduoties, kad galėtume stebėti įsipareigojimą, kuriuo buvo pagrįsta ši kūrimo užduotis.


  2. Tada sukurkite failą, pavadintą environment.js , kuriame galite apibrėžti, kokių aplinkos kintamųjų jums reikia. Frontend sistema juos įves už jus. Pavyzdžiui, „React“ jie saugomi objekte process.env :


     const ORIGIN_ENVIRONMENTS = window.ORIGIN_ENVIRONMENTS = { CLIENT_ID: process.env.CLIENT_ID, API_URL: process.env.API_URL, PUBLIC_URL: process.env.PUBLIC_URL, COMMIT_SHA: process.env.COMMIT_SHA }; export const ENVIRONMENT = { clientId: ORIGIN_ENVIRONMENTS.CLIENT_ID, apiUrl: ORIGIN_ENVIRONMENTS.API_URL, publicUrl: ORIGIN_ENVIRONMENTS.PUBLIC_URL ?? "/", commitSha: ORIGIN_ENVIRONMENTS.COMMIT_SHA, };


  1. Čia gausite visas pradines kintamųjų reikšmes window.ORIGIN_ENVIRONMENTS objekte, kuris leidžia jas peržiūrėti naršyklės konsolėje. Be to, turite nukopijuoti juos į objektą ENVIRONMENT , kur taip pat galite nustatyti kai kuriuos numatytuosius nustatymus, pavyzdžiui: manome, kad publicUrl pagal numatytuosius nustatymus yra /. Naudokite objektą ENVIRONMENT visur, kur šie kintamieji reikalingi programoje.


    Šiame etape įvykdėte visus vietos plėtros poreikius. Tačiau tikslas yra valdyti skirtingas aplinkas.


  2. Norėdami tai padaryti, sukurkite .env failą su tokiu turiniu:

 CLIENT_ID='<client_id>' API_URL='<api_url>' PUBLIC_URL='<public_url>' COMMIT_SHA=$COMMIT_SHA

Šiame faile norėsite nurodyti vietos rezervavimo ženklus kintamiesiems, kurie priklauso nuo aplinkos. Jie gali būti bet kokie, kurių tik norite, jei jie yra unikalūs ir jokiu būdu nesutampa su jūsų šaltinio kodu. Norėdami gauti papildomos garantijos, netgi galite naudoti UUID - Universaliai unikalūs identifikatoriai.


Tiems kintamiesiems, kurie nesikeičia įvairiose aplinkose (pvz., įvykdymo maišos), galite tiesiogiai parašyti tikrąsias reikšmes arba naudoti vertes, kurios bus pasiekiamos kūrimo užduoties metu (pvz., $COMMIT_SHA ). Kūrimo proceso metu sąsajos sistema šiuos rezervuotus ženklus pakeis tikrosiomis vertėmis:


Failas
Failas

  1. Dabar jūs gaunate galimybę vietoje rezervuotųjų ženklų įdėti tikras vertybes. Norėdami tai padaryti, sukurkite failą inject.py (aš pasirinkau Python, bet tam galite naudoti bet kokį įrankį), kuriame pirmiausia turėtų būti vietos rezervavimo ženklų susiejimas su kintamųjų pavadinimais:


 replacement_map = { "<client_id>": "CLIENT_ID", "<api_url>": "API_URL", "<public_url>": "PUBLIC_URL", "%3Cpublic_url%3E": "PUBLIC_URL" }

Atkreipkite dėmesį, kad public_url pateikiamas du kartus, o antrame įraše nėra skliaustų. To reikia visiems kintamiesiems, kurie naudojami CSS ir HTML failuose.


  1. Dabar pridėkime failų, kuriuos norime modifikuoti, sąrašą (tai būtų „Nginx“ pavyzdys):


 base_path = 'usr/share/nginx/html' target_files = [ f'{base_path}/static/js/main.*.js', f'{base_path}/static/js/chunk.*.js', f'{base_path}/static/css/main.*.css', f'{base_path}/static/css/chunk.*.css', f'{base_path}/index.html' ]


  1. Tada sukuriame failą injector.py , kuriame gausime kūrimo artefaktų failų (pvz., JS, HTML ir CSS failų) susiejimą ir sąrašą ir pakeisime vietos rezervavimo ženklus kintamųjų reikšmėmis iš dabartinės aplinkos:


 import os import glob def inject_envs(filename, replacement_map): with open(filename) as r: lines = r.read() for key, value in replacement_map.items(): lines = lines.replace(key, os.environ.get(value) or '') with open(filename, "w") as w: w.write(lines) def inject(target_files, replacement_map, base_path): for target_file in target_files: for filename in glob.glob(target_file.glob): inject_envs(filename, replacement_map)


Tada faile inject.py pridėkite šią eilutę (nepamirškite importuoti injector.py ):

 injector.inject(target_files, replacement_map, base_path)


  1. Dabar turime įsitikinti, kad inject.py scenarijus veikia tik diegimo metu. Įdiegę Python ir nukopijavę visus artefaktus, galite pridėti jį prie Dockerfile komandoje CMD :
 RUN apk add python3 COPY nginx/default.conf /etc/nginx/conf.d/default.conf COPY --from=build /app/ci /ci COPY --from=build /app/build /usr/share/nginx/html CMD ["/bin/sh", "-c", "python3 ./ci/inject.py && nginx -g 'daemon off;'"]That's it! This way, during each deployment, the pre-built files will be used, with variables specific to the deployment environment injected into them.


tai viskas! Tokiu būdu kiekvieno diegimo metu bus naudojami iš anksto sukurti failai, į kuriuos įterpiami diegimo aplinkai būdingi kintamieji.


Failas: Failas


Failų vardų maišos tvarkymas, kad naršyklė būtų tinkamai išsaugota talpykloje

Vienas dalykas – jei jūsų kūrimo artefaktų failų pavadinimuose yra turinio maišos, ši injekcija neturės įtakos failų pavadinimams ir dėl to gali kilti problemų dėl naršyklės talpyklos saugojimo. Norėdami tai išspręsti, pakeitę failus su įterptais kintamaisiais, turėsite:


  1. Sugeneruokite naują maišą atnaujintiems failams.
  2. Pridėkite šią naują maišą prie failų pavadinimų, kad naršyklė juos traktuotų kaip naujus failus.
  3. Atnaujinkite visas nuorodas į senus failų pavadinimus savo kode (pvz., importavimo teiginius), kad atitiktų naujus failų pavadinimus.


Norėdami tai įgyvendinti, į failą inject.py pridėkite maišos bibliotekos importą ( import hashlib ) ir šias funkcijas.


 def sha256sum(filename): h = hashlib.sha256() b = bytearray(128 * 1024) mv = memoryview(b) with open(filename, 'rb', buffering=0) as f: while n := f.readinto(mv): h.update(mv[:n]) return h.hexdigest() def replace_filename_imports(filename, new_filename, base_path): allowed_extensions = ('.html', '.js', '.css') for path, dirc, files in os.walk(base_path): for name in files: current_filename = os.path.join(path, name) if current_filename.endswith(allowed_extensions): with open(current_filename) as f: s = f.read() s = s.replace(filename, new_filename) with open(current_filename, "w") as f: f.write(s) def rename_file(fullfilename): dirname = os.path.dirname(fullfilename) filename, ext = os.path.splitext(os.path.basename(fullfilename)) digest = sha256sum(fullfilename) new_filename = f'{filename}.{digest[:8]}' new_fullfilename = f'{dirname}/{new_filename}{ext}' os.rename(fullfilename, new_fullfilename) return filename, new_filename


Tačiau ne visus failus reikia pervardyti. Pavyzdžiui, index.html failo pavadinimas turi likti nepakitęs ir kad tai pasiektumėte, sukurkite TargetFile klasę, kurioje bus saugoma vėliavėlė, nurodanti, ar reikia pervadinti:


 class TargetFile: def __init__(self, glob, should_be_renamed = True): self.glob = glob self.should_be_renamed = should_be_renamed


Dabar tereikia pakeisti failų kelių masyvą inject.py į TargetFile klasės objektų masyvą:

 target_files = [ injector.TargetFile(f'{base_path}/static/js/main.*.js'), injector.TargetFile(f'{base_path}/static/js/chunk.*.js'), injector.TargetFile(f'{base_path}/static/css/main.*.css'), injector.TargetFile(f'{base_path}/static/css/chunk.*.css'), injector.TargetFile(f'{base_path}/index.html', False) ]


Ir atnaujinkite inject funkciją injector.py kad įtrauktumėte failo pervadinimą, jei vėliavėlė nustatyta:


 def inject(target_files, replacement_map, base_path): for target_file in target_files: for filename in glob.glob(target_file.glob): inject_envs(filename, replacement_map) if target_file.should_be_renamed: filename, new_filename = rename_file(filename) replace_filename_imports(filename, new_filename, base_path)


Todėl artefaktų failai bus pavadinti tokiu formatu: <origin-file-name> . <injection-hash> . <extension> .


Failo pavadinimas prieš injekciją:

Failo pavadinimas prieš injekciją


Failo pavadinimas po injekcijos:Failo pavadinimas po injekcijos


Tie patys aplinkos kintamieji duoda tą patį failo pavadinimą, leidžiantį vartotojo naršyklei tinkamai išsaugoti failą talpykloje. Dabar yra garantija, kad teisingos šių kintamųjų reikšmės bus saugomos naršyklės talpykloje, todėl klientui bus geresnis našumas.


Sprendimas supaprastintam diegimui

Dėl tradicinio požiūrio, kad kiekvienai aplinkai būtų kuriamos atskiros versijos, atsirado keletas kritinių neveiksmingumo, o tai gali būti problema komandoms, turinčioms ribotus išteklius.


Dabar turite leidimo proceso planą, kuris gali išspręsti užsitęsusį diegimo laiką, perteklinį kūrimą ir padidėjusią frontend programų kokybės užtikrinimo riziką – visa tai. Visa tai kartu įvedant naują garantuoto nuoseklumo lygį visose aplinkose.


Užuot prireikę N versijų, jums reikės tik vieno. Būsimam leidimui galite tiesiog įdiegti jau išbandytą versiją, kuri taip pat padeda išspręsti galimas trikčių problemas, nes ta pati versija bus naudojama visose aplinkose. Be to, šio scenarijaus vykdymo greitis yra nepalyginamai greitesnis nei net labiausiai optimizuoto kūrimo. Pavyzdžiui, vietiniai etalonai „MacBook 14 PRO“, M1, 32 GB yra tokie:


Mano požiūris supaprastina išleidimo procesą, palaiko programos našumą, leisdamas veiksmingas talpyklos strategijas ir užtikrina, kad su kūrimu susijusios klaidos nepateks į aplinką. Be to, visas laikas ir pastangos, kurios anksčiau buvo skiriamos varginančioms kūrimo užduotims, dabar gali būti sutelktos į dar geresnės vartotojo patirties kūrimą. Ko nemylėti?


Užtikriname, kad su kūrimu susijusios klaidos nepatektų į programą, skirtą kitoms aplinkoms. Gali būti fantominių klaidų, kurios atsiranda dėl kūrimo sistemų trūkumų. Tikimybė nedidelė, bet jos egzistuoja.



L O A D I N G
. . . comments & more!

About Author

Egor Grushin HackerNoon profile picture
Egor Grushin@egorgrushin
11+ years of experience both in software development and architecture for highload B2B and B2C projects.

PABAIGTI ŽYMES

ŠIS STRAIPSNIS BUVO PRISTATYMAS...