<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Koduj]]></title><description><![CDATA[Poruszamy tematy Web developmentu. JavaScript, CSS, HTML. Koduj z nami!]]></description><link>https://koduj.eu/</link><image><url>https://koduj.eu/favicon.png</url><title>Koduj</title><link>https://koduj.eu/</link></image><generator>Ghost 5.13</generator><lastBuildDate>Sat, 18 Apr 2026 00:44:29 GMT</lastBuildDate><atom:link href="https://koduj.eu/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Angular na AWS S3: Hosting w 6 krokach]]></title><description><![CDATA[Jako developer, znasz moc Angulara w tworzeniu dynamicznych i interaktywnych aplikacji internetowych. Ale co z hostingiem? Szukasz rozwiązania prostego, skalowalnego i przyjaznego dla budżetu? AWS S3 może okazać się idealną odpowiedzią!]]></description><link>https://koduj.eu/angular-na-aws-s3-hosting-w-6-krokach/</link><guid isPermaLink="false">662022c57d4ceddb3919135c</guid><category><![CDATA[angular]]></category><category><![CDATA[aws]]></category><category><![CDATA[hosting]]></category><dc:creator><![CDATA[Radomir Skrzepij]]></dc:creator><pubDate>Thu, 18 Apr 2024 17:03:00 GMT</pubDate><media:content url="https://koduj.eu/content/images/2024/04/Angular-na-AWS-S3-Hosting-w-7-krokach-5.jpg" medium="image"/><content:encoded><![CDATA[<h2 id="czym-jest-aws-s3">Czym jest AWS S3?</h2><img src="https://koduj.eu/content/images/2024/04/Angular-na-AWS-S3-Hosting-w-7-krokach-5.jpg" alt="Angular na AWS S3: Hosting w 6 krokach"><p>Amazon Simple Storage Service (S3) to platforma chmurowa oferuj&#x105;ca bezpieczne i skalowalne przechowywanie obiekt&#xF3;w. Jest to popularny wyb&#xF3;r do hostowania statycznych stron internetowych, aplikacji internetowych, a nawet obraz&#xF3;w i film&#xF3;w. S3 s&#x142;ynie z prostoty u&#x17C;ytkowania, niskich koszt&#xF3;w i niezawodno&#x15B;ci.</p><h2 id="dlaczego-warto-hostowa%C4%87-angulara-na-aws-s3">Dlaczego warto hostowa&#x107; Angulara na AWS S3?</h2><ul><li><strong><strong>Prostota:</strong></strong> S3 jest niezwykle &#x142;atwy w konfiguracji i u&#x17C;ytkowaniu. Wystarczy utworzy&#x107; bucket, przes&#x142;a&#x107; pliki aplikacji i skonfigurowa&#x107; adres URL.</li><li><strong><strong>Skalowalno&#x15B;&#x107;:</strong></strong> S3 mo&#x17C;e automatycznie skalowa&#x107; si&#x119; w g&#xF3;r&#x119; lub w d&#xF3;&#x142; w zale&#x17C;no&#x15B;ci od potrzeb aplikacji. Bez wzgl&#x119;du na to, czy obs&#x142;ugujesz ruch z kilku os&#xF3;b, czy z milion&#xF3;w u&#x17C;ytkownik&#xF3;w, S3 poradzi sobie z tym bez problemu.</li><li><strong><strong>Niskie koszty:</strong></strong> S3 oferuje darmowy plan, kt&#xF3;ry obejmuje 5 GB pami&#x119;ci masowej i 20 000 &#x17C;&#x105;da&#x144; miesi&#x119;cznie. To &#x15B;wietne rozwi&#x105;zanie do testowania i hostowania ma&#x142;ych aplikacji. Nawet po wyczerpaniu darmowego poziomu, S3 nadal oferuje konkurencyjne ceny.</li><li><strong><strong>Wysoka dost&#x119;pno&#x15B;&#x107;:</strong></strong> S3 replikuje dane w wielu centrach danych na ca&#x142;ym &#x15B;wiecie, co zapewnia wysok&#x105; dost&#x119;pno&#x15B;&#x107; i odporno&#x15B;&#x107; na awarie.</li><li><strong><strong>Bezpiecze&#x144;stwo:</strong></strong> S3 oferuje szereg funkcji bezpiecze&#x144;stwa, kt&#xF3;re chroni&#x105; Twoje dane przed nieautoryzowanym dost&#x119;pem.</li></ul><p>Praca z AWS to nie tylko u&#x142;atwienie hostingu, ale r&#xF3;wnie&#x17C; doskona&#x142;a okazja do rozwoju zawodowego. AWS jest niezwykle popularny na rynku IT, a umiej&#x119;tno&#x15B;&#x107; jego obs&#x142;ugi to cenny atut w CV ka&#x17C;dego dewelopera. Znajomo&#x15B;&#x107; S3 mo&#x17C;e u&#x142;atwi&#x107; Ci znalezienie nowej pracy, awans zawodowy, a nawet przej&#x15B;cie do roli DevOpsa, gdzie umiej&#x119;tno&#x15B;&#x107; zarz&#x105;dzania infrastruktur&#x105; chmurow&#x105; jest wysoko ceniona.</p><h2 id="1-zak%C5%82adanie-nowego-konta-na-aws">1. Zak&#x142;adanie nowego konta na AWS</h2><p>Wchodzimy na stron&#x119; rejestracyjn&#x105; AWS: &#xA0;<a href="https://portal.aws.amazon.com/billing/signup">https://portal.aws.amazon.com/billing/signup</a></p><p>B&#x119;dziemy potrzebowali potwierdzi&#x107; kilka danych w procesie rejestracji: </p><ul><li>E-mail</li><li>Numer telefonu</li><li>Dane karty kredytowej (mo&#x17C;na u&#x17C;y&#x107; tymczasowej np. Revolut) </li></ul><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text"><em>Wszystkie dane s&#x105; weryfikowane, wi&#x119;c musz&#x105; by&#x107; poprawne. </em><br><br><em>Z karty kredytowej pobrana jest op&#x142;ata w wysoko&#x15B;ci 1$, kt&#xF3;ra zostanie automatycznie zwr&#xF3;cona po kilku dniach.</em></div></div><h2 id="pierwsze-logowanie-i-wst%C4%99pne-ustawienia">Pierwsze logowanie i wst&#x119;pne ustawienia </h2><p>Po poprawnej rejestracji logujemy si&#x119; do panelu adresem e-mail i has&#x142;em.</p><p>Na pocz&#x105;tku dobrze sobie wybra&#x107; lokalizacj&#x119;, w kt&#xF3;rej b&#x119;d&#x105; tworzone nasze us&#x142;ugi.</p><p>Dost&#x119;pne lokalizacje widoczne s&#x105; w prawym g&#xF3;rnym rogu panelu.</p><p>Domy&#x15B;lnie b&#x119;dzie lokalizacja gdzie&#x15B; w Stanach Zjednoczonych. &#x17B;eby mie&#x107; troch&#x119; lepsze pingi (czasy odpowiedzi serwera) polecam ustawi&#x107; lokalizacje us&#x142;ugi na co&#x15B; bli&#x17C;ej nas lub grupy docelowej aplikacji. </p><p>W przypadku Polski, polecam ustawi&#x107; Frankfurt, albo inny region zaczynaj&#x105;cy si&#x119; od <code>eu</code>.</p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2024/04/image-5.png" class="kg-image" alt="Angular na AWS S3: Hosting w 6 krokach" loading="lazy" width="579" height="870"></figure><p>Z kolei w lewym g&#xF3;rnym rogu mo&#x17C;emy zapozna&#x107; si&#x119; z dost&#x119;pnymi serwisami, wyszuka&#x107; konkretnej us&#x142;ugi i doda&#x107; je do ulubionych.</p><p>W tym celu klikamy w pole wyszukania, wpisujemy S3 i klikamy gwiazdk&#x119;, aby doda&#x107; us&#x142;ug&#x119; do paska ulubionych. Dzi&#x119;ki temu szybciej dostaniemy si&#x119; do naszych najwa&#x17C;niejszych us&#x142;ug w przysz&#x142;o&#x15B;ci.</p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2024/04/Screenshot-2024-04-17-at-22.02.31.png" class="kg-image" alt="Angular na AWS S3: Hosting w 6 krokach" loading="lazy" width="2000" height="597" srcset="https://koduj.eu/content/images/size/w600/2024/04/Screenshot-2024-04-17-at-22.02.31.png 600w, https://koduj.eu/content/images/size/w1000/2024/04/Screenshot-2024-04-17-at-22.02.31.png 1000w, https://koduj.eu/content/images/size/w1600/2024/04/Screenshot-2024-04-17-at-22.02.31.png 1600w, https://koduj.eu/content/images/2024/04/Screenshot-2024-04-17-at-22.02.31.png 2098w" sizes="(min-width: 720px) 720px"></figure><h2 id="2-tworzenie-nowego-bucketu-s3">2. Tworzenie nowego bucketu S3</h2><p>Wchodzimy w us&#x142;ug&#x119; S3 (z pasku na g&#xF3;rze) i klikamy utworzenie nowego bucketa - czyli przestrzeni w kt&#xF3;rej przechowywana b&#x119;dzie nasza zbudowana aplikacja Angularowa. </p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2024/04/image-1.png" class="kg-image" alt="Angular na AWS S3: Hosting w 6 krokach" loading="lazy" width="1514" height="222" srcset="https://koduj.eu/content/images/size/w600/2024/04/image-1.png 600w, https://koduj.eu/content/images/size/w1000/2024/04/image-1.png 1000w, https://koduj.eu/content/images/2024/04/image-1.png 1514w" sizes="(min-width: 720px) 720px"></figure><p>W cz&#x119;&#x15B;ci g&#x142;&#xF3;wnej konfiguracji nowego bucketa wpisujemy nazw&#x119;, kt&#xF3;ra musi by&#x107; unikatowa. Reszt&#x119; pozostawiamy bez zmian.</p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2024/04/image-2.png" class="kg-image" alt="Angular na AWS S3: Hosting w 6 krokach" loading="lazy" width="1128" height="506" srcset="https://koduj.eu/content/images/size/w600/2024/04/image-2.png 600w, https://koduj.eu/content/images/size/w1000/2024/04/image-2.png 1000w, https://koduj.eu/content/images/2024/04/image-2.png 1128w" sizes="(min-width: 720px) 720px"></figure><p>W sekcji &apos;<strong>Object Ownership&apos;</strong> zostawiamy domy&#x15B;lne ustawienia, czyli &apos;ACLs disabled&apos; - nie b&#x119;dziemy korzystali z tej opcji.</p><p>Nast&#x119;pnie mamy cz&#x119;&#x15B;&#x107; z ustawieniami dost&#x119;pu. Tutaj musimy odznaczy&#x107; opcj&#x119; &apos;block all public access&apos;, poniewa&#x17C; chcemy aby nasza aplikacja by&#x142;a dost&#x119;pna publicznie. </p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2024/04/image-3.png" class="kg-image" alt="Angular na AWS S3: Hosting w 6 krokach" loading="lazy" width="1222" height="1064" srcset="https://koduj.eu/content/images/size/w600/2024/04/image-3.png 600w, https://koduj.eu/content/images/size/w1000/2024/04/image-3.png 1000w, https://koduj.eu/content/images/2024/04/image-3.png 1222w" sizes="(min-width: 720px) 720px"></figure><p>Pozosta&#x142;e sekcje: <br>- <strong>Bucket Versioning, </strong><br>- <strong>Tags, </strong><br>- <strong>Default encryption</strong> <br>zostawiamy bez zmian.</p><p>Ustawienia zaawansowane r&#xF3;wnie&#x17C; w tym przypadku nas nie dotycz&#x105;. </p><p>Przechodzimy na sam d&#xF3;&#x142; strony i klikamy w prawym dolnym rogu &apos;Create bucket&apos;</p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2024/04/image-4.png" class="kg-image" alt="Angular na AWS S3: Hosting w 6 krokach" loading="lazy" width="1230" height="214" srcset="https://koduj.eu/content/images/size/w600/2024/04/image-4.png 600w, https://koduj.eu/content/images/size/w1000/2024/04/image-4.png 1000w, https://koduj.eu/content/images/2024/04/image-4.png 1230w" sizes="(min-width: 720px) 720px"></figure><p>Po tym zabiegu przeniesie nas do listy bucket&#xF3;w, na kt&#xF3;rej zobaczymy nowo utworzony kontener</p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2024/04/image-6.png" class="kg-image" alt="Angular na AWS S3: Hosting w 6 krokach" loading="lazy" width="1868" height="306" srcset="https://koduj.eu/content/images/size/w600/2024/04/image-6.png 600w, https://koduj.eu/content/images/size/w1000/2024/04/image-6.png 1000w, https://koduj.eu/content/images/size/w1600/2024/04/image-6.png 1600w, https://koduj.eu/content/images/2024/04/image-6.png 1868w" sizes="(min-width: 720px) 720px"></figure><h2 id="3-konfiguracja-aws-s3-pod-web-hosting">3. Konfiguracja AWS S3 pod Web Hosting</h2><p>Mamy utworzony nowy bucket i jest do niego publiczny dost&#x119;p, ale potrzebujemy doda&#x107; jeszcze kilka regu&#x142; i przede wszystkim &#x2014; aktywowa&#x107; na nim us&#x142;ug&#x119; Web Hostingu.</p><h4 id="aktywowanie-us%C5%82ugi-web-hostingu-na-s3">Aktywowanie us&#x142;ugi Web Hostingu na S3:</h4><p><br>Na li&#x15B;cie bucket&#xF3;w, klikamy w nasz nowo utworzony, nast&#x119;pnie przechodzimy w zak&#x142;adk&#x119; &quot;Properties&quot;</p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2024/04/image-13.png" class="kg-image" alt="Angular na AWS S3: Hosting w 6 krokach" loading="lazy" width="1068" height="392" srcset="https://koduj.eu/content/images/size/w600/2024/04/image-13.png 600w, https://koduj.eu/content/images/size/w1000/2024/04/image-13.png 1000w, https://koduj.eu/content/images/2024/04/image-13.png 1068w" sizes="(min-width: 720px) 720px"></figure><p>Zje&#x17C;d&#x17C;amy na sam d&#xF3;&#x142; strony i klikamy &quot;Edit&quot; w sekcji &quot;Static website hosting&quot;</p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2024/04/image-14.png" class="kg-image" alt="Angular na AWS S3: Hosting w 6 krokach" loading="lazy" width="1856" height="270" srcset="https://koduj.eu/content/images/size/w600/2024/04/image-14.png 600w, https://koduj.eu/content/images/size/w1000/2024/04/image-14.png 1000w, https://koduj.eu/content/images/size/w1600/2024/04/image-14.png 1600w, https://koduj.eu/content/images/2024/04/image-14.png 1856w" sizes="(min-width: 720px) 720px"></figure><p>W ekranie edycji:</p><ul><li>aktywujemy opcje &quot;Static website hosting&quot; </li><li>upewniamy si&#x119;, &#x17C;e mamy zaznaczon&#x105; opcj&#x119; &quot;Host a static website&quot;</li><li>Ustawiamy w polach &quot;Index document&quot; oraz &quot;Error document&quot; t&#x105; sam&#x105; warto&#x15B;&#x107;: <code>index.html</code> </li></ul><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2024/04/image-15.png" class="kg-image" alt="Angular na AWS S3: Hosting w 6 krokach" loading="lazy" width="1234" height="1036" srcset="https://koduj.eu/content/images/size/w600/2024/04/image-15.png 600w, https://koduj.eu/content/images/size/w1000/2024/04/image-15.png 1000w, https://koduj.eu/content/images/2024/04/image-15.png 1234w" sizes="(min-width: 720px) 720px"></figure><p>Zapisujemy zmiany i je&#x17C;eli wszystko jest dobrze wype&#x142;nione, zostaniemy przekierowani na detale naszego bucketa, do zak&#x142;adki &quot;Properties&quot;. </p><p>Ponownie przechodz&#x105;c na sam d&#xF3;&#x142; strony, powinni&#x15B;my widzie&#x107; informacje o aktywowanym Static website hostingu oraz link do naszej publicznej witryny</p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2024/04/image-16.png" class="kg-image" alt="Angular na AWS S3: Hosting w 6 krokach" loading="lazy" width="1364" height="452" srcset="https://koduj.eu/content/images/size/w600/2024/04/image-16.png 600w, https://koduj.eu/content/images/size/w1000/2024/04/image-16.png 1000w, https://koduj.eu/content/images/2024/04/image-16.png 1364w" sizes="(min-width: 720px) 720px"></figure><p>Jednak gdy spr&#xF3;bujemy przej&#x15B;&#x107; na dedykowany adres URL, dostaniemy b&#x142;&#x105;d 403 - brak dost&#x119;pu. Dlatego musimy jeszcze przypisa&#x107; odpowiednie regu&#x142;y dost&#x119;powe. </p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2024/04/image-17.png" class="kg-image" alt="Angular na AWS S3: Hosting w 6 krokach" loading="lazy" width="540" height="210"></figure><h4 id="okre%C5%9Blenie-regu%C5%82-dost%C4%99powych">Okre&#x15B;lenie regu&#x142; dost&#x119;powych</h4><p>Ci&#x105;gle b&#x119;d&#x105;c w widoku detalu naszego bucketa, przechodzimy do zak&#x142;adki &quot;Permissions&quot; i klikamy &quot;Edit&quot; w sekcji &quot;Bucket policy&quot;. <br></p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2024/04/image-18.png" class="kg-image" alt="Angular na AWS S3: Hosting w 6 krokach" loading="lazy" width="1882" height="1230" srcset="https://koduj.eu/content/images/size/w600/2024/04/image-18.png 600w, https://koduj.eu/content/images/size/w1000/2024/04/image-18.png 1000w, https://koduj.eu/content/images/size/w1600/2024/04/image-18.png 1600w, https://koduj.eu/content/images/2024/04/image-18.png 1882w" sizes="(min-width: 720px) 720px"></figure><p>W polu tekstowym wpisujemy nast&#x119;puj&#x105;c&#x105; konfiguracje: </p><!--kg-card-begin: markdown--><pre><code class="language-JSON">{
  &quot;Version&quot;: &quot;2012-10-17&quot;,
  &quot;Statement&quot;: [
    {
      &quot;Sid&quot;: &quot;PublicRead&quot;,
      &quot;Principal&quot;: &quot;*&quot;,
      &quot;Effect&quot;: &quot;Allow&quot;,
      &quot;Action&quot;: [
        &quot;s3:GetObject&quot;
      ],
      &quot;Resource&quot;: [
        &quot;arn:aws:s3:::nazwa-bucketa/*&quot;
      ]
    }
  ]
}
</code></pre>
<!--kg-card-end: markdown--><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">&#x1F449;</div><div class="kg-callout-text">Nale&#x17C;y pami&#x119;ta&#x107;, aby zmieni&#x107; warto&#x15B;&#x107; &apos;nazwa-bucketa&apos; na w&#x142;a&#x15B;ciw&#x105; dla aktualizowanego przez nas bucketa.</div></div><p>W naszym przyk&#x142;adowym bucketcie, pe&#x142;na prawid&#x142;owa konfiguracja wygl&#x105;da tak: </p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2024/04/image-20.png" class="kg-image" alt="Angular na AWS S3: Hosting w 6 krokach" loading="lazy" width="1086" height="1070" srcset="https://koduj.eu/content/images/size/w600/2024/04/image-20.png 600w, https://koduj.eu/content/images/size/w1000/2024/04/image-20.png 1000w, https://koduj.eu/content/images/2024/04/image-20.png 1086w" sizes="(min-width: 720px) 720px"></figure><p>Zapisujemy zmiany. Przechodzimy do zakladki &quot;Properties&quot;, zje&#x17C;d&#x17C;amy na sam d&#xF3;&#x142; strony i jeszcze raz pr&#xF3;bujemy wej&#x15B;&#x107; na dedykowany dla tego bucketa adres URL.</p><p>Je&#x17C;eli wszystko zrobili&#x15B;my dobrze, to teraz powinien nam si&#x119; wy&#x15B;wietli&#x107; b&#x142;&#x105;d 404:</p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2024/04/image-21.png" class="kg-image" alt="Angular na AWS S3: Hosting w 6 krokach" loading="lazy" width="682" height="266" srcset="https://koduj.eu/content/images/size/w600/2024/04/image-21.png 600w, https://koduj.eu/content/images/2024/04/image-21.png 682w"></figure><p>Co oznacza, &#x17C;e dost&#x119;py s&#x105; dobrze skonfigurowane. B&#x142;&#x105;d wynika z tego, &#x17C;e nie wrzucili&#x15B;my jeszcze plik&#xF3;w aplikacji na nasz hosting S3. </p><p>Je&#x17C;eli wrzuciliby&#x15B;my jaki&#x15B; plik index.html, to ju&#x17C; prawid&#x142;owo si&#x119; wy&#x15B;wietli.</p><p>No ale przejd&#x17A;my teraz do aplikacji Angularowej.</p><h2 id="4-tworzenie-nowej-aplikacji">4. Tworzenie nowej aplikacji</h2><p>Zapewne posiadasz ju&#x17C; jak&#x105;&#x15B; aplikacj&#x119; napisan&#x105; w Angularze, ale na wszelki wypadek zacznijmy od pocz&#x105;tku, czyli utworzenia podstawowej aplikacji zgodnie z dokumentacja dost&#x119;pn&#x105; na oficjalnej stronie <a href="https://angular.io/guide/setup-local">angular.io</a>. </p><p>W wielkim skr&#xF3;cie:</p><ol><li>Instalujemy node.js wraz z npm (najlepiej przez <a href="https://github.com/nvm-sh/nvm">nvm</a>)</li><li>Instalujemy globalnie Angular CLI poleceniem w terminalu:<br><code>npm install -g @angular/cli</code></li><li>Inicjujemy nowy projekt Angular poleceniem: <br><code>ng new my-app</code><br>i odpowiadamy na pojawiaj&#x105;ce si&#x119; pytania zgodnie z naszymi preferencjami.</li><li>Dla pewno&#x15B;ci uruchamiamy aplikacj&#x119; przez:<br><code>npm run start</code><br>i sprawdzamy w przegl&#x105;darce czy aplikacja prawid&#x142;owo si&#x119; wy&#x15B;wietla pod adresem <code><a href="http://localhost:53016/">http://localhost:</a>4200</code></li></ol><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2024/04/image-11.png" class="kg-image" alt="Angular na AWS S3: Hosting w 6 krokach" loading="lazy" width="1658" height="1114" srcset="https://koduj.eu/content/images/size/w600/2024/04/image-11.png 600w, https://koduj.eu/content/images/size/w1000/2024/04/image-11.png 1000w, https://koduj.eu/content/images/size/w1600/2024/04/image-11.png 1600w, https://koduj.eu/content/images/2024/04/image-11.png 1658w" sizes="(min-width: 720px) 720px"></figure><p>W przypadku Angular v17 domy&#x15B;lna strona powinna wygl&#x105;da&#x107; ta:</p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2024/04/image-8.png" class="kg-image" alt="Angular na AWS S3: Hosting w 6 krokach" loading="lazy" width="1174" height="624" srcset="https://koduj.eu/content/images/size/w600/2024/04/image-8.png 600w, https://koduj.eu/content/images/size/w1000/2024/04/image-8.png 1000w, https://koduj.eu/content/images/2024/04/image-8.png 1174w" sizes="(min-width: 720px) 720px"></figure><h2 id="5-budowanie-aplikacji">5. Budowanie aplikacji</h2><p>Gdy jeste&#x15B;my ju&#x17C; pewni, &#x17C;e posiadamy dzia&#x142;aj&#x105;c&#x105; aplikacj&#x119;, mo&#x17C;emy przej&#x15B;&#x107; do procesu budowania.</p><p>W tym poradniku b&#x119;dziemy budowali aplikacje lokalnie, a wynik budowania przerzucimy na AWS S3.</p><hr><!--kg-card-begin: html--><p style="text-align: center">
          W kolejnym po&#x15B;cie zautomatyzujemy ten proces z wykorzystaniem GitHub Actions. Subskrybuj, aby by&#x107; na bie&#x17C;&#x105;co z aktualno&#x15B;ciami
          </p><!--kg-card-end: html--><div class="kg-card kg-button-card kg-align-center"><a href="#/portal/signup/" class="kg-btn kg-btn-accent">Subskrybuj</a></div><hr><p>Budowanie aplikacji odbywa si&#x119; standardowo, przez wywo&#x142;anie polecenia <code>npm run build</code>.</p><p>Po zako&#x144;czonym procesie budowania powinni&#x15B;my zobaczy&#x107; w naszym projekcie nowy folder o nazwie <code>dist</code>, w kt&#xF3;rym znajduje si&#x119; nasza zbudowana aplikacja, a konkretnie:</p><!--kg-card-begin: markdown--><pre><code class="language-bash">my-app/
&#x251C;&#x2500; dist/
&#x2502;  &#x251C;&#x2500; my-app/
&#x2502;  &#x2502;  &#x251C;&#x2500; browser/
</code></pre>
<!--kg-card-end: markdown--><p>Proces budowania i wygenerowane pliki powinny wygl&#x105;da&#x107; przyk&#x142;adowo w taki spos&#xF3;b:</p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2024/04/image-12.png" class="kg-image" alt="Angular na AWS S3: Hosting w 6 krokach" loading="lazy" width="1536" height="726" srcset="https://koduj.eu/content/images/size/w600/2024/04/image-12.png 600w, https://koduj.eu/content/images/size/w1000/2024/04/image-12.png 1000w, https://koduj.eu/content/images/2024/04/image-12.png 1536w" sizes="(min-width: 720px) 720px"></figure><p>Tak wygenerowane pliki, mo&#x17C;emy ju&#x17C; wrzuca&#x107; na nasz skonfigurowany bucket S3.</p><h2 id="6-wrzucenie-zbudowanej-aplikacji-na-aws-s3">6. Wrzucenie zbudowanej aplikacji na AWS S3</h2><p>To ju&#x17C; ostatni krok, &#x17C;eby osi&#x105;gn&#x105;&#x107; nasz cel. </p><p>Wchodzimy ponownie na stron&#x119; z detalami naszego skonfigurowanego bucketa. Przechodzimy do zak&#x142;adki &quot;Objects&quot; i klikamy w przycisk &quot;Upload&quot;</p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2024/04/image-22.png" class="kg-image" alt="Angular na AWS S3: Hosting w 6 krokach" loading="lazy" width="1950" height="864" srcset="https://koduj.eu/content/images/size/w600/2024/04/image-22.png 600w, https://koduj.eu/content/images/size/w1000/2024/04/image-22.png 1000w, https://koduj.eu/content/images/size/w1600/2024/04/image-22.png 1600w, https://koduj.eu/content/images/2024/04/image-22.png 1950w" sizes="(min-width: 720px) 720px"></figure><p>Klikamy &quot;Add files&quot; i dodajemy wszystkie pliki z naszej <strong>zbudowanej</strong> aplikacji Angular, czyli w naszym przypadku zawartosc folderu <code>my-app/dist/my-app/browser/</code> </p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2024/04/image-23.png" class="kg-image" alt="Angular na AWS S3: Hosting w 6 krokach" loading="lazy" width="1582" height="960" srcset="https://koduj.eu/content/images/size/w600/2024/04/image-23.png 600w, https://koduj.eu/content/images/size/w1000/2024/04/image-23.png 1000w, https://koduj.eu/content/images/2024/04/image-23.png 1582w" sizes="(min-width: 720px) 720px"></figure><p>Po dodaniu plik&#xF3;w upewniamy si&#x119;, &#x17C;e lista plik&#xF3;w zgadza si&#x119; z tym co mamy lokalnie na komputerze. </p><p>Je&#x17C;eli wszystko jest ok, nic wi&#x119;cej nie zmiemiamy, tylko klikamy &quot;Upload&quot; w prawym dolnym rogu</p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2024/04/image-24.png" class="kg-image" alt="Angular na AWS S3: Hosting w 6 krokach" loading="lazy" width="1270" height="1380" srcset="https://koduj.eu/content/images/size/w600/2024/04/image-24.png 600w, https://koduj.eu/content/images/size/w1000/2024/04/image-24.png 1000w, https://koduj.eu/content/images/2024/04/image-24.png 1270w" sizes="(min-width: 720px) 720px"></figure><p>Zostaniemy nast&#x119;pnie poinformowani, czy wszystkie pliki wgra&#x142;y sie prawid&#x142;owo.</p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2024/04/image-25.png" class="kg-image" alt="Angular na AWS S3: Hosting w 6 krokach" loading="lazy" width="1718" height="1140" srcset="https://koduj.eu/content/images/size/w600/2024/04/image-25.png 600w, https://koduj.eu/content/images/size/w1000/2024/04/image-25.png 1000w, https://koduj.eu/content/images/size/w1600/2024/04/image-25.png 1600w, https://koduj.eu/content/images/2024/04/image-25.png 1718w" sizes="(min-width: 720px) 720px"></figure><p>I na tym koniec! </p><p>Pozostaje ponownie odwiedzi&#x107; nasz dedykowany adres URL i cieszy&#x107; si&#x119; z opublikowanej aplikacji Angularowej &#x1F44F;</p><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text">Us&#x142;uga AWS S3 jest dost&#x119;pna za darmo dla pojemno&#x15B;ci maksymalnie 5GB w ramach pakietu Free Tier dost&#x119;pnego dla nowych klient&#xF3;w.<br>Po tym okresie, obowi&#x105;zuje standardowy cennik dost&#x119;pny na: https://aws.amazon.com/s3/pricing/</div></div><h2 id="podsumowanie"><br><strong>Podsumowanie</strong></h2><p>W tym artykule poznali&#x15B;my prost&#x105; i skuteczn&#x105; metod&#x119; hostowania aplikacji Angulara na AWS S3. <br>Przeszli&#x15B;my przez 6 krok&#xF3;w, kt&#xF3;re obejmowa&#x142;y konfiguracj&#x119; konta AWS, utworzenie bucketa S3, skonfigurowanie hostingu statycznego, ustawienie regu&#x142; dost&#x119;pu i wgranie zbudowanej aplikacji.</p><p>Warto r&#xF3;wnie&#x17C; wspomnie&#x107;, &#x17C;e AWS S3 doskonale nadaje si&#x119; nie tylko do hostowania aplikacji Angulara. Mo&#x17C;emy tam r&#xF3;wnie&#x17C; umieszcza&#x107; aplikacje napisane w <strong>React.js, Astro</strong> czy proste strony statyczne. <br>Dzi&#x119;ki temu zyskujemy uniwersaln&#x105; platform&#x119; hostingow&#x105;, kt&#xF3;ra spe&#x142;ni potrzeby wielu projekt&#xF3;w webowych zar&#xF3;wno hobbystycznych, jak i komercyjnych.</p><h4 id="dodatkowe-linki">Dodatkowe linki:</h4><ul><li>Oficjalna strona AWS S3: <a href="https://aws.amazon.com/s3/" rel="noopener noreferrer">https://aws.amazon.com/s3/</a></li><li>Oficjalna dokumentacja Angulara: <a href="https://angular.io/" rel="noopener noreferrer">https://angular.io/</a></li><li>Oficjalna dokumentacja React.js: <a href="https://react.dev/">https://react.dev/</a></li></ul>]]></content:encoded></item><item><title><![CDATA[Sygnały w Angularze 16 - część 2]]></title><description><![CDATA[<p><a href="https://koduj.eu/sygnaly-w-angularze-16-czesc-1/">W cz&#x119;&#x15B;ci 1 artyku&#x142;u</a> przedstawili&#x15B;my podstawowe informacje o sygna&#x142;ach w Angularze 16. W tej cz&#x119;&#x15B;ci om&#xF3;wimy bardziej szczeg&#xF3;&#x142;owo dzia&#x142;anie sygna&#x142;&#xF3;w i ich zastosowanie w praktyce.</p><h3 id="dzia%C5%82anie-sygna%C5%82%C3%B3w">Dzia&#x142;anie</h3>]]></description><link>https://koduj.eu/sygnaly-w-angularze-16-czesc-2/</link><guid isPermaLink="false">64f22186fb969e1161862206</guid><category><![CDATA[angular]]></category><category><![CDATA[javascript]]></category><dc:creator><![CDATA[Radomir Skrzepij]]></dc:creator><pubDate>Sun, 11 Feb 2024 18:34:00 GMT</pubDate><media:content url="https://koduj.eu/content/images/2023/09/Angular-Signals-p2.png" medium="image"/><content:encoded><![CDATA[<img src="https://koduj.eu/content/images/2023/09/Angular-Signals-p2.png" alt="Sygna&#x142;y w Angularze 16 - cz&#x119;&#x15B;&#x107; 2"><p><a href="https://koduj.eu/sygnaly-w-angularze-16-czesc-1/">W cz&#x119;&#x15B;ci 1 artyku&#x142;u</a> przedstawili&#x15B;my podstawowe informacje o sygna&#x142;ach w Angularze 16. W tej cz&#x119;&#x15B;ci om&#xF3;wimy bardziej szczeg&#xF3;&#x142;owo dzia&#x142;anie sygna&#x142;&#xF3;w i ich zastosowanie w praktyce.</p><h3 id="dzia%C5%82anie-sygna%C5%82%C3%B3w">Dzia&#x142;anie sygna&#x142;&#xF3;w</h3><p>Sygna&#x142;y dzia&#x142;aj&#x105; na zasadzie obserwowalno&#x15B;ci (observable). Ka&#x17C;dy sygna&#x142; ma swoj&#x105; w&#x142;asn&#x105; kolejk&#x119; zdarze&#x144;, do kt&#xF3;rej dodawane s&#x105; emitowane warto&#x15B;ci. Komponenty, kt&#xF3;re s&#x105; subskrybowane na sygnale, s&#x105; automatycznie informowane o nowych warto&#x15B;ciach w kolejce zdarze&#x144;.</p><p>Warto&#x15B;ci emitowane przez sygna&#x142;y mog&#x105; by&#x107; dowolnego typu danych. Mog&#x105; to by&#x107; liczby, tekst, obiekty, listy, czy mapy.</p><h3 id="subskrypcja-na-sygna%C5%82y">Subskrypcja na sygna&#x142;y</h3><p>Aby subskrybowa&#x107; si&#x119; na sygna&#x142;, nale&#x17C;y u&#x17C;y&#x107; metody <code>subscribe()</code>. Metoda <code>subscribe()</code> przyjmuje funkcj&#x119; jako parametr. Funkcja ta jest wykonywana po zmianie warto&#x15B;ci sygna&#x142;u.</p><p>Metoda <code>subscribe()</code> mo&#x17C;e przyjmowa&#x107; r&#xF3;wnie&#x17C; inne parametry, takie jak:</p><ul><li><code>next()</code>: parametr ten jest u&#x17C;ywany do przekazywania warto&#x15B;ci sygna&#x142;u do funkcji.</li><li><code>error()</code>: parametr ten jest u&#x17C;ywany do przekazywania b&#x142;&#x119;d&#xF3;w do funkcji.</li><li><code>complete()</code>: parametr ten jest u&#x17C;ywany do informowania o zako&#x144;czeniu subskrypcji.</li></ul><h3 id="kiedy-stosowa%C4%87-sygna%C5%82y">Kiedy stosowa&#x107; sygna&#x142;y</h3><p>Sygna&#x142;y mog&#x105; by&#x107; u&#x17C;ywane w r&#xF3;&#x17C;nych sytuacjach w aplikacjach Angularowych. Oto kilka przyk&#x142;ad&#xF3;w zastosowania sygna&#x142;&#xF3;w:</p><ul><li><strong>Komunikacja pomi&#x119;dzy komponentami</strong><br> sygna&#x142;y mog&#x105; by&#x107; u&#x17C;ywane do przekazywania danych pomi&#x119;dzy komponentami.</li><li><strong>Wydawanie zdarze&#x144;</strong><br> sygna&#x142;y mog&#x105; by&#x107; u&#x17C;ywane do emitowania zdarze&#x144;, kt&#xF3;re mog&#x105; by&#x107; obs&#x142;ugiwane przez inne komponenty lub us&#x142;ugi.</li><li><strong>Podtrzymanie stanu aplikacji</strong><br> sygna&#x142;y mog&#x105; by&#x107; u&#x17C;ywane do podtrzymywania stanu aplikacji.</li></ul><h3 id="kiedy-nie-stosowa%C4%87-sygna%C5%82%C3%B3w">Kiedy nie stosowa&#x107; sygna&#x142;&#xF3;w</h3><p>Sygna&#x142;y to pot&#x119;&#x17C;ne narz&#x119;dzie, ale nie powinno si&#x119; ich u&#x17C;ywa&#x107; w ka&#x17C;dym przypadku. Oto kilka sytuacji, w kt&#xF3;rych nie nale&#x17C;y stosowa&#x107; sygna&#x142;&#xF3;w:</p><ul><li>Do przekazywania danych, kt&#xF3;re nie s&#x105; zmienne: je&#x15B;li dane nie s&#x105; zmienne, to nie ma potrzeby ich przekazywania za pomoc&#x105; sygna&#x142;&#xF3;w. W takim przypadku mo&#x17C;na po prostu u&#x17C;y&#x107; w&#x142;a&#x15B;ciwo&#x15B;ci komponentu.</li><li>Do przekazywania danych, kt&#xF3;re s&#x105; u&#x17C;ywane tylko w jednym komponencie: je&#x15B;li dane s&#x105; u&#x17C;ywane tylko w jednym komponencie, to nie ma potrzeby ich przekazywania za pomoc&#x105; sygna&#x142;&#xF3;w. W takim przypadku mo&#x17C;na po prostu u&#x17C;y&#x107; w&#x142;a&#x15B;ciwo&#x15B;ci komponentu lub innej metody dost&#x119;pu do danych.</li><li>Do przekazywania danych, kt&#xF3;re s&#x105; u&#x17C;ywane tylko w jednym cyklu detekcji zmian: je&#x15B;li dane s&#x105; u&#x17C;ywane tylko w jednym cyklu detekcji zmian, to nie ma potrzeby ich przekazywania za pomoc&#x105; sygna&#x142;&#xF3;w. W takim przypadku mo&#x17C;na po prostu u&#x17C;y&#x107; w&#x142;a&#x15B;ciwo&#x15B;ci komponentu lub innej metody dost&#x119;pu do danych.</li></ul><h3 id="kilka-dodatkowych-wskaz%C3%B3wek-kt%C3%B3re-pomog%C4%85-ci-zdecydowa%C4%87-czy-u%C5%BCy%C4%87-sygna%C5%82u">Kilka dodatkowych wskaz&#xF3;wek, kt&#xF3;re pomog&#x105; Ci zdecydowa&#x107;, czy u&#x17C;y&#x107; sygna&#x142;u</h3><ul><li>Je&#x15B;li nie jeste&#x15B; pewien, czy u&#x17C;y&#x107; sygna&#x142;u, to lepiej go nie u&#x17C;ywa&#x107;.</li><li>Je&#x15B;li musisz przekaza&#x107; dane pomi&#x119;dzy komponentami, to sygna&#x142; jest dobrym wyborem.</li><li>Je&#x15B;li musisz emitowa&#x107; zdarzenia, to sygna&#x142; jest dobrym wyborem.</li><li>Je&#x15B;li musisz podtrzymywa&#x107; stan aplikacji, to sygna&#x142; jest dobrym wyborem.</li></ul><h3 id="przyk%C5%82ad-zastosowania-sygna%C5%82u-do-podtrzymywania-stanu-aplikacji-i-inkrementacji">Przyk&#x142;ad zastosowania sygna&#x142;u do podtrzymywania stanu aplikacji i inkrementacji</h3><pre><code class="language-javascript">// Komponent emituj&#x105;cy sygna&#x142;
@Component({
  selector: &apos;my-component&apos;,
  templateUrl: &apos;./my-component.component.html&apos;,
  styleUrls: [&apos;./my-component.component.css&apos;]
})
export class MyComponent {

  @Output() mySignal = new EventEmitter();

  constructor() {
    this.myState = 10;
  }

  onIncrement() {
    this.myState++;
    this.mySignal.emit(this.myState);
  }

}

// Komponent subskrybuj&#x105;cy si&#x119; na sygna&#x142;
@Component({
  selector: &apos;my-subscriber&apos;,
  templateUrl: &apos;./my-subscriber.component.html&apos;,
  styleUrls: [&apos;./my-subscriber.component.css&apos;]
})
export class MySubscriber {

  constructor(private readonly myComponent: MyComponent) {
    this.myComponent.mySignal.subscribe((value) =&gt; {
      console.log(value);
    });
  }

}

// HTML

&lt;div class=&quot;my-component&quot;&gt;
  &lt;button (click)=&quot;myComponent.onIncrement()&quot;&gt;+&lt;/button&gt;
&lt;/div&gt;</code></pre><p>W tym przyk&#x142;adzie sygna&#x142; jest u&#x17C;ywany do podtrzymywania stanu liczbowego komponentu <code>MyComponent</code>. Kiedy u&#x17C;ytkownik kliknie przycisk <code>+</code>, warto&#x15B;&#x107; stanu komponentu zostanie zwi&#x119;kszona o 1. Sygna&#x142; <code>mySignal</code> zostanie r&#xF3;wnie&#x17C; wyemitowany, aby poinformowa&#x107; inne komponenty o zmianie stanu.</p><h3 id="podsumowanie">Podsumowanie</h3><p>Sygna&#x142;y to pot&#x119;&#x17C;ne narz&#x119;dzie, kt&#xF3;re mo&#x17C;e znacz&#x105;co ulepszy&#x107; wydajno&#x15B;&#x107; i responsywno&#x15B;&#x107; aplikacji Angularowych. Je&#x15B;li jeszcze nie korzystasz z sygna&#x142;&#xF3;w, warto si&#x119; z nimi zapozna&#x107;.</p>]]></content:encoded></item><item><title><![CDATA[Sygnały w Angularze 16 - część 1]]></title><description><![CDATA[<p><a href="https://angular.io/guide/update-to-version-16">Angular 16</a> wprowadzi&#x142; szereg nowo&#x15B;ci, z kt&#xF3;rych jedn&#x105; z najbardziej znacz&#x105;cych jest wprowadzenie sygna&#x142;&#xF3;w. Sygna&#x142;y to nowy spos&#xF3;b przekazywania danych pomi&#x119;dzy komponentami, kt&#xF3;ry jest bardziej reaktywny i wydajny ni&#x17C; tradycyjne</p>]]></description><link>https://koduj.eu/sygnaly-w-angularze-16-czesc-1/</link><guid isPermaLink="false">64f0fa7d3e685e9dfee8ea4f</guid><category><![CDATA[angular]]></category><category><![CDATA[javascript]]></category><dc:creator><![CDATA[Radomir Skrzepij]]></dc:creator><pubDate>Tue, 30 Jan 2024 22:05:00 GMT</pubDate><media:content url="https://koduj.eu/content/images/2023/08/Angular-Signals-p1-2.png" medium="image"/><content:encoded><![CDATA[<img src="https://koduj.eu/content/images/2023/08/Angular-Signals-p1-2.png" alt="Sygna&#x142;y w Angularze 16 - cz&#x119;&#x15B;&#x107; 1"><p><a href="https://angular.io/guide/update-to-version-16">Angular 16</a> wprowadzi&#x142; szereg nowo&#x15B;ci, z kt&#xF3;rych jedn&#x105; z najbardziej znacz&#x105;cych jest wprowadzenie sygna&#x142;&#xF3;w. Sygna&#x142;y to nowy spos&#xF3;b przekazywania danych pomi&#x119;dzy komponentami, kt&#xF3;ry jest bardziej reaktywny i wydajny ni&#x17C; tradycyjne metody.</p><h3 id="zalety-sygna%C5%82%C3%B3w">Zalety sygna&#x142;&#xF3;w</h3><p>Sygna&#x142;y oferuj&#x105; szereg korzy&#x15B;ci w por&#xF3;wnaniu do tradycyjnych metod przekazywania danych:</p><ul><li><strong>S&#x105; bardziej reaktywne:</strong> sygna&#x142;y automatycznie wykrywaj&#x105; zmiany i propaguj&#x105; je do komponent&#xF3;w, kt&#xF3;re s&#x105; na nich subskrybowane. Dzi&#x119;ki temu dane s&#x105; zawsze aktualne, bez konieczno&#x15B;ci stosowania jawnych subskrypcji.</li></ul><p>W tradycyjnych metodach przekazywania danych, takich jak przekazywanie w&#x142;a&#x15B;ciwo&#x15B;ci lub metod, nale&#x17C;y jawnie subskrybowa&#x107; si&#x119; na zmian&#x119; warto&#x15B;ci. Oznacza to, &#x17C;e komponent musi wykona&#x107; dodatkow&#x105; operacj&#x119;, aby sprawdzi&#x107;, czy warto&#x15B;&#x107; si&#x119; zmieni&#x142;a. Sygna&#x142;y eliminuj&#x105; t&#x119; potrzeb&#x119;, automatycznie informuj&#x105;c komponenty o zmianach.</p><ul><li><strong>S&#x105; bardziej wydajne:</strong> sygna&#x142;y nie wymagaj&#x105; tworzenia obiekt&#xF3;w obserwowalnych, co mo&#x17C;e znacz&#x105;co poprawi&#x107; wydajno&#x15B;&#x107; aplikacji.</li></ul><p>Obiekty obserwowalne s&#x105; u&#x17C;ywane do przekazywania danych pomi&#x119;dzy komponentami w tradycyjnych metodach. S&#x105; one obiektami, kt&#xF3;re monitoruj&#x105; zmiany warto&#x15B;ci i informuj&#x105; o nich subskrybent&#xF3;w. Sygna&#x142;y nie wymagaj&#x105; tworzenia obiekt&#xF3;w obserwowalnych, poniewa&#x17C; mog&#x105; same monitorowa&#x107; zmiany warto&#x15B;ci.</p><ul><li><strong>S&#x105; bardziej elastyczne:</strong> sygna&#x142;y mog&#x105; by&#x107; u&#x17C;ywane do przekazywania dowolnego typu danych, w tym obiekt&#xF3;w, list i map.</li></ul><p>Obiekty obserwowalne s&#x105; ograniczone do przekazywania danych typu obiektu. Sygna&#x142;y nie maj&#x105; tej ograniczenia i mog&#x105; by&#x107; u&#x17C;ywane do przekazywania dowolnego typu danych.</p><h3 id="jak-u%C5%BCywa%C4%87-sygna%C5%82%C3%B3w">Jak u&#x17C;ywa&#x107; sygna&#x142;&#xF3;w</h3><p>U&#x17C;ycie sygna&#x142;&#xF3;w jest bardzo proste. Aby utworzy&#x107; sygna&#x142;, nale&#x17C;y u&#x17C;y&#x107; adnotacji <code>@Output()</code>:</p><pre><code class="language-javascript">@Output() mySignal = new EventEmitter();
</code></pre><p>Adnotacja <code>@Output()</code> tworzy obiekt <code>EventEmitter</code>, kt&#xF3;ry jest u&#x17C;ywany do emitowania warto&#x15B;ci sygna&#x142;u.</p><p>Aby subskrybowa&#x107; si&#x119; na sygna&#x142;, nale&#x17C;y u&#x17C;y&#x107; metody <code>subscribe()</code>:</p><pre><code class="language-javascript">component.mySignal.subscribe((value) =&gt; {
  // Wykonaj akcj&#x119; po zmianie warto&#x15B;ci sygna&#x142;u.
});
</code></pre><p>Metoda <code>subscribe()</code> przyjmuje funkcj&#x119; jako parametr, kt&#xF3;ra jest wykonywana po zmianie warto&#x15B;ci sygna&#x142;u.</p><h3 id="przyk%C5%82ad-zastosowania-sygna%C5%82%C3%B3w">Przyk&#x142;ad zastosowania sygna&#x142;&#xF3;w</h3><p>Poni&#x17C;ej znajduje si&#x119; przyk&#x142;ad zastosowania sygna&#x142;&#xF3;w:</p><pre><code class="language-javascript">// Komponent emituj&#x105;cy sygna&#x142;
@Component({
  selector: &apos;my-signal-component&apos;,
  templateUrl: &apos;./my-signal-component.component.html&apos;,
  styleUrls: [&apos;./my-signal-component.component.css&apos;]
})

export class MySignalComponent {

  @Output() mySignal = new EventEmitter();

  constructor() {
    this.mySignal.emit(10);
  }

}

// Komponent subskrybuj&#x105;cy si&#x119; na sygna&#x142;
@Component({
  selector: &apos;my-subscriber&apos;,
  templateUrl: &apos;./my-subscriber.component.html&apos;,
  styleUrls: [&apos;./my-subscriber.component.css&apos;]
})

export class MySubscriber {

  constructor(private readonly mySignalComponent: MySignalComponent) {
    this.mySignalComponent.mySignal.subscribe((value) =&gt; {
      console.log(value);
    });
  }

}
</code></pre><p>Wynik dzia&#x142;ania tego kodu:</p><pre><code class="language-bash">10
</code></pre><p>W tym przyk&#x142;adzie komponent <code>MyComponent</code> emituje warto&#x15B;&#x107; 10 za pomoc&#x105; sygna&#x142;u <code>mySignal</code>. Komponent <code>MySubscriber</code> subskrybuje si&#x119; na sygnale <code>mySignal</code> i wy&#x15B;wietla warto&#x15B;&#x107; w konsoli po jej zmianie.</p><h3 id="kontynuacja-w-cz%C4%99%C5%9Bci-2">Kontynuacja w cz&#x119;&#x15B;ci 2</h3><p>W cz&#x119;&#x15B;ci 2 artyku&#x142;u om&#xF3;wimy bardziej szczeg&#xF3;&#x142;owo dzia&#x142;anie sygna&#x142;&#xF3;w i ich zastosowanie w praktyce.</p>]]></content:encoded></item><item><title><![CDATA[Łatwy sposób na jasna i ciemna wersje strony z color-scheme]]></title><description><![CDATA[<figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2023/07/Jasny--900-507-px-.png" class="kg-image" alt loading="lazy" width="900" height="507" srcset="https://koduj.eu/content/images/size/w600/2023/07/Jasny--900-507-px-.png 600w, https://koduj.eu/content/images/2023/07/Jasny--900-507-px-.png 900w" sizes="(min-width: 720px) 720px"></figure><p>W miar&#x119; rozwoju technologii webowych, tw&#xF3;rcy stron internetowych coraz cz&#x119;&#x15B;ciej staraj&#x105; si&#x119; dostarcza&#x107; u&#x17C;ytkownikom lepsze do&#x15B;wiadczenia i personalizacj&#x119;. Jednym z aspekt&#xF3;w, kt&#xF3;ry nabiera popularno&#x15B;ci, jest mo&#x17C;liwo&#x15B;&#x107;</p>]]></description><link>https://koduj.eu/css-color-scheme/</link><guid isPermaLink="false">63235a432645f53e9dd012a5</guid><category><![CDATA[css]]></category><dc:creator><![CDATA[Radomir Skrzepij]]></dc:creator><pubDate>Wed, 13 Dec 2023 15:30:00 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2023/07/Jasny--900-507-px-.png" class="kg-image" alt loading="lazy" width="900" height="507" srcset="https://koduj.eu/content/images/size/w600/2023/07/Jasny--900-507-px-.png 600w, https://koduj.eu/content/images/2023/07/Jasny--900-507-px-.png 900w" sizes="(min-width: 720px) 720px"></figure><p>W miar&#x119; rozwoju technologii webowych, tw&#xF3;rcy stron internetowych coraz cz&#x119;&#x15B;ciej staraj&#x105; si&#x119; dostarcza&#x107; u&#x17C;ytkownikom lepsze do&#x15B;wiadczenia i personalizacj&#x119;. Jednym z aspekt&#xF3;w, kt&#xF3;ry nabiera popularno&#x15B;ci, jest mo&#x17C;liwo&#x15B;&#x107; oferowania stron w wersji jasnej i ciemnej. Dzi&#x119;ki CSS color-scheme i prefers-color-scheme, programi&#x15B;ci maj&#x105; prosty spos&#xF3;b na zapewnienie tego rodzaju personalizacji. W tym artykule przyjrzymy si&#x119;, jak CSS color-scheme i prefers-color-scheme dzia&#x142;aj&#x105; jako &#x142;atwe narz&#x119;dzia s&#x142;u&#x17C;&#x105;ce do serwowania stron w wersji jasnej i ciemnej. Dodatkowo, dowiemy si&#x119;, jak mo&#x17C;na zastosowa&#x107; color-scheme tak&#x17C;e w meta tagach HTML.</p><h2 id="css-color-scheme">CSS color-scheme</h2><p>CSS color-scheme to w&#x142;a&#x15B;ciwo&#x15B;&#x107; CSS, kt&#xF3;ra umo&#x17C;liwia tw&#xF3;rcom stron internetowych okre&#x15B;lanie preferencji kolorystycznych dla zawarto&#x15B;ci na stronie. Mo&#x17C;na j&#x105; zastosowa&#x107; do ca&#x142;ej strony lub do konkretnych element&#xF3;w, takich jak t&#x142;a, czcionki, linki itp. Dzi&#x119;ki color-scheme, tw&#xF3;rcy mog&#x105; definiowa&#x107; dwie opcje kolorystyczne: jasn&#x105; (light) i ciemn&#x105; (dark). To daje u&#x17C;ytkownikom mo&#x17C;liwo&#x15B;&#x107; wyboru preferowanej wersji kolorystycznej w zale&#x17C;no&#x15B;ci od swoich upodoba&#x144; lub preferencji.</p><h2 id="u%C5%BCycie-color-scheme-w-meta-tagach-html">U&#x17C;ycie color-scheme w meta tagach HTML</h2><p>Color-scheme mo&#x17C;na r&#xF3;wnie&#x17C; zastosowa&#x107; w meta tagach HTML, co pozwala na kontrol&#x119; kolor&#xF3;w interfejsu przegl&#x105;darki, takich jak paski narz&#x119;dziowe i przyciski. Mo&#x17C;na to osi&#x105;gn&#x105;&#x107; poprzez dodanie atrybutu <code>color-scheme</code> do elementu <code>&lt;meta name=&quot;theme-color&quot; content=&quot;#ffffff&quot; color-scheme=&quot;light dark&quot;&gt;</code>. Dzi&#x119;ki temu, mo&#x17C;na okre&#x15B;li&#x107; preferowane wersje kolorystyczne dla interfejsu przegl&#x105;darki, a u&#x17C;ytkownicy mog&#x105; dostosowa&#x107; wygl&#x105;d przegl&#x105;darki do swoich preferencji.</p><h2 id="prefers-color-scheme-jako-media-query">Prefers-color-scheme jako media query</h2><p>Prefers-color-scheme to mechanizm media query, kt&#xF3;ry sprawdza preferencje kolorystyczne u&#x17C;ytkownika. Dzi&#x119;ki niemu, tw&#xF3;rcy stron internetowych mog&#x105; personalizowa&#x107; wygl&#x105;d swojej strony, dostosowuj&#x105;c go do preferencji jasnego lub ciemnego motywu, ustalonych przez u&#x17C;ytkownika w ustawieniach systemowych swojego urz&#x105;dzenia. Przyk&#x142;ad u&#x17C;ycia prefers-color-scheme wygl&#x105;da nast&#x119;puj&#x105;co:</p><!--kg-card-begin: markdown--><pre><code class="language-css">@media (prefers-color-scheme: dark) {
  /* Style dla ciemnego motywu */
}

@media (prefers-color-scheme: light) {
  /* Style dla jasnego motywu */
}
</code></pre>
<!--kg-card-end: markdown--><p>Dzi&#x119;ki prefers-color-scheme, strony internetowe mog&#x105; automatycznie dostosowywa&#x107; sw&#xF3;j wygl&#x105;d do preferencji kolorystycznych u&#x17C;ytkownik&#xF3;w, co pozwala na bardziej spersonalizowane do&#x15B;wiadczenie.</p><h3 id="podsumowanie">Podsumowanie: </h3><p>CSS color-scheme i prefers-color-scheme to narz&#x119;dzia, kt&#xF3;re umo&#x17C;liwiaj&#x105; programistom &#x142;atwe serwowanie stron w wersji jasnej i ciemnej. Poprzez okre&#x15B;lanie preferencji kolorystycznych dla zawarto&#x15B;ci na stronie oraz wykorzystanie mechanizmu media query, tw&#xF3;rcy stron mog&#x105; personalizowa&#x107; wygl&#x105;d swoich stron i interfejs&#xF3;w w zale&#x17C;no&#x15B;ci od preferencji u&#x17C;ytkownik&#xF3;w. U&#x17C;ycie color-scheme w meta tagach HTML daje r&#xF3;wnie&#x17C; mo&#x17C;liwo&#x15B;&#x107; kontrolowania kolor&#xF3;w interfejsu przegl&#x105;darki. Dzi&#x119;ki tym narz&#x119;dziom, dostarczanie spersonalizowanych wersji strony internetowej staje si&#x119; prostsze i bardziej efektywne.</p><p>Personalizacja i dostosowanie do preferencji u&#x17C;ytkownik&#xF3;w to jedne z kluczowych czynnik&#xF3;w, kt&#xF3;re przyczyniaj&#x105; si&#x119; do doskona&#x142;ego do&#x15B;wiadczenia u&#x17C;ytkownika na stronach internetowych. Dzi&#x119;ki CSS color-scheme i prefers-color-scheme, tw&#xF3;rcy stron mog&#x105; zapewni&#x107; u&#x17C;ytkownikom wi&#x119;ksz&#x105; swobod&#x119; w wyborze preferowanej wersji kolorystycznej, przyczyniaj&#x105;c si&#x119; do bardziej satysfakcjonuj&#x105;cego odbioru ich tre&#x15B;ci.</p>]]></content:encoded></item><item><title><![CDATA[Zdalne odpalanie Bitbucket Pipeline]]></title><description><![CDATA[<h2 id="bitbucket-pipelines">Bitbucket Pipelines</h2><p>Bitbucket, poza tym, &#x17C;e jest serwisem na kt&#xF3;rym mo&#x17C;emy trzyma&#x107; swoje repozytoria GIT, pozwala nam tak&#x17C;e na odpalanie Pipeline&apos;&#xF3;w. </p><p>Podobn&#x105; funckjonalno&#x15B;&#x107;&#xA0;oferuj&#x105; inne popularne hostingi GITa, takie jak Github (Actions) czy Gitlab</p>]]></description><link>https://koduj.eu/zdalne-odpalanie-bitbucket-pipeline/</link><guid isPermaLink="false">633b52cbecc9297def0d914a</guid><category><![CDATA[javascript]]></category><category><![CDATA[ci/cd]]></category><category><![CDATA[git]]></category><category><![CDATA[strapi]]></category><dc:creator><![CDATA[Radomir Skrzepij]]></dc:creator><pubDate>Tue, 31 Oct 2023 23:39:00 GMT</pubDate><media:content url="https://koduj.eu/content/images/2022/10/bb-ci.jpg" medium="image"/><content:encoded><![CDATA[<h2 id="bitbucket-pipelines">Bitbucket Pipelines</h2><img src="https://koduj.eu/content/images/2022/10/bb-ci.jpg" alt="Zdalne odpalanie Bitbucket Pipeline"><p>Bitbucket, poza tym, &#x17C;e jest serwisem na kt&#xF3;rym mo&#x17C;emy trzyma&#x107; swoje repozytoria GIT, pozwala nam tak&#x17C;e na odpalanie Pipeline&apos;&#xF3;w. </p><p>Podobn&#x105; funckjonalno&#x15B;&#x107;&#xA0;oferuj&#x105; inne popularne hostingi GITa, takie jak Github (Actions) czy Gitlab (Pipelines). Poza tym, mamy mo&#x17C;liwo&#x15B;&#x107; korzystania z dedykowanych aplikacji zewn&#x119;trznych, aby osi&#x105;gn&#x105;&#x107; ten sam cel - mo&#x17C;emy tutaj wymieni&#x107; mi&#x119;dzy innymi takie narz&#x119;dzia jak Circle CI, Travis czy Jenkins.</p><p>Uruchomianie Pipeline&apos;&#xF3;w ma na celu automatyzacje pewnych czynno&#x15B;ci, takich jak uruchamianie test&#xF3;w, sprawdzanie jako&#x15B;ci kodu czy deployment. W skr&#xF3;cie, te akcje, nazywamy CI / CD i stanowi&#x105; one ju&#x17C; pewnego rodzaju standard przy budowaniu nowoczesnych aplikacji. Wi&#x119;cej na ten temat napiszemy w innym po&#x15B;cie.</p><p>Na t&#x105; chwil&#x119;, wa&#x17C;ne &#x17C;eby&#x15B; wiedzia&#x142;, ka&#x17C;dy dostawca CI / CD, jak to w &#x17C;yciu bywa, ma zar&#xF3;wno pewne zalety jak i wady. Bitbucket nie jest tutaj wyj&#x105;tkiem. Dzisiaj postaramy si&#x119; rozwi&#x105;za&#x107; jeden z problem&#xF3;w, kt&#xF3;rym jest zdalne odpalanie pipelin&#xF3;w.</p><h2 id="po-co-nam-zdalny-dost%C4%99p-do-pipelines">Po co nam zdalny dost&#x119;p do Pipelines?</h2><p>Zazwyczaj, konkretny Pipeline, czyli konkretne akcje, wykonywane s&#x105; po wykryciu zdefiniowanej czynno&#x15B;ci w repozytorium GIT. Najcz&#x119;&#x15B;ciej jest to Pull Request do repozytorium lub wykrycie zmian w kodzie, na konkretnym branchu. </p><p>W innych przypadkach, mo&#x17C;emy r&#xF3;wnie&#x17C; ustawi&#x107; odpalanie Pipeline&apos;a w okre&#x15B;lonym czasie, cyklicznie. Mo&#x17C;e by&#x107;&#xA0;to przydatne przy odpalaniu test&#xF3;w End-to-End, aby sprawdza&#x107;, czy nie ma regresji i kluczowe funkcjonalno&#x15B;ci naszej aplikacji dzia&#x142;aj&#x105; jak nale&#x17C;y.</p><p>Zdalny dost&#x119;p mo&#x17C;e si&#x119; jednak przyda&#x107;, gdy chcemy aby Pipeline wystartowa&#x142; w momencie wyst&#x105;pienia jakich&#x15B; zmian poza naszym repozytorium GIT. Konkretny use case na kt&#xF3;ry ostatnio natrafilem:</p><ul><li>Wykorzystuj&#x105;c frontendowe frameworki takie jak Gatsby czy Next.js, budujemy aplikacj&#x119; frontendow&#x105;, sk&#x142;ada si&#x119; ona ze statycznych plik&#xF3;w HTML</li><li>Statyczne pliki budowane s&#x105; na podstawie zawarto&#x15B;ci zewn&#x119;trznego CMSa (np Wordpress, Strapi)</li><li>Kto&#x15B; wprowadzi zmiany w panelu administracyjnym, doda nowy wpis, edytuje lub usunie ju&#x17C; istniej&#x105;cy</li><li>Aplikacja frontendowa powinna si&#x119; przebudowa&#x107;, aby wygenerowa&#x107; dane zgodne z aktualn&#x105; zawarto&#x15B;ci&#x105; znajduj&#x105;c&#x105; si&#x119;&#xA0;w CMSie.</li></ul><p>Dzi&#x119;ki temu, w automatyczny spos&#xF3;b mo&#x17C;emy zautomatyzowa&#x107; proces deploymentu mega szybkiej aplikacji, kt&#xF3;ra nie b&#x119;dzie potrzebowa&#x142;a &#x142;&#x105;czenia si&#x119; z zewn&#x119;trznymi serwerami w celu pobierania danych do wy&#x15B;wietlenia. Jest to fajna opcja na prowadzenie niewielkiego bloga czy rzadko aktualizowanej strony, kt&#xF3;r&#x105; jednak chcemy zarz&#x105;dza&#x107; z poziomu panelu. </p><p>W takim w&#x142;a&#x15B;nie przypadku, chcieliby&#x15B;my poinformowa&#x107; Bitbucket&apos;a o tym, &#x17C;e dosz&#x142;o do jakich&#x15B; zmian wymagaj&#x105;cych odpalenia Pipeline&apos;a - w tym przypadku odpowiadaj&#x105;cego za przebudowanie aplikacji i deployment.</p><h2 id="ograniczenia-i-mo%C5%BCliwo%C5%9Bci-bitbucketa">Ograniczenia i mo&#x17C;liwo&#x15B;ci Bitbucketa</h2><p>Niekt&#xF3;re aplikacje umo&#x17C;liwiaj&#x105; stworzenie webhooka, kt&#xF3;rego wystarczy podpi&#x105;&#x107; w odpowiednie miejsce i aplikacja frontowa mo&#x17C;e si&#x119; nam przebudowa&#x107;. Przyk&#x142;adem jest tutaj Strapi CMS + Vercel, w kt&#xF3;rym mo&#x17C;emy sobie wygenerowa&#x107; klucz i podpi&#x105;&#x107; go w CMSie pod odpowiednie czynno&#x15B;ci, takie jak dodanie nowego wpisu. Dzi&#x119;ki temu zabiegowi, konkretne zmiany b&#x119;d&#x105; automatycznie odpala&#x142;y budowanie si&#x119; aplikacji. Super fajne! </p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2022/10/image.png" class="kg-image" alt="Zdalne odpalanie Bitbucket Pipeline" loading="lazy" width="2000" height="1380" srcset="https://koduj.eu/content/images/size/w600/2022/10/image.png 600w, https://koduj.eu/content/images/size/w1000/2022/10/image.png 1000w, https://koduj.eu/content/images/size/w1600/2022/10/image.png 1600w, https://koduj.eu/content/images/2022/10/image.png 2322w" sizes="(min-width: 720px) 720px"></figure><p>Bitbucket Pipeline nie ma mo&#x17C;liwo&#x15B;ci, aby w ultra prosty spos&#xF3;b odpali&#x107; dowolny Pipeline. Nie mo&#x17C;emy &apos;wyklika&#x107;&apos; sobie linku, pod kt&#xF3;ry po prostu strzelimy i konkretny Pipeline si&#x119; odpali.. Znaczy, uderza&#x107; pod pewien endpoint musimy, ale nie jest to a&#x17C; takie proste.</p><p>Dodatkowo, Bitbucket Pipelines zachowuj&#x105; si&#x119; domy&#x15B;lnie w spos&#xF3;b, kt&#xF3;ry w tym przypadku stwarza dodatkowe problemy. Ot&#xF3;&#x17C; je&#x17C;eli konkretny Pipeline jest ju&#x17C; uruchomiony i trwa, to kolejny, tak samo zdefiniowany Pipeline, automatycznie przechodzi w stan pauzy i mo&#x17C;emy go uruchomi&#x107; ponownie tylko r&#x119;cznie. My natomiast chcemy, aby nowy Pipeline powodowa&#x142; zatrzymanie wcze&#x15B;niejszego i rozpoczyna&#x142; swoj&#x105; prac&#x119;. Niestety, musimy ten przypadek r&#xF3;wnie&#x17C; obs&#x142;u&#x17C;y&#x107; r&#x119;cznie. </p><p>Na szcz&#x119;&#x15B;cie, Bitbucket oferuje do&#x15B;&#x107; szerokie mo&#x17C;liwo&#x15B;ci za po&#x15B;rednictwem dedykowanego <strong>API</strong>. Mo&#x17C;emy dzi&#x119;ki temu komunikowa&#x107; si&#x119;&#xA0;z naszymi Pipeline&apos;ami &#xA0;(i nie tylko) z zewn&#x105;trz. </p><p>Tak wi&#x119;c.. do dzie&#x142;a! </p><h2 id="strapi-cms-bitbucket-pipeline">Strapi CMS + Bitbucket Pipeline</h2><p>W naszym konkretnym przypadku, b&#x119;dziemy bazowali na Strapi CMS - kt&#xF3;ry odpowiada za dostarczanie tre&#x15B;ci do aplikacji frontowej. Po dokonaniu zmian w panelu CMSa, odpalimy konkretny Pipeline Dodatkowo, &#xA0;chcemy zastopowa&#x107; poprzedni, je&#x17C;eli nadal trwa. </p><p>No ale po kolei:</p><ol><li>Gdy nasze repozytorium na Bitbucket jest prywatne, musimy wygenerowa&#x107; sobie has&#x142;o aplikacji - aby m&#xF3;c autoryzowa&#x107; nasze strza&#x142;y do API. Je&#x17C;eli jest publiczne, pomi&#x144; ten krok. </li><li>W aplikacji backendowej (Strapi), definiujemy podstawow&#x105; konfiguracje, uwzgl&#x119;dniaj&#x105;c mi&#x119;dzy innymi headery czy w&#x142;a&#x15B;nie dane dost&#x119;powe. Wykorzystamy w tym celu bibliteke <code>Axios</code>:</li></ol><pre><code class="language-js">baseUrl = &quot;https://api.bitbucket.org/2.0/repositories/&lt;workspace&gt;/&lt;repository&gt;/&quot;

// Default axios settings for BitBucket connections
export const BitBucketClient = axios.create({
  baseURL: baseUrl,
  timeout: 2000,
  headers: {
    &quot;Content-Type&quot;: &quot;application/json&quot;,
  },
  auth: {
    username: &quot;username&quot;,
    password: &quot;bitbucketAppPassword&quot;,
  },
})</code></pre><p><code>baseUrl</code> - jest g&#x142;&#xF3;wnym adresem, pod kt&#xF3;rym b&#x119;dziemy sie komunikowa&#x107; z Bitbucket&apos;em. Najpro&#x15B;ciej wej&#x15B;&#x107; w konkretne repozytorium w przegl&#x105;darce i w URLu pojawi si&#x119; nam podobny zapis, z kt&#xF3;rego b&#x119;dziemy mogli przeklei&#x107; <code>&lt;workspace&gt;</code> oraz <code>&lt;repository&gt;</code>.</p><p>3. &#xA0;Przygotujmy metod&#x119;, kt&#xF3;ra pozwoli nam uderza&#x107; do Bitbucket, informuj&#x105;c o konieczno&#x15B;ci r&#x119;cznego odpalenia Pipeline&apos;a:</p><pre><code class="language-js">export const invokePipeline = async (): Promise&lt;void&gt; =&gt; {
  await BitBucketClient.post(`/pipelines/`, {
    target: {
      ref_type: &quot;branch&quot;,
      type: &quot;pipeline_ref_target&quot;,
      ref_name: &quot;production&quot;, //Name of target branch
    },
  })
}</code></pre><p>Na dobr&#x105; spraw&#x119;, tyle nam wystarczy, &#x17C;eby zdalnie odpali&#x107; Pipeline. Teraz wystarczy tylko w odpowiednim miejscu wywo&#x142;a&#x107; funkcje <code>invokePipeline</code>. W przypadku Strapi CMS, jest to plik <code>lifecycles.ts</code> , w kt&#xF3;rym mamy dost&#x119;p do metod cykli &#x17C;ycia kolekcji danych.</p><p>4. &#xA0;Wywo&#x142;anie funkcji <code>invokePipeline</code></p><pre><code class="language-js">// lifecycles.ts

export default {
  afterCreate(event: { params: { data: Record&lt;string, unknown&gt; } }) {
    invokePipeline()
  },
  afterUpdate(event: { params: { data: Record&lt;string, unknown&gt; } }) {
    invokePipeline()
  },

  afterDelete(event: { params: { data: Record&lt;string, unknown&gt; } }) {
    invokePipeline()
  },
}</code></pre><p>W ten spos&#xF3;b, nasz Pipeline, b&#x119;dzie si&#x119; odpala&#x142; za ka&#x17C;dym razem gdy dodamy, zaktualizujemy lub usuniemy jak&#x105;&#x15B; stron&#x119; kolekcji. </p><p>W przypadku innych CMS&#xF3;w, trzeba po prostu znale&#x17A;&#x107; odpowiednie miejsce gdzie mo&#x17C;na si&#x119; wpi&#x105;&#x107;.</p><p>Pami&#x119;tajmy jednak, &#x17C;e dobrze jest zamkn&#x105;&#x107; trwaj&#x105;cy, wcze&#x15B;niejszy Pipeline - je&#x17C;eli kto&#x15B; przyk&#x142;adowo w kr&#xF3;tkim czasie doda i edytuje wpis. Potrzebujemy do tego nast&#x119;pujace funkcje</p><p>5. Najpierw musimy pobra&#x107; ostatnie Pipeline&apos;y i sprawdzi&#x107;, czy kt&#xF3;ry&#x15B; z nich jest aktywny. Je&#x17C;eli tak, to zwracamy jego UUID - kt&#xF3;ry jest unikalny identyfikatorem, potrzebnym, &#x17C;eby w nast&#x119;pnym kroku powiedzie&#x107; kt&#xF3;ry Pipeline chcemy zatrzyma&#x107;</p><pre><code class="language-js">const getActivePipelineUUID = async (): Promise&lt;string | undefined&gt; =&gt; {
  //Get pipelines by newest
  const res = await BitBucketClient.get(`/pipelines/?sort=-created_on`)
  if ([201, 200].indexOf(res.status) === -1) return

  //Only values of pipelines
  const pipelines = res.data.values

  if (pipelines &amp;&amp; pipelines.length) {
  
    //Find pipeline data of our branch (&quot;production&quot;)
    const latestBranchPipeline = pipelines.find((p: any) =&gt; p.target?.ref_name === &quot;production&quot;)
    if (!latestBranchPipeline) return

    const triggeredManually = latestBranchPipeline.trigger.type === &quot;pipeline_trigger_manual&quot;
    const isInProgress = [&quot;pipeline_state_in_progress&quot;, &quot;pipeline_state_pending&quot;].includes(
      latestBranchPipeline.state.type,
    )

    return triggeredManually &amp;&amp; isInProgress ? latestBranchPipeline.uuid : undefined
  }
}</code></pre><p>6. No i jeszcze potrzebujemy metod&#x119; stopuj&#x105;c&#x105; pipeline</p><pre><code class="language-js">const stopPreviousPipeline = async (uuid: string): Promise&lt;number&gt; =&gt; {
  const res = await BitBucketClient.post(`/pipelines/${uuid}/stopPipeline`)
  return res.status
}</code></pre><p>7. &#xA0;Teraz mo&#x17C;emy nasze pomocnicze metody sprawdzaj&#x105;ce, u&#x17C;y&#x107; w metodzie g&#x142;&#xF3;wnej <code>invokePipeline</code></p><pre><code class="language-js">export const invokePipeline = async (): Promise&lt;void&gt; =&gt; {

  const activePipelineUUID = await getActivePipelineUUID()
  if (activePipelineUUID) await stopPreviousPipeline(activePipelineUUID)

  const res = await BitBucketClient.post(`/pipelines/`, {
    target: {
      ref_type: &quot;branch&quot;,
      type: &quot;pipeline_ref_target&quot;,
      ref_name: bitBucketBranch,
    },
  })
}</code></pre><p>To tyle. Po wprowadzeniu tych zmian, za ka&#x17C;dym razem gdy zmienimy co&#x15B; w naszym &#x17A;r&#xF3;dle danych - CMSie, odpowiedni Pipeline odpali si&#x119; powoduj&#x105;c przebudowanie aplikacji.</p><p>Oczywi&#x15B;cie dodatkowo polecam zabezpieczy&#x107; t&#x105; funkcjonalno&#x15B;&#x107; o sprawdzenie, czy jeste&#x15B;my na wersji produkcyjnej - przez chocia&#x17C;by wykorzystanie zmiennych &#x15B;rodowiskowych. </p><p>Bitbucket API daje nam du&#x17C;o wi&#x119;cej mo&#x17C;liwo&#x15B;ci, mo&#x17C;emy mi&#x119;dzy innymi odpala&#x107; konkretne commity, czy&#x15B;ci&#x107; cache i wiele wi&#x119;cej. Po szczeg&#xF3;&#x142;y zapraszam do oficjalnej dokumentacji API <a href="https://developer.atlassian.com/cloud/bitbucket/rest/api-group-pipelines/#api-group-pipelines"><code>https://developer.atlassian.com/cloud/bitbucket/rest/api-group-pipelines/#api-group-pipelines</code></a></p>]]></content:encoded></item><item><title><![CDATA[Jak dodać Syntax Highlighter w Ghost CMS]]></title><description><![CDATA[<h2 id="ghost-cms">Ghost CMS </h2><p>Nie b&#x119;dziemy si&#x119; tutaj zbytnio rozpisywa&#x107; na temat samego Ghost CMS. Natomiast, dobrze &#x17C;eby&#x15B; wiedzia&#x142;, o czym w og&#xF3;le piszemy i dlaczego. </p><p>Ghost CMS, najpro&#x15B;ciej m&#xF3;wi&#x105;c, jest alternatyw&#x105; dla bardzo popularnego Wordpressa.</p>]]></description><link>https://koduj.eu/ghost-cms-syntax-highlight/</link><guid isPermaLink="false">6328cf6e11b5ea138eaf6e68</guid><category><![CDATA[ghost]]></category><category><![CDATA[javascript]]></category><category><![CDATA[cms]]></category><dc:creator><![CDATA[Radomir Skrzepij]]></dc:creator><pubDate>Wed, 04 Oct 2023 22:09:00 GMT</pubDate><media:content url="https://koduj.eu/content/images/2022/09/ghost.jpeg" medium="image"/><content:encoded><![CDATA[<h2 id="ghost-cms">Ghost CMS </h2><img src="https://koduj.eu/content/images/2022/09/ghost.jpeg" alt="Jak doda&#x107; Syntax Highlighter w Ghost CMS"><p>Nie b&#x119;dziemy si&#x119; tutaj zbytnio rozpisywa&#x107; na temat samego Ghost CMS. Natomiast, dobrze &#x17C;eby&#x15B; wiedzia&#x142;, o czym w og&#xF3;le piszemy i dlaczego. </p><p>Ghost CMS, najpro&#x15B;ciej m&#xF3;wi&#x105;c, jest alternatyw&#x105; dla bardzo popularnego Wordpressa. R&#xF3;wnie&#x17C; powsta&#x142; z my&#x15B;l&#x105; o autorach blog&#xF3;w, aby w prosty spos&#xF3;b mogli prowadzi&#x107;&#xA0;swoje internetowe dzienniki.</p><p>G&#x142;&#xF3;wn&#x105; r&#xF3;&#x17C;nic&#x105; mi&#x119;dzy tymi systemami jest to, Ghost jest napisany w JSie (Node.js), natomiast Wordpress w PHP. <br>Ghost jest nowocze&#x15B;niejszym rozwi&#x105;zaniem, ale i mniej prze&#x142;adowanym. Mimo ci&#x105;g&#x142;ego rozwoju, system ci&#x105;gle skupia si&#x119; na byciu platform&#x105; blogow&#x105;, gdzie Wordpress ju&#x17C; dawno sta&#x142; si&#x119; kombajnem, kt&#xF3;rego wielu u&#x17C;ywa do prowadzenia sklep&#xF3;w, stron szkoleniowych czy innych.. Cz&#x119;sto nawet pozbawionych g&#x142;&#xF3;wnej funkcji - czyli blogu.</p><p>Tyle wystarczy s&#x142;owem wst&#x119;pu, temat zg&#x142;&#x119;bimy bardziej w osobnym wpisie, por&#xF3;wnuj&#x105;cym oba systemy.</p><h2 id="syntax-highlighter">Syntax highlighter</h2><p>Wiemy ju&#x17C;, &#x17C;e Ghost CMS mo&#x17C;e by&#x107; ciekawym rozwi&#x105;zaniem dla os&#xF3;b chc&#x105;cych prowadzi&#x107; sw&#xF3;j blog. Jednak je&#x17C;eli ma to by&#x107; blog techniczny, jedn&#x105; z g&#x142;&#xF3;wnych funkcjonalno&#x15B;ci jak&#x105; potrzebujesz do pisania rzeczowych post&#xF3;w, jest Syntax highlighter - czyli pod&#x15B;wietlanie sk&#x142;adni, kawa&#x142;k&#xF3;w kodu pisanych w r&#xF3;&#x17C;nych j&#x119;zykach. </p><p>Ghost, domy&#x15B;lnie oferuje pisanie blok&#xF3;w kodu (r&#xF3;wnie&#x17C; pe&#x142;ny Markdown), jednak nie ma wbudowania kolorowania sk&#x142;adni. Funkcjonalno&#x15B;&#x107; ta musi zosta&#x107; przez nas dopisana. I mo&#x17C;emy to zrobi&#x107; na kilka sposob&#xF3;w.</p><p>We wszystkich opisanych poni&#x17C;ej sposobach, b&#x119;dziemy implementowali w tym celu bibliotek&#x119; PrismJS - kt&#xF3;ra ju&#x17C; od dawna znajduje si&#x119; w &#x15B;cis&#x142;ej czo&#x142;&#xF3;wce bibliotek oferuj&#x105;cych kolorowanie sk&#x142;adni dla wielu j&#x119;zyk&#xF3;w programowania.</p><h3 id="spos%C3%B3b-1code-injection">Spos&#xF3;b 1 - Code Injection</h3><p>Najprostszym sposobem, jest podpi&#x119;cie biblioteki PrismJS bezpo&#x15B;rednio w Panelu Administracyjnym Ghost. </p><ol><li>Logujemy si&#x119; do Panelu Ghost</li><li>Wchodzimy w Settings &gt; Code Injection</li><li>W sekcji <code>Site Header</code> wrzucamy link do CSSa ze stylami Prism, kt&#xF3;re najbardziej nam odpowiadaj&#x105; np <code>Okaidia</code>:</li></ol><pre><code class="language-html">&lt;link rel=&quot;stylesheet&quot; href=&quot;https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-okaidia.min.css&quot; integrity=&quot;sha384-qTzu9jz8wpyzFe5KLoZfw0CS5iY+kCoZlBd5ByJ3f0NUT9dgCIU19M1IQKj594Ei&quot; crossorigin=&quot;anonymous&quot; referrerpolicy=&quot;no-referrer&quot;&gt;</code></pre><p>4. &#xA0;W sekcji <code>Site Footer</code> podpinamy niezb&#x119;dne pliki JS: </p><pre><code class="language-html">&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-core.min.js&quot; integrity=&quot;sha384-MXybTpajaBV0AkcBaCPT4KIvo0FzoCiWXgcihYsw4FUkEz0Pv3JGV6tk2G8vJtDc&quot; crossorigin=&quot;anonymous&quot; referrerpolicy=&quot;no-referrer&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js&quot; integrity=&quot;sha384-Uq05+JLko69eOiPr39ta9bh7kld5PKZoU+fF7g0EXTAriEollhZ+DrN8Q/Oi8J2Q&quot; crossorigin=&quot;anonymous&quot; referrerpolicy=&quot;no-referrer&quot;&gt;&lt;/script&gt;
</code></pre><p>5. &#xA0;Zapisujemy zmiany i kolorowanie sk&#x142;adni ju&#x17C; dzia&#x142;a! </p><p>Podpi&#x119;cie biblioteki powinno wygl&#x105;da&#x107; tak:</p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2022/09/Screenshot-2022-09-19-at-23.11.45.png" class="kg-image" alt="Jak doda&#x107; Syntax Highlighter w Ghost CMS" loading="lazy" width="1266" height="650" srcset="https://koduj.eu/content/images/size/w600/2022/09/Screenshot-2022-09-19-at-23.11.45.png 600w, https://koduj.eu/content/images/size/w1000/2022/09/Screenshot-2022-09-19-at-23.11.45.png 1000w, https://koduj.eu/content/images/2022/09/Screenshot-2022-09-19-at-23.11.45.png 1266w" sizes="(min-width: 720px) 720px"></figure><h3 id="spos%C3%B3b-2zmiany-w-szablonie-r%C4%99czne-%C5%9Bci%C4%85gni%C4%99cie-plik%C3%B3w">Spos&#xF3;b 2 - Zmiany w szablonie (r&#x119;czne &#x15B;ci&#x105;gni&#x119;cie plik&#xF3;w)</h3><p>Gdy mamy mo&#x17C;liwo&#x15B;&#x107; edycji naszego szablonu, z pewno&#x15B;ci&#x105; lepszym rozwi&#x105;zaniem b&#x119;dzie podpi&#x119;cie PrismJS bezpo&#x15B;rednio w kodzie. Najpierw zrobimy to w spos&#xF3;b bardziej manualny - czyli przez r&#x119;czne &#x15B;ci&#x105;gni&#x119;cie potrzebnych plik&#xF3;w. </p><ol><li>Wchodzimy na <a href="https://prismjs.com/download.html#themes=prism-tomorrow&amp;languages=markup+css+clike+javascript">oficjaln&#x105; stron&#x119; PrismJS</a> </li><li>Wybieramy tam szablon i j&#x119;zyki jakie chcemy obs&#x142;ugiwa&#x107;</li><li>Pobieramy wygenerowan&#x105; paczk&#x119; (JS i CSS)</li><li>Pobrany plik CSS wrzucamy do folderu <code>assets/css</code> w naszym szablonie Ghosta i importujemy go w pliku <code>assets/css/screen.css</code></li></ol><pre><code class="language-css">@import &quot;prismjs/themes/prism.css&quot;</code></pre><p>5. &#xA0;Pobrany plik JS przenosimy do folderu <code>assets/js/lib</code> - i to wszystko</p><p>6. &#xA0;Restartujemy Ghost CMS / przebudowujemy szablon i cieszymy si&#x119; eleganckim syntax highlightningiem.</p><h3 id="spos%C3%B3b-3zmiany-w-szablonie-npm-yarn">Spos&#xF3;b 3 - Zmiany w szablonie (npm / yarn)</h3><p>Jest to najbardziej zaawansowane rozwi&#x105;zanie, ale jednocze&#x15B;nie najbezpieczniejsze i umo&#x17C;liwia &#x142;atwe podbijanie biblioteki PrismJS w przysz&#x142;o&#x15B;ci. Tym razem, zamiast r&#x119;cznie, bibliotek&#x119; do pod&#x15B;wietlania sk&#x142;adni b&#x119;dziemy pobierali za pomoc&#x105; wybranego przez nas package managera. </p><ol><li>W folderze szablonu, instalujemy PrismJS <code>npm i -D prismjs</code></li><li>Je&#x17C;eli u&#x17C;ywamy TypeScripta, doci&#x105;gamy r&#xF3;wnie&#x17C; typy dla PrismJS - <code>npm i -D @types/prismjs</code></li><li>Podobnie jak we wcze&#x15B;niejszym sposobie, dodajemy plik CSS z definicj&#x105; kolor&#xF3;w do naszego g&#x142;&#xF3;wnego pliku CSS szablonu Ghost <code>assets/css/screen.css</code> np:</li></ol><pre><code class="language-css">@import &quot;prismjs/themes/prism-okaidia.css&quot;</code></pre><p>4. Dodajemy plik JS Prism&apos;a, do procesu tworzenia szablonu: </p><pre><code class="language-javascript">&apos;node_modules/prismjs/prism.js&apos;</code></pre><p>5. Przebudowujemy szablon Ghosta i mamy ju&#x17C; wsparcie dla kolorowania sk&#x142;adni.</p><p>Tym razem, nie mogli&#x15B;my podpi&#x105;&#x107; pliku <code>prism.js</code> po prostu wrzucaj&#x105;c go do <code>assets/js/lib</code> - chyba, &#x17C;e przekopiujemy zawarto&#x15B;&#x107; <code>prism.js</code> z <code>node_modules</code> - ale nie o to tu chodzi. <br>Plik JS musi zosta&#x107;&#xA0;dodany do konfiguracji task managera, kt&#xF3;rego u&#x17C;ywamy do budowania naszego szablonu. Powinna tam ju&#x17C; istnie&#x107; definicja innych plik&#xF3;w wej&#x15B;ciowych <code>.js</code></p><p>Przyk&#x142;adowo, w przypadku Gulpa, zapis b&#x119;dzie wygl&#x105;da&#x142; mniej wi&#x119;cej w taki spos&#xF3;b:</p><figure class="kg-card kg-image-card"><img src="https://koduj.eu/content/images/2022/09/Screenshot-2022-09-19-at-23.44.14.png" class="kg-image" alt="Jak doda&#x107; Syntax Highlighter w Ghost CMS" loading="lazy" width="785" height="328" srcset="https://koduj.eu/content/images/size/w600/2022/09/Screenshot-2022-09-19-at-23.44.14.png 600w, https://koduj.eu/content/images/2022/09/Screenshot-2022-09-19-at-23.44.14.png 785w" sizes="(min-width: 720px) 720px"></figure><h3 id="bonus">Bonus</h3><p>Je&#x17C;eli szablon naszego blogu ma r&#xF3;&#x17C;ne wersje kolorystyczne, uzale&#x17C;nione od preferencji systemowych u&#x17C;ytkownika, mo&#x17C;emy w prosty spos&#xF3;b doda&#x107;&#xA0;dwa r&#xF3;&#x17C;ne szablony kolorowania sk&#x142;adni. </p><p>W tym celu, w pliku <code>/assets/css/screen.css</code> - do kt&#xF3;rego importujemy nasz plik CSS z PrismaJS, dodajemy taki zapis:</p><pre><code class="language-CSS">@import &quot;prismjs/themes/prism-okaidia.css&quot; (prefers-color-scheme: dark);
@import &quot;prismjs/themes/prism.css&quot; (prefers-color-scheme: light);</code></pre><p>Dzi&#x119;ki temu, je&#x17C;eli osoba odwiedzaj&#x105;ca naszego bloga, ma preferowane kolory systemowe ustawione na ciemne, to serwowane mu b&#x119;dzie kolorowanie sk&#x142;adni w stylu <code>prism-okaidia</code> . Natomiast je&#x17C;eli preferowane kolory s&#x105; jasne, to nasz serwis zaprezentuje syntax highlighting w domy&#x15B;lnych, czyli jasnych barwach - <code>prism.css</code>. </p><h3 id="podoba%C5%82o-si%C4%99">Podoba&#x142;o si&#x119;?</h3><p>Na tym ko&#x144;czymy wpis o pod&#x15B;wietlaniu sk&#x142;adni. </p><p>Dajcie zna&#x107; czy wpis by&#x142; pomocny i czy nie mieli&#x15B;cie problem&#xF3;w z implementacj&#x105; tej funkcjonalno&#x15B;ci u siebie.</p><p>Je&#x17C;eli chcecie dowiedzie&#x107; si&#x119; wi&#x119;cej na temat Ghost CMS, jak z nim pracowa&#x107;, tworzy&#x107; / modyfikowa&#x107; szablony - r&#xF3;wnie&#x17C; jeste&#x15B;my do Waszej dyspozycji. </p><p>Nie ograniczajmy si&#x119; ju&#x17C; tylko do Wordpressa, kt&#xF3;ry tak cz&#x119;sto jest nadu&#x17C;ywany, oferujmy rozwi&#x105;zania odpowiednie do potrzeb. Wp&#x142;ynie to korzystnie na odbi&#xF3;r tworzonych przez nas aplikacji.</p>]]></content:encoded></item><item><title><![CDATA[Sposoby generowania aplikacji w Next.js]]></title><description><![CDATA[<p></p><p>Next.js jest aktualnie jednym z najbardziej popularnych framework&#xF3;w w &#x15B;wiecie JavaScript. </p><p>Du&#x17C;o os&#xF3;b i projekt&#xF3;w, przechodzi ze standardowo u&#x17C;ywanego Create React App, w&#x142;a&#x15B;nie na Nexta. Jednym z powod&#xF3;w jest to, &#x17C;e</p>]]></description><link>https://koduj.eu/sposoby-generowania-aplikacji-w-next-js/</link><guid isPermaLink="false">63168021446bafe90087abf0</guid><category><![CDATA[React]]></category><dc:creator><![CDATA[Radomir Skrzepij]]></dc:creator><pubDate>Fri, 01 Sep 2023 08:53:00 GMT</pubDate><media:content url="https://koduj.eu/content/images/2022/09/next-1.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://koduj.eu/content/images/2022/09/next-1.jpg" alt="Sposoby generowania aplikacji w Next.js"><p></p><p>Next.js jest aktualnie jednym z najbardziej popularnych framework&#xF3;w w &#x15B;wiecie JavaScript. </p><p>Du&#x17C;o os&#xF3;b i projekt&#xF3;w, przechodzi ze standardowo u&#x17C;ywanego Create React App, w&#x142;a&#x15B;nie na Nexta. Jednym z powod&#xF3;w jest to, &#x17C;e Next.js daje nam wi&#x119;ksz&#x105; kontrol&#x119; nad sposobem generowania SPA.</p><p>Zacznijmy mo&#x17C;e od definicji podstawowych sposob&#xF3;w generowania aplikacji frontendowej. Mo&#x17C;emy tutaj wymieni&#x107; mi&#x119;dzy innymi: </p><ul><li><strong>CSR</strong> (<em>Client Side Rendering</em>) - czyli zbudowana przez nas aplikacja, posiada w sobie du&#x17C;o skryptu JS, kt&#xF3;ry odczytywany jest przez interpreter przegl&#x105;darki. Mo&#x17C;na powiedzie&#x107;, &#x17C;e ca&#x142;y tekst, obrazki i inne elementy strony, opakowane s&#x105; w skrypt JavaScript. Mo&#x17C;e to powodowa&#x107; spore obci&#x105;&#x17C;enie po stronie przegl&#x105;darki u&#x17C;ytkownika</li><li><strong>SSR </strong>(<em>Server Side Rendering</em>) - w tym przypadku, tre&#x15B;ci strony pobierane s&#x105; z backendu. Wchodz&#x105;c na tak&#x105; aplikacje, zazwyczaj musimy poczeka&#x107; chwil&#x119;, a&#x17C; nasza przegl&#x105;darka wy&#x15B;le zapytanie o tre&#x15B;&#x107; do serwera, odbierze j&#x105; w formie responsa, a nast&#x119;pnie wy&#x15B;wietli otrzyman&#x105; zawarto&#x15B;&#x107;. Takie rozwi&#x105;zanie powoduje, &#x17C;e przegl&#x105;darka u&#x17C;ytkownika jest mniej obci&#x105;&#x17C;ona, natomiast w&#x142;a&#x15B;ciciel aplikacji, musi wyposa&#x17C;y&#x107; si&#x119;&#xA0;w stosowny serwer i baz&#x119; danych, gdzie b&#x119;d&#x105; przechowywane wszelkie tre&#x15B;ci.</li><li><strong>SSG </strong>(<em>Static Site Generator</em>) - ostatnim rozwi&#x105;zaniem, jest generowanie statycznych tre&#x15B;ci. Takie podej&#x15B;cie by&#x142;o standardem wiele lat temu, gdzie serwowane by&#x142;y zwyk&#x142;e, statyczne pliki HTML i CSS. Teraz ponownie wraca do &#x142;ask ze wzgl&#x119;du na swoje liczne zalety, jednak nie musimy ju&#x17C; pisa&#x107; czystych HTML r&#x119;cznie, bo mamy w&#x142;a&#x15B;nie od tego tryb &apos;generatora&apos; w nowoczesnych frameworkach. G&#x142;&#xF3;wn&#x105; zalet&#x105; tego rozwi&#x105;zania, jak mo&#x17C;na si&#x119; domy&#x15B;li&#x107;, jest minimalne obci&#x105;&#x17C;enie zar&#xF3;wno przegl&#x105;darki u&#x17C;ytkownika, jak i serwera w&#x142;a&#x15B;ciciela aplikacji. Wszystko dzia&#x142;a b&#x142;yskawicznie szybko, a to dzi&#x119;ki temu, &#x17C;e u&#x17C;ytkownik wchodz&#x105;c na nasz&#x105; stron&#x119; otrzymuje nic innego, jak zwyk&#x142;y plik HTML. Bardzo cz&#x119;sto te rozwi&#x105;zania, s&#x105; od razu wyposa&#x17C;one w systemy cache&apos;owania czy prerenderingu - o czym opowiemy przy innej okazji.</li></ul><p>Teraz, gdy znamy ju&#x17C; podstawowe sposoby generowania aplikacji (bo nie wymienili&#x15B;my wszystkich!), mo&#x17C;emy przej&#x15B;&#x107; dalej.</p><p>Poczciwy &apos;Create React App&apos;, standardowo buduje aplikacj&#x119; w formie CSR (<em>Client Side Rendering</em>). Jak ju&#x17C; wspomnieli&#x15B;my, oznacza to, &#x17C;e wchodz&#x105;c na nasz&#x105; aplikacje, bardzo du&#x17C;o rzeczy potrafi by&#x107; przetwa&#x17C;ane bezpo&#x15B;rednio w naszej przegl&#x105;darce. CRA nie ma mo&#x17C;liwo&#x15B;ci &#x142;atwego przechodzenia mi&#x119;dzy trybami generowania aplikacji. Tak dzia&#x142;a i tyle.</p><p>Mi&#x119;dzy innymi dlatego, pojawi&#x142;a si&#x119; przestrze&#x144; dla innych framework&#xF3;w takich jak Gatsby, czy tytu&#x142;owy Next.js. </p><p>Aktualnie, Next.js oferuje mo&#x17C;liwo&#x15B;&#x107; budowania stron zar&#xF3;wno w formie CSR jak i SSR i SSG a tak&#x17C;e, od niedawna w formie <strong>ISR</strong> (<em>Incremental Static Regeneration).</em></p><p>W oficjalnej specyfikacji Next.js wyczyta&#x107; mo&#x17C;emy, &#x17C;e rekomendowanym rozwi&#x105;zaniem jest w&#x142;a&#x15B;nie SSG, ze wzgl&#x119;du na to, &#x17C;e generuje nam statyczne pliki kt&#xF3;re b&#x142;yskawicznie potrafi&#x105; zosta&#x107; obs&#x142;u&#x17C;one przez przegl&#x105;dark&#x119;, a dodatkowo mo&#x17C;na je serwowa&#x107; w formie CDNa. </p><p>SSR oczywi&#x15B;cie r&#xF3;wnie&#x17C; jest bardzo dobrym rozwi&#x105;zanem, jednak powinien by&#x107; u&#x17C;ywany g&#x142;&#xF3;wnie tam, gdzie prezentowana tre&#x15B;&#x107; mo&#x17C;e si&#x119; cz&#x119;sto zmienia&#x107; na backendzie. M&#xF3;wimy tutaj np o serwisach nad kt&#xF3;rymi pracuje wi&#x119;cej os&#xF3;b i operuj&#x105; na r&#xF3;&#x17C;nych danych liczbowych, konfiguracjach itp. Natomiast je&#x17C;eli chodzi o zwyk&#x142;e blogi, gdzie raz na jaki&#x15B; czas dodajemy posta, to SSG powinien by&#x107; wystarczaj&#x105;cy. <br>Tym bardziej &#x17C;e.. Mamy jeszcze wspomniany ISR. </p><p>ISR jest nowym &apos;wynalazkiem&apos;, kt&#xF3;ry polega na pewnego rodzaju po&#x142;&#x105;czeniu technologii SSG i SSR. Czyli, generujemy statyczne pliki, natomiast mo&#x17C;emy ustawi&#x107; czas, po kt&#xF3;rym nasza zawarto&#x15B;&#x107;&#xA0;mo&#x17C;e ulec ponownej weryfikacji - czyli m&#xF3;wi&#x105;c wprost, dane zaktualizuj&#x105; si&#x119; na podstawie nowej zawarto&#x15B;ci otrzymanej z serwera. Co najlepsze, nie ma tutaj jakiej&#x15B; skomplikowanej konfiguracji aby wykorzysta&#x107; takie podej&#x15B;cie. Wystarczy, &#x17C;e przy standardowej definicji pobierania danych dla SSG (czyli przez u&#x17C;ycie <code>getStaticProps</code> u&#x17C;yjemy dodatkowej opcji <code>revalidate: &lt;number&gt;</code> - kt&#xF3;ra to definiuje, po jakim czasie nasza strona ma ulec rewalidacji. <code>&lt;numer&gt;</code> jest tutaj liczb&#x105;, wyra&#x17C;an&#x105; w sekundach. </p><p>Co ciekawe, zar&#xF3;wno SSG jak i SSR czy nawet ISR, mo&#x17C;n u&#x17C;ywa&#x107; na przemiennie w ramach jednej aplikacji. Dlatego wybieraj&#x105;c Next.js mo&#x17C;emy bez problemu dobiera&#x107; najlepiej pasuj&#x105;ce rozwi&#x105;zania generowania tre&#x15B;ci dla ka&#x17C;dej strony, a nawet ka&#x17C;dego komponentu. W zale&#x17C;no&#x15B;ci od tego, czy jest to tre&#x15B;&#x107; statyczna, aktualizowana sporadycznie, czy te&#x17C; tre&#x15B;&#x107; kt&#xF3;ra b&#x119;dzie ulega&#x142;a cz&#x119;stym zmian&#x105; w bazie danych. </p><p><u>Na koniec dodatkowa uwaga:</u><br>Pami&#x119;tajcie, &#x17C;e przy u&#x17C;yciu Static Site Generatora, wszelkie requesty s&#x105; pobierane w trakcie budowania aplikacji! Z tego powodu, czas budowania mo&#x17C;e by&#x107; odrobin&#x119; d&#x142;u&#x17C;szy, ale za to wygenerowane pliki HTML maj&#x105; ju&#x17C; tre&#x15B;&#x107; otrzyman&#x105; z serwera. Je&#x17C;eli dojdzie do jakich&#x15B; zmian na serwerze, to nie zostan&#x105; one wy&#x15B;wietlone odwiedzaj&#x105;cym nas u&#x17C;ytkownikom, do momentu, a&#x17C; nie przebudujemy naszej aplikacji.</p>]]></content:encoded></item><item><title><![CDATA[React Hooks Part 1 - useEffect]]></title><description><![CDATA[<p>Min&#x119;&#x142;y ju&#x17C; prawie 3 lata od kiedy React Hooksy po raz pierwszy zago&#x15B;ci&#x142;y w wersji React 16.8. Jedni pokochali je od razu, drudzy potrzebowali troch&#x119; czasu na oswojenie. W tym materiale przedstawi&#x119; wam oraz spr&#xF3;buje wyt&#x142;</p>]]></description><link>https://koduj.eu/jak-poprawnie-uzywac-react-hooksy/</link><guid isPermaLink="false">61f7b0a39cbc504ac0a76248</guid><category><![CDATA[React]]></category><category><![CDATA[javascript]]></category><dc:creator><![CDATA[Mateusz Wasik]]></dc:creator><pubDate>Wed, 02 Aug 2023 09:30:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1643611657752-fb0ce6989d88?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8YWxsfDE0fHx8fHx8Mnx8MTY0MzYyMjY5Mw&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1643611657752-fb0ce6989d88?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8YWxsfDE0fHx8fHx8Mnx8MTY0MzYyMjY5Mw&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="React Hooks Part 1 - useEffect"><p>Min&#x119;&#x142;y ju&#x17C; prawie 3 lata od kiedy React Hooksy po raz pierwszy zago&#x15B;ci&#x142;y w wersji React 16.8. Jedni pokochali je od razu, drudzy potrzebowali troch&#x119; czasu na oswojenie. W tym materiale przedstawi&#x119; wam oraz spr&#xF3;buje wyt&#x142;umaczy&#x107; dzia&#x142;anie najcz&#x119;&#x15B;ciej u&#x17C;ywanych hooks&#xF3;w z jakimi b&#x119;dziecie mieli do czynienia w projektach reactowych. Na pocz&#x105;tek zajmijmy si&#x119; funkcj&#x105;, kt&#xF3;ra niezrozumiana mo&#x17C;e narobi&#x107; troch&#x119; k&#x142;opot&#xF3;w pocz&#x105;tkuj&#x105;cym programistom.</p><p>Pami&#x119;taj prosz&#x119;, &#x17C;e wszystkie przyk&#x142;ady kt&#xF3;re Ci zademonstruje w tym po&#x15B;cie nie s&#x105; przyk&#x142;adami produkcyjnymi. Zosta&#x142;y one maksymalnie uproszczone tak aby&#x15B; skupi&#x142; si&#x119; na tym co wa&#x17C;ne a nie zastanawia&#x142;&#xA0;si&#x119; co robi akurat ten <code>if</code> i dlaczego zosta&#x142; on tak napisany.</p><h2 id="useeffect"><strong>useEffect</strong></h2><p>O <code>UseEffect&apos;ie</code> m&#xF3;wi si&#x119; jak o zamienniku &quot;starego&quot; klasowego <code>componentDidMount</code>. Poniek&#x105;d jest to prawda chocia&#x17C; nie tylko na tym ko&#x144;czy si&#x119; jego rola. </p><pre><code class="language-javascript">useEffect( () =&gt; {

// do something

})</code></pre><p>Hooka efekt&#xF3;w u&#x17C;ywa si&#x119; g&#x142;&#xF3;wnie do wykonania jakiej&#x15B; czynno&#x15B;ci, jakiego&#x15B; side-effectu, po tym jak komponent si&#x119; ju&#x17C; zbuduje i &quot;narysuje&quot;. Po wyrenderowaniu DOM&apos;a zostanie wywo&#x142;any nasz <code>useEffect</code> a &#x15B;ci&#x15B;le rzecz bior&#x105;c funkcja kt&#xF3;r&#x105; do niego przekazali&#x15B;my. </p><p><strong>Dependency array</strong></p><p>A co kiedy nie chcemy aby za ka&#x17C;dym prze&#x142;adowaniem naszego komponentu dany efekt si&#x119; wywo&#x142;ywa&#x142;? W tym przypadku dostali&#x15B;my do dyspozycji tablice zale&#x17C;no&#x15B;ci - <code>dependency array</code>. </p><p>&#x17B;eby &#x142;atwiej zwizualizowa&#x107; sobie jak tak naprawd&#x119; zbudowany jest <code>useEffect</code> upro&#x15B;&#x107;my go sobie maksymalnie.</p><pre><code class="language-javascript">useEffect(funkcja, tablica zale&#x17C;no&#x15B;ci)</code></pre><p>UseEffect jest przede wszystkim funkcj&#x105;, kt&#xF3;rej pierwszym argumentem jest kolejna funkcja, kt&#xF3;ra wywo&#x142;a nam jaki&#x15B; efekt. Drugim argumentem jest tablica zale&#x17C;no&#x15B;ci, od kt&#xF3;rych b&#x119;dzie <em>zale&#x17C;a&#x142;o</em> to czy nasza funkcja si&#x119; wywo&#x142;a czy nie.</p><p>W przypadku pierwszego argumentu tutaj nie mamy co dyskutowa&#x107;, nale&#x17C;y zawsze poda&#x107;, inaczej nie mia&#x142;oby to &#x17C;adnego sensu prawda? Natomiast w przypadku tablicy zale&#x17C;no&#x15B;ci, no tutaj sprawa ma si&#x119; troch&#x119; inaczej. Szybkie spojrzenie na implementacje w pliku &#x17A;r&#xF3;d&#x142;owym daje nam cenn&#x105; informacj&#x119; :</p><pre><code class="language-javascript">function useEffect(effect: EffectCallback, deps?: DependencyList): void;</code></pre><p>Drugi argument przekazywany do hooka efektu jest opcjonalny, co oznacza &#x17C;e mo&#x17C;emy go przes&#x142;a&#x107; albo nie. Ale co to TAK NAPRAWD&#x118; oznacza? Co je&#x17C;eli go nie podam?</p><p><strong>Deklarowa&#x107; dependency array czy nie?</strong></p><p>Przede wszystkim nie powiniene&#x15B; nie podawa&#x107; tablicy zale&#x17C;no&#x15B;ci. Takie podej&#x15B;cie jest przez wielu uwa&#x17C;ane za b&#x142;&#x119;dne i doprowadzaj&#x105;ce do zachowa&#x144;, kt&#xF3;re nierzadko ci&#x119;&#x17C;ko nam przewidzie&#x107;. Dlaczego? Ot&#xF3;&#x17C; niepodanie tej tablicy b&#x119;dzie skutkowa&#x142;o tym, &#x17C;e za ka&#x17C;dym prze&#x142;adowaniem naszego komponentu wywo&#x142;a si&#x119; nasz efekt. </p><p><em>No ale co z tego</em>? <em>Mam ma&#x142;&#x105; funkcyjke, kt&#xF3;ra sobie co&#x15B; tam sprawdza i tyle, niech wykonuje si&#x119; za ka&#x17C;dym razem, nie bardzo mnie to boli.</em> Warto zastanowi&#x107; si&#x119; czy tak naprawd&#x119; jest. </p><p>Wyobra&#x17A; sobie, &#x17C;e mamy komponent <code>Radio</code>, kt&#xF3;ry ma wszystkie cechy radia. Mo&#x17C;emy s&#x142;ucha&#x107; muzyki, podg&#x142;a&#x15B;nia&#x107; i &#x15B;cisza&#x107; d&#x17A;wi&#x119;k, zmienia&#x107; stacje, ustawia&#x107; basy i robi&#x107; wszystko to co mo&#x17C;esz robi&#x107; w swoim w&#x142;asnym radiu. W poni&#x17C;szym przyk&#x142;adzie chcemy zwi&#x119;kszy&#x107; g&#x142;o&#x15B;no&#x15B;&#x107; w momencie kiedy akurat leci nasza ulubiona piosenka - <code>Parostatek</code> na 80%. W innym wypadku niech g&#x142;o&#x15B;no&#x15B;&#x107; b&#x119;dzie ustawiona na 40%. </p><pre><code class="language-javascript">useEffect( () =&gt; {

 if(song === &apos;Parostatek&apos;) {
   setVolume(80) // 80 percent
  } else {
   setVolume(40) // 40 percent
  }
  
}, [song])
</code></pre><p>Powy&#x17C;sza funkcja nas&#x142;uchuje, przy ka&#x17C;dym przerenderowaniu komponentu, czy warto&#x15B;&#x107; <code>song</code> si&#x119; zmieni&#x142;a por&#xF3;wnuj&#x105;c j&#x105; do poprzednio zapami&#x119;tanej warto&#x15B;ci. Je&#x17C;eli warto&#x15B;&#x107; po przerenderowaniu jest inna ni&#x17C; ta kt&#xF3;r&#x105; pami&#x119;ta, wywo&#x142;a nam si&#x119; nasz efekt.</p><p>Patrz&#x105;c na powy&#x17C;szy przyk&#x142;ad mo&#x17C;esz zapyta&#x107; dlaczego nie pozwolimy aby ten efekt wywo&#x142;ywa&#x142; si&#x119; za ka&#x17C;dym razem? Przecie&#x17C; piosenki w radio zmieniaj&#x105; si&#x119; raptem co pare minut, a ta funkcja nie robi nic wielkiego wi&#x119;c dlaczego nie wywali&#x107; tablicy zale&#x17C;no&#x15B;ci i pozwoli&#x107; jej wywo&#x142;ywa&#x107; si&#x119; za ka&#x17C;dym razem przy prze&#x142;adowaniu komponentu?</p><p>Dobrze, a co je&#x17C;eli &quot;wywo&#x142;amy&quot; inn&#x105; funkcje zwi&#x105;zan&#x105; z u&#x17C;ywaniem radia? Czy chcemy aby nasza funkcja wywo&#x142;ywa&#x142;a si&#x119; gdy &#x15B;ciszymy radio? Albo gdy zwi&#x119;kszymy basy? Nie. Dlatego jasno dali&#x15B;my Reactowi do zrozumienia, &#x17C;e chcemy aby nasza funkcja zosta&#x142;a odpalona tylko w momencie kiedy zmieni si&#x119; warto&#x15B;&#x107; przechowywana w zmiennej <code>song</code>.</p><p><strong>&quot;Nowy&quot; componentDidMount</strong></p><p>Jak wspomina&#x142;em wy&#x17C;ej, useEffect jest cz&#x119;sto nazywany funkcyjnym zamiennikiem jednego ze stanu cyklu &#x17C;ycia komponentu klasowego jakim jest <code>componentDidMount</code>. Okej, potrzebujemy wywo&#x142;a&#x107; co&#x15B; raz i tylko raz w momencie pierwszej inicjalizacji komponentu. Jak to napisa&#x107; wykorzystuj&#x105;c <code>useEffect</code> ?</p><pre><code class="language-javascript">useEffect( () =&gt; {

// do something only once when component is
// created for the first time

}, [] )</code></pre><p>Odpowied&#x17A; brzmi: poprzez podanie pustej tablicy zale&#x17C;no&#x15B;ci. Powy&#x17C;sza funkcja wywo&#x142;a nam si&#x119; tylko i wy&#x142;&#x105;cznie w momencie pierwszej inicjalizacji naszego komponentu i b&#x119;dzie ignorowa&#x107; wszelkie dalsze prze&#x142;adowania.</p><p><strong>Posprz&#x105;taj po sobie</strong></p><p>Podczas cyklu &#x17C;ycia naszej funkcji wielokrotnie ja prze&#x142;adowujemy, zmieniamy warto&#x15B;ci, wy&#x15B;wietlamy r&#xF3;&#x17C;ne dane. W skr&#xF3;cie, robimy du&#x17C;o &quot;ba&#x142;aganu&quot;. Jedn&#x105; z rzeczy kt&#xF3;ra potrafi narobi&#x107; ba&#x142;aganu jest subskrypcja. Po tym gdy nasz komponent &quot;wyrazi ch&#x119;&#x107;&quot; na otrzymywanie w ramach subskrybcji nowych informacji, to w momencie kiedy nie b&#x119;dzie nam ju&#x17C; potrzebny i b&#x119;dziemy chcieli go usun&#x105;&#x107;, nale&#x17C;a&#x142;o by po sobie posprz&#x105;ta&#x107; i nacisn&#x105;&#x107; guzik &quot;unsubscribe&quot;. W innym wypadku mo&#x17C;e doj&#x15B;&#x107; do bardzo niepo&#x17C;&#x105;danego wycieku pami&#x119;ci.</p><p>Szybkie wprowadzenia co to jest subskrypcja w programowaniu. Upraszczaj&#x105;c, poj&#x119;cie subskrypcji oznacza ch&#x119;&#x107; na otrzymywanie powiadomie&#x144; (nowych warto&#x15B;ci) gdy co&#x15B; co nas interesuje (czyli to do czego si&#x119; subskrybujemy) si&#x119; zmieni. Przyk&#x142;ad z &#x17C;ycia wzi&#x119;ty - macie swojego ulubionego youtubera kt&#xF3;ry wypuszcza filmiki, subskrybujecie go aby dostawa&#x107; powiadomienia za ka&#x17C;dym razem gdy na jego kanale pojawi si&#x119; nowy filmik. Tak to mniej wi&#x119;cej dzia&#x142;a i tu.</p><pre><code class="language-js">useEffect( () =&gt; {

  ChartApi.subscribe()

},[])</code></pre><p>Na przyk&#x142;adzie widzimy jak podczas pierwszego zbudowania si&#x119; naszego komponentu subskrybujemy si&#x119; do <code>ChartAPI</code>, kt&#xF3;ra przypu&#x15B;&#x107;my podsy&#x142;a nam co chwil&#x119; nowe warto&#x15B;ci do wy&#x15B;wietlenia na naszym wykresie. W ten spos&#xF3;b nasz wykres &quot;&#x17C;yje&quot;, dostaje nowe &#x15B;wie&#x17C;e dane kt&#xF3;re u&#x17C;ytkownik widzi na bie&#x17C;&#x105;co. Fajna sprawa, ale wymaga od nas przygotowania si&#x119; na sytuacj&#x119; w kt&#xF3;rej nasz komponent, kt&#xF3;ry si&#x119; subskrybuje do <code>ChartAPI</code>, przestanie nam by&#x107; potrzebny. Czyli co? Czyli trzeba po sobie posprz&#x105;ta&#x107;.</p><pre><code class="language-javascript">useEffect( () =&gt; {

  ChartApi.subscribe()
  
    // cleaning function
  return () =&gt; {
	ChartAPI.unsubscribe()
  }

},[])</code></pre><p>Aby zrobi&#x107; to prawid&#x142;owo nale&#x17C;y wywo&#x142;a&#x107; funkcj&#x119; <code>return</code> podaj&#x105;c jej co ma sta&#x107; si&#x119; w momencie gdy nasz komponent zostanie &apos;odmontowany&apos; (unmounted). W ten spos&#xF3;b zabezpieczamy si&#x119; przed nierzadko tragicznym w skutkach wycieku pami&#x119;ci, poniewa&#x17C; mimo &#x17C;e komponent ju&#x17C; nie istnieje w dalszym ci&#x105;gu nasz subskrybent pr&#xF3;buje wysy&#x142;a&#x107; mu nowe informacje.</p>]]></content:encoded></item></channel></rss>