<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ilyoskhuja</title>
    <description>The latest articles on DEV Community by Ilyoskhuja (@ilyoskhuja).</description>
    <link>https://dev.to/ilyoskhuja</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F817113%2F54a36f13-81a5-4f91-bf2a-f1ce593ce90e.png</url>
      <title>DEV Community: Ilyoskhuja</title>
      <link>https://dev.to/ilyoskhuja</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ilyoskhuja"/>
    <language>en</language>
    <item>
      <title>Optimizing an Angular Real-Estate App: SSR, a Map with Hundreds of Markers, and a Lighthouse Score That Went From 54 to 96</title>
      <dc:creator>Ilyoskhuja</dc:creator>
      <pubDate>Sun, 05 Jul 2026 18:05:03 +0000</pubDate>
      <link>https://dev.to/ilyoskhuja/optimizing-an-angular-real-estate-app-ssr-a-map-with-hundreds-of-markers-and-a-lighthouse-score-3276</link>
      <guid>https://dev.to/ilyoskhuja/optimizing-an-angular-real-estate-app-ssr-a-map-with-hundreds-of-markers-and-a-lighthouse-score-3276</guid>
      <description>&lt;p&gt;I build &lt;a href="https://locus.uz" rel="noopener noreferrer"&gt;locus.uz&lt;/a&gt;, a real-estate search site for Uzbekistan — think Zillow for Tashkent. The &lt;a href="https://locus.uz/buy" rel="noopener noreferrer"&gt;https://locus.uz/buy&lt;/a&gt; page is the hard one: a Leaflet map with hundreds of listing pins on the left, an infinite-feeling list of photo cards on the right, three languages (Uzbek, Russian, English), all server-side rendered.&lt;/p&gt;

&lt;p&gt;The stack, so you know exactly what this applies to: &lt;strong&gt;Angular 21&lt;/strong&gt; (standalone components, signals, zoneless change detection — the default for new apps since v21), &lt;strong&gt;@angular/ssr&lt;/strong&gt; on an &lt;strong&gt;Express 5&lt;/strong&gt; server, &lt;strong&gt;Leaflet 1.9&lt;/strong&gt; for the map, deployed on a VPS behind nginx and Cloudflare. No NgRx, no component library. Everything here was written against Angular 21.x, and I've checked that none of the framework behavior described has changed in v22.0 (released June 2026).&lt;/p&gt;

&lt;p&gt;One weekend I ran Lighthouse against &lt;code&gt;/buy&lt;/code&gt; and got Performance 88, Accessibility 83, Best Practices &lt;strong&gt;54&lt;/strong&gt;. A few days of work later:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;88&lt;/td&gt;
&lt;td&gt;93 (LCP 1.0s, CLS 0, TBT 90ms)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Accessibility&lt;/td&gt;
&lt;td&gt;83&lt;/td&gt;
&lt;td&gt;96&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best Practices&lt;/td&gt;
&lt;td&gt;54&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;96&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SEO&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This article covers the Angular techniques that got us there — and three production incidents along the way, because those taught us more than the wins.&lt;/p&gt;

&lt;h2&gt;
  
  
  The foundation: SSR + hydration, and the flag everyone misses
&lt;/h2&gt;

&lt;p&gt;The app uses Angular's application builder with SSR and full hydration. Event replay (&lt;code&gt;withEventReplay()&lt;/code&gt;) has been the CLI default for new SSR apps since v19 — the interesting line is the second one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;provideClientHydration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;withEventReplay&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="nf"&gt;withHttpTransferCacheOptions&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;includePostRequests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Angular's HTTP transfer cache carries responses fetched during SSR to the browser so the client doesn't refetch them during hydration. But it only caches &lt;strong&gt;GET and HEAD&lt;/strong&gt; by default (&lt;code&gt;ALLOWED_METHODS = ['GET', 'HEAD']&lt;/code&gt; in the source, unchanged through v22). Our listings come from a &lt;code&gt;POST /map-search&lt;/code&gt; — the request body carries viewport bounds and filters, too much for a query string. So the server rendered twenty listing cards, the client re-issued the POST during hydration, and — because the response is async — Angular's first client render hit the &lt;em&gt;empty&lt;/em&gt; &lt;code&gt;@if&lt;/code&gt; branch while the server HTML contained the populated list. That structural mismatch is what throws &lt;code&gt;NG0500&lt;/code&gt; (the docs classify it under "differing server/client render output", not as an HTTP problem — if our loading state had the same DOM shape, we'd have gotten a silent duplicate request and a flicker instead of an error).&lt;/p&gt;

&lt;p&gt;One flag fixed the mismatch, the duplicate fetch, and the console error at once. Two honest footnotes: the global flag is &lt;em&gt;one&lt;/em&gt; way to do it — since v17 you can opt in a single request with &lt;code&gt;http.post(url, body, { transferCache: true })&lt;/code&gt;, which is safer when only one endpoint is an idempotent read. And never enable this for POSTs that mutate state; ours is a search query that just happens to travel as POST.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why not incremental hydration?&lt;/strong&gt; Angular 20 stabilized it (&lt;code&gt;withIncrementalHydration()&lt;/code&gt; plus &lt;code&gt;@defer (hydrate on viewport)&lt;/code&gt; and friends), and from v22 it's the default. We stayed on full hydration because our main content is a client-only map that never gets server-rendered anyway — there's little dehydrated DOM to skip. If your page has heavy server-rendered sections users rarely touch, hydrate triggers are the modern way to cut initial JS execution, and you should reach for them before anything in this article.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why not &lt;code&gt;@defer&lt;/code&gt; for the map?&lt;/strong&gt; Deferrable views (introduced in v17, stable since v18) with &lt;code&gt;@defer (on viewport)&lt;/code&gt; are the idiomatic way to lazy-load heavy components, and on the server they render only their placeholder — so they'd also keep Leaflet out of SSR. We used route-level lazy loading plus a guarded dynamic &lt;code&gt;import('leaflet')&lt;/code&gt; instead, for one reason: the map is the page's &lt;em&gt;primary above-the-fold content&lt;/em&gt;. Angular's own defer guide warns against deferring initial-viewport content (layout shift), and a viewport trigger would fire immediately anyway. For a below-the-fold widget, &lt;code&gt;@defer&lt;/code&gt; would have been the right call.&lt;/p&gt;

&lt;p&gt;One more foundation piece: &lt;code&gt;afterNextRender&lt;/code&gt; for anything that must not race hydration. We restore the user's saved language from &lt;code&gt;localStorage&lt;/code&gt; — doing that in a constructor changes the first client render, which then no longer matches the server HTML (hello again, NG0500). Registering it in &lt;code&gt;afterNextRender&lt;/code&gt; means the first render matches the server byte-for-byte and the preference applies immediately after.&lt;/p&gt;

&lt;h2&gt;
  
  
  The map: hundreds of dots without melting the main thread
&lt;/h2&gt;

&lt;p&gt;The map renders ~280 pins at city zoom plus colored district polygons for all of Tashkent, and the page stays at 90ms Total Blocking Time.&lt;/p&gt;

&lt;p&gt;A word on the library choice, since someone will ask: at this scale — hundreds of DOM features on raster tiles — Leaflet is a lighter, simpler tool than MapLibre GL, which earns its complexity with vector tiles and thousands-plus of GPU-rendered features. Leaflet 1.9.4 is still the current stable in mid-2026 (2.0 has been in alpha since August 2025; 1.x is in maintenance mode), and we'll migrate when 2.0 lands.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The viewport is the query.&lt;/strong&gt; We never fetch "all listings". The map's &lt;code&gt;moveend&lt;/code&gt; event sends the current bounds to the backend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;lMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;moveend&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBounds&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadListings&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;northEast&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getNorthEast&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="na"&gt;southWest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSouthWest&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The database does the spatial filtering; the browser only ever holds what's visible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Signals drive the markers — which matters more in a zoneless app.&lt;/strong&gt; The API service exposes listings as a signal, and the map redraws in an &lt;code&gt;effect()&lt;/code&gt; (third-party rendering is explicitly one of the documented use cases for effects):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isPlatformBrowser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;platformId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mapReady&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;markers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;markers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lang&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;i18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;currentLang&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// redraw popups on language switch&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawMarkers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;markers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since the app is zoneless, the classic "wrap Leaflet in &lt;code&gt;NgZone.runOutsideAngular&lt;/code&gt;" advice is moot — there's no zone to escape, and Leaflet's internal &lt;code&gt;mousemove&lt;/code&gt;/&lt;code&gt;drag&lt;/code&gt; storms can't trigger change detection in the first place. The risk actually inverts: a Leaflet event handler that &lt;em&gt;should&lt;/em&gt; update the UI does nothing unless it writes to a signal. Ours all do, which is why the pattern above isn't just tidy — it's the mechanism.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Cheap markers, canvas polygons — and know which is which.&lt;/strong&gt; Each pin is a &lt;code&gt;divIcon&lt;/code&gt; (one styled &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;, no image request). The district boundaries are detailed GeoJSON polygons, and rendering them as SVG (Leaflet's default) means thousands of path nodes in the DOM — so that layer gets &lt;code&gt;renderer: L.canvas()&lt;/code&gt;, painting every district into a single canvas element. We also simplify the geometry first: interior rings and all but the largest part of each MultiPolygon get stripped, because a boundary overlay doesn't need survey-grade precision.&lt;/p&gt;

&lt;p&gt;One precision note, because map people will check: &lt;code&gt;L.canvas()&lt;/code&gt;/&lt;code&gt;preferCanvas&lt;/code&gt; only affects &lt;em&gt;vector path&lt;/em&gt; layers like our polygons. &lt;code&gt;divIcon&lt;/code&gt; markers are always DOM elements — if you need to scale markers into the thousands, the answer is clustering, &lt;code&gt;circleMarker&lt;/code&gt;s, a canvas-marker plugin, or WebGL, not the canvas renderer. At ~280 pins, plain DOM markers are comfortably fine; the community rule of thumb is that you reach for &lt;code&gt;Leaflet.markercluster&lt;/code&gt; (proven to tens of thousands of points) somewhere past 500–1,000.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Kill the feedback loops before they kill you.&lt;/strong&gt; The map reloads listings on &lt;code&gt;moveend&lt;/code&gt;. Search-by-district calls &lt;code&gt;fitBounds&lt;/code&gt;. &lt;code&gt;fitBounds&lt;/code&gt; fires &lt;code&gt;moveend&lt;/code&gt;. Which reloads listings, which can move the map… We guard every programmatic move:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;programmaticMove&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;leafletElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fitBounds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bounds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;maxZoom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// in the moveend handler:&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;programmaticMove&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;programmaticMove&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same defensive posture around sizing: Leaflet 1.9's &lt;code&gt;trackResize&lt;/code&gt; only watches &lt;em&gt;window&lt;/em&gt; resize, so container-driven changes (sidebar toggles, flex reflows) need a manual &lt;code&gt;ResizeObserver&lt;/code&gt; calling &lt;code&gt;invalidateSize()&lt;/code&gt; — guarded to skip when the container is hidden, because Leaflet does not enjoy being resized while &lt;code&gt;display: none&lt;/code&gt;. (The 2.0 alpha observes the container natively, so this workaround is 1.x-specific.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Markers are UI, so they follow UI rules.&lt;/strong&gt; Leaflet has made every keyboard-enabled marker a focusable &lt;code&gt;role="button"&lt;/code&gt; since 1.8 — and by default a &lt;em&gt;nameless&lt;/em&gt; one, which is a Lighthouse accessibility failure multiplied by 280. The built-in fix is the &lt;code&gt;title&lt;/code&gt; option (Leaflet sets it on the icon element; the &lt;code&gt;alt&lt;/code&gt; option only applies to image icons, so it's silently ignored for &lt;code&gt;divIcon&lt;/code&gt;s):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;formatPriceCurrency&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;district&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; — &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;marker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;leaflet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;marker&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lng&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now a screen reader announces "$52,500 — Sergeli" instead of "button". (A &lt;code&gt;title&lt;/code&gt; attribute is a fairly weak name source; if you build custom &lt;code&gt;divIcon&lt;/code&gt; HTML anyway, an &lt;code&gt;aria-label&lt;/code&gt; inside it is more robust.)&lt;/p&gt;

&lt;h2&gt;
  
  
  The listing images: fast, stable, and no broken pictures
&lt;/h2&gt;

&lt;p&gt;The right half of the page is a grid of photo cards, each with a swipeable gallery. Every card thumb looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"thumb"&lt;/span&gt;
     &lt;span class="na"&gt;[src]=&lt;/span&gt;&lt;span class="s"&gt;"imageError ? '/no_image.jpg' : photos()[current]"&lt;/span&gt;
     &lt;span class="na"&gt;(error)=&lt;/span&gt;&lt;span class="s"&gt;"handleImageError($event)"&lt;/span&gt;
     &lt;span class="na"&gt;[attr.loading]=&lt;/span&gt;&lt;span class="s"&gt;"priority() ? 'eager' : 'lazy'"&lt;/span&gt;
     &lt;span class="na"&gt;[attr.fetchpriority]=&lt;/span&gt;&lt;span class="s"&gt;"priority() ? 'high' : null"&lt;/span&gt;
     &lt;span class="na"&gt;[alt]=&lt;/span&gt;&lt;span class="s"&gt;"listing().location || listing().district || (…fallback | translate)"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reasoning, attribute by attribute:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;loading="lazy"&lt;/code&gt; — for everything &lt;em&gt;except&lt;/em&gt; the LCP image.&lt;/strong&gt; Twenty cards render per page; only the ones near the viewport fetch their images, which (with the other fixes) took the page payload from 11MB to 3.4MB. But lazy-loading the image that &lt;em&gt;is&lt;/em&gt; your Largest Contentful Paint is a well-documented anti-pattern — Angular has flagged it in dev mode since v17 (the NG0913 check inspects plain &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tags too). So the first cards get a &lt;code&gt;priority&lt;/code&gt; input: eager loading plus &lt;code&gt;fetchpriority="high"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The container owns the layout, not the image.&lt;/strong&gt; The wrapper has &lt;code&gt;aspect-ratio: 4 / 3&lt;/code&gt; with &lt;code&gt;object-fit: cover&lt;/code&gt;, so cards occupy their final size before a single image byte arrives. That's the entire reason CLS is a flat &lt;strong&gt;0&lt;/strong&gt; — explicit &lt;code&gt;width&lt;/code&gt;/&lt;code&gt;height&lt;/code&gt; attributes achieve the same thing, and map directly onto NgOptimizedImage's requirements if you migrate later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; per card, not one per photo.&lt;/strong&gt; A listing can have fifteen photos, but the carousel is a single image element whose &lt;code&gt;src&lt;/code&gt; swaps on navigation. Photos you never swipe to are never downloaded. The dots under the photo are real &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;s, visually 8px but with a 24×24 hit area via &lt;code&gt;background-clip: content-box&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;decoding="async"&lt;/code&gt; on the lazy images&lt;/strong&gt; — a cheap, no-downside hint, though honestly a marginal one in 2026 (browsers largely decode off the main thread anyway), and deliberately &lt;em&gt;not&lt;/em&gt; set on the priority image.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Broken images have two safety nets.&lt;/strong&gt; Client-side, &lt;code&gt;(error)&lt;/code&gt; swaps in a placeholder. Server-side, nginx does &lt;code&gt;try_files $uri /no_image.jpg;&lt;/code&gt; so a missing photo returns a 200 placeholder instead of a 404 — Lighthouse counts every failed request as a console error, and twenty cards can generate a lot of 404s.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why not NgOptimizedImage?&lt;/strong&gt; Fair question — &lt;code&gt;ngSrc&lt;/code&gt; has been Angular's documented image best practice since v15, and it's the first thing any reviewer will ask. The directive's headline wins are automatic &lt;code&gt;srcset&lt;/code&gt; generation and placeholders, and both require an image loader backed by a resizing CDN (Cloudinary, ImageKit, Imgix…). Our photos are self-hosted in a single size — there's no &lt;code&gt;srcset&lt;/code&gt; to generate, and automatic placeholders actually throw without a loader. What the directive would still give us loaderless — enforced dimensions, lazy-by-default, and the &lt;code&gt;priority&lt;/code&gt; handling with SSR preload hints — we've replicated manually above. If we adopt an image CDN, switching to &lt;code&gt;ngSrc&lt;/code&gt; with &lt;code&gt;priority&lt;/code&gt; on the first cards is the drop-in upgrade, and it's the honest next step on this list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices 54 → 96: security headers on the Express server
&lt;/h2&gt;

&lt;p&gt;The score of 54 had a blunt cause: the site sent no security headers at all. The fix lives in the Express SSR server — a global middleware for HSTS, COOP, &lt;code&gt;X-Frame-Options&lt;/code&gt;, &lt;code&gt;nosniff&lt;/code&gt; and Referrer-Policy, plus a per-request &lt;strong&gt;nonce-based CSP&lt;/strong&gt; on rendered HTML. The server mints a nonce, stamps it onto every &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag (and every &lt;code&gt;&amp;lt;link rel="modulepreload"&amp;gt;&lt;/code&gt; — miss those and &lt;code&gt;'strict-dynamic'&lt;/code&gt; blocks your chunk preloads), and sends:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;script&lt;/span&gt;-&lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="s1"&gt;'nonce-...'&lt;/span&gt; &lt;span class="s1"&gt;'strict-dynamic'&lt;/span&gt; &lt;span class="s1"&gt;'self'&lt;/span&gt; &lt;span class="s1"&gt;'unsafe-inline'&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;: &lt;span class="n"&gt;http&lt;/span&gt;:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The trailing values are backward-compat fallbacks that nonce-aware browsers ignore. Angular's hydration and event-replay inline scripts all accept the nonce.&lt;/p&gt;

&lt;p&gt;Except one thing did not, and it took the whole site's CSS down with it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Strict CSP vs. Angular's critical CSS: know your options
&lt;/h3&gt;

&lt;p&gt;Minutes after the CSP went live, our map disappeared, replaced by &lt;code&gt;Canvas exceeds max size&lt;/code&gt; errors. Measuring the map container in a headless browser: &lt;strong&gt;4,194,366 pixels tall&lt;/strong&gt; — 2²², a doubling feedback loop that had run thirteen times, with 6,393 map tiles loaded into it.&lt;/p&gt;

&lt;p&gt;A commit-by-commit bisect with a headless browser pointed at… my own CSP commit. The mechanism: Angular's &lt;code&gt;inlineCritical&lt;/code&gt; optimization (on by default; since v19 powered by Beasties, the maintained Critters fork) inlines critical CSS and emits the full stylesheet as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"styles.css"&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"print"&lt;/span&gt; &lt;span class="na"&gt;onload=&lt;/span&gt;&lt;span class="s"&gt;"this.media='all'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A non-blocking load that flips to &lt;code&gt;media="all"&lt;/code&gt; via an &lt;strong&gt;inline event handler&lt;/strong&gt; — which a strict CSP blocks. The stylesheet stayed stuck as a print stylesheet, so the page — &lt;em&gt;including all of Leaflet's CSS&lt;/em&gt; — rendered unstyled. Unpositioned map tiles became ordinary in-flow images stacking vertically, the container grew, more tiles loaded, repeat. (Not literally silent, in fairness: the CSP violations were in the console. But nothing tells you "your stylesheet is now print-only", and the visible symptom — a canvas error from the map — pointed everywhere except CSS delivery.)&lt;/p&gt;

&lt;p&gt;Here's the part I only fully understood afterwards, and it changes the recommendation. &lt;strong&gt;This failure only happens when Angular doesn't know your nonce.&lt;/strong&gt; Since v16, if the served HTML carries an &lt;code&gt;ngCspNonce&lt;/code&gt; attribute on the app root, Angular's build and &lt;code&gt;@angular/ssr&lt;/code&gt; handle everything: the &lt;code&gt;onload&lt;/code&gt; handler is replaced with a nonce'd loader script, inline critical styles get the nonce, and so do the hydration/event-replay scripts. That's the framework-blessed path for strict CSP with SSR, and it keeps the critical-CSS FCP win. (Two footnotes: the &lt;code&gt;CSP_NONCE&lt;/code&gt; injection token &lt;em&gt;alone&lt;/em&gt; is not enough for SSR — build-emitted scripts won't get the nonce; and the CLI's newer hash-based &lt;code&gt;autoCsp&lt;/code&gt; option, experimental since v19, throws "Cannot set both SSR and auto-CSP" — it's a no-go for SSR apps.)&lt;/p&gt;

&lt;p&gt;We chose the other lever:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"optimization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"styles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"minify"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"inlineCritical"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One line, no per-request HTML templating, at the cost of the stylesheet becoming a normal render-blocking link — a few milliseconds of first paint on our numbers. For a small self-hosted stylesheet that's a fine trade; for a bigger app already generating per-request nonces, wiring &lt;code&gt;ngCspNonce&lt;/code&gt; is the better answer. What you cannot do is ship a strict CSP without choosing one of them — nothing in the build warns you about the combination, and the failure mode looks like anything but CSS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two more bugs the audit smoked out
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Production was serving a month-old build.&lt;/strong&gt; After the first round of fixes, the Lighthouse score didn't move — because nginx was serving a stale prerendered &lt;code&gt;index.html&lt;/code&gt; from a June build. Our GitHub Actions deploy used &lt;code&gt;scp&lt;/code&gt;, which copies but never deletes, and old files shadowed five consecutive deploys. The tell was in the response headers all along: &lt;code&gt;last-modified: Fri, 26 Jun&lt;/code&gt;. HTML responses from an SSR server don't have a last-modified date. Now the pipeline wipes the target directories before copying, and nginx proxies everything except hashed assets to the Node server. If your deploy is &lt;code&gt;scp&lt;/code&gt;/&lt;code&gt;rsync&lt;/code&gt; without &lt;code&gt;--delete&lt;/code&gt;, go check your server right now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The language switcher un-switched itself in 6ms.&lt;/strong&gt; Our i18n uses URL prefixes (&lt;code&gt;/ru/buy&lt;/code&gt;) via a custom &lt;code&gt;UrlSerializer&lt;/code&gt; whose &lt;code&gt;parse()&lt;/code&gt; records the language as a side effect. (Angular's official i18n guidance is a different architecture entirely — one build per locale under a URL &lt;code&gt;subPath&lt;/code&gt; — so a single-build runtime-locale setup like ours is community-pattern territory.) It turns out the Router re-parses the &lt;em&gt;raw browser URL&lt;/em&gt; with your serializer during internal same-URL checks — &lt;code&gt;isUpdatedBrowserUrl()&lt;/code&gt; in &lt;code&gt;navigation_transition.ts&lt;/code&gt;, verified unchanged through 21.x. So if the address bar still said &lt;code&gt;/ru/buy&lt;/code&gt; when you clicked "O'zbek", an internal re-parse stomped the language state back to Russian before the UI could blink. I found it by monkey-patching &lt;code&gt;localStorage.setItem&lt;/code&gt; with stack traces. The fix: &lt;code&gt;location.replaceState(newPrefixedUrl)&lt;/code&gt; &lt;em&gt;before&lt;/em&gt; &lt;code&gt;router.navigateByUrl&lt;/code&gt;, so any re-parse sees the new prefix. The lesson: the Router makes no promises about when or how often &lt;code&gt;parse()&lt;/code&gt; runs — treat it as something that must be pure.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually mattered
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;includePostRequests: true&lt;/code&gt;&lt;/strong&gt; (or per-request &lt;code&gt;{ transferCache: true }&lt;/code&gt;) if your SSR app reads data via POST — fixes hydration mismatches and double-fetching at once. Idempotent reads only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Viewport-bounds queries + signal-driven &lt;code&gt;effect()&lt;/code&gt; redraws + &lt;code&gt;divIcon&lt;/code&gt;/canvas rendering&lt;/strong&gt; carry a Leaflet map to hundreds of markers without jank. In a zoneless app, map-event-writes-to-signal isn't a style choice — it's the only way the UI updates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;loading="lazy"&lt;/code&gt; everywhere except the LCP image&lt;/strong&gt;, which gets &lt;code&gt;fetchpriority="high"&lt;/code&gt; — plus &lt;code&gt;aspect-ratio&lt;/code&gt; containers and single-img carousels. CLS 0 is a design decision, not luck.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strict CSP + SSR requires choosing&lt;/strong&gt;: &lt;code&gt;ngCspNonce&lt;/code&gt; (keeps critical CSS, framework-supported since v16) or &lt;code&gt;inlineCritical: false&lt;/code&gt; (one line, render-blocking styles). Choosing neither breaks your CSS in a way that looks like anything but CSS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit in incognito&lt;/strong&gt; — DevTools Lighthouse runs your extensions inside the page, and their deprecation warnings count against you. My first "after" run said 73; a clean profile said 96.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trust nothing about production until you've curled it.&lt;/strong&gt; The most impactful fix of the week wasn't Angular at all — it was discovering which build users were actually receiving.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What's still red, honestly: the touch-target audit flags overlapping map pins — that's WCAG 2.2's target-size criterion (24×24 CSS px of &lt;em&gt;unobscured&lt;/em&gt; area), and 280 pins at city zoom obscure each other by definition. The standard fix is &lt;code&gt;Leaflet.markercluster&lt;/code&gt; with spiderfying for coincident pins; at our scale it's an accessibility-and-UX decision rather than a performance one (and note the default cluster icons need accessible names of their own). That's the next project.&lt;/p&gt;

&lt;p&gt;The scores are the headline, but the real gains were quieter: pages hydrate cleanly instead of re-rendering, the map redraws only what changed, users stopped downloading photos they'd never see, and — after an embarrassing discovery — they're finally getting the build we shipped.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Power Up Your Angular App with Progressive Web Apps (PWAs)</title>
      <dc:creator>Ilyoskhuja</dc:creator>
      <pubDate>Mon, 30 Jan 2023 10:07:07 +0000</pubDate>
      <link>https://dev.to/ilyoskhuja/power-up-your-angular-app-with-progressive-web-apps-pwas-1p88</link>
      <guid>https://dev.to/ilyoskhuja/power-up-your-angular-app-with-progressive-web-apps-pwas-1p88</guid>
      <description>&lt;p&gt;As a web developer, you are always looking for ways to improve the user experience and performance of your applications. One solution that has gained popularity in recent years is Progressive Web Apps (PWAs). PWAs are web applications that use modern web technologies to provide a native-like experience on the web. In this article, we will discuss how you can power up your Angular app with PWAs.&lt;/p&gt;

&lt;p&gt;What are PWAs?&lt;/p&gt;

&lt;p&gt;PWAs are web applications that use modern web technologies, such as service workers and web manifests, to provide a native-like experience on the web. PWAs can be installed on a user's device, just like a native app, and can be launched from the home screen. PWAs can also work offline, providing users with a seamless experience even when there is no internet connection.&lt;/p&gt;

&lt;p&gt;Why use PWAs with Angular?&lt;/p&gt;

&lt;p&gt;Angular is a popular framework for building web applications. By combining Angular with PWAs, you can create fast, offline-capable, and installable web applications that provide a native-like experience to users. This can lead to improved user engagement and retention, as well as increased conversions and revenue.&lt;/p&gt;

&lt;p&gt;How to add PWA to your Angular app?&lt;/p&gt;

&lt;p&gt;Adding a PWA to your Angular app is relatively straightforward, and can be done with the help of Angular CLI and the @angular/pwa package. Here's a step-by-step guide on how to do it:&lt;/p&gt;

&lt;p&gt;Install Angular CLI: If you haven't already installed Angular CLI, do so by running the following command: npm install -g @angular/cli.&lt;/p&gt;

&lt;p&gt;Create a new Angular project: Run the following command to create a new Angular project: ng new my-app.&lt;/p&gt;

&lt;p&gt;Install the @angular/pwa package: Run the following command to install the @angular/pwa package: npm install @angular/pwa.&lt;/p&gt;

&lt;p&gt;Add the PWA module to your app: Open the app.module.ts file and add the following import statement: import { BrowserModule } from '@angular/platform-browser';.&lt;/p&gt;

&lt;p&gt;Add the Service Worker: Run the following command to add a service worker to your app: ng add @angular/pwa.&lt;/p&gt;

&lt;p&gt;Build and serve your app: Run the following command to build and serve your app: ng serve.&lt;/p&gt;

&lt;p&gt;That's it! Your Angular app is now a PWA. You can test it by visiting the app in a browser and checking the "Add to Home Screen" option.&lt;/p&gt;

&lt;p&gt;Conclusion&lt;/p&gt;

&lt;p&gt;PWAs are a powerful way to improve the user experience and performance of your Angular applications. By combining Angular with PWAs, you can create fast, offline-capable, and installable web applications that provide a native-like experience to users. With the help of Angular CLI and the @angular/pwa package, adding a PWA to your Angular app is relatively straightforward. So, what are you waiting for? Power up your Angular app with PWAs today!&lt;/p&gt;

</description>
      <category>crypto</category>
      <category>web3</category>
      <category>blockchain</category>
      <category>offers</category>
    </item>
    <item>
      <title>Web3 development with Angular: Making life easy with blockchain</title>
      <dc:creator>Ilyoskhuja</dc:creator>
      <pubDate>Mon, 30 Jan 2023 04:55:56 +0000</pubDate>
      <link>https://dev.to/ilyoskhuja/web3-development-with-angular-making-life-easy-with-blockchain-13fa</link>
      <guid>https://dev.to/ilyoskhuja/web3-development-with-angular-making-life-easy-with-blockchain-13fa</guid>
      <description>&lt;p&gt;The use of blockchain technology has become more and more widespread in recent years. The decentralization of data and the security provided by blockchain make it a perfect fit for many applications. However, incorporating blockchain into web applications can often be a challenging task. This is where Angular, a popular web development framework, can make life easier.&lt;/p&gt;

&lt;p&gt;In this article, we will discuss how to incorporate blockchain technology into an Angular project and some best practices to keep in mind. We will also look at some ideas for creating reusable components and services for your application.&lt;/p&gt;

&lt;p&gt;Integrating blockchain into Angular&lt;/p&gt;

&lt;p&gt;The first step in incorporating blockchain into an Angular project is to choose the appropriate blockchain technology for your needs. Ethereum, for example, is a popular choice for decentralized applications. Once you have chosen your blockchain technology, you can start integrating it into your Angular application.&lt;/p&gt;

&lt;p&gt;One approach is to use a pre-existing Angular library such as Angular-Ethereum. This library provides an easy-to-use interface for communicating with the Ethereum blockchain and can help to streamline the integration process.&lt;/p&gt;

&lt;p&gt;Another option is to create your own custom library for communicating with the blockchain. This approach gives you more control over the communication and can help you to better tailor the library to your specific needs. When creating your own library, it is important to keep in mind the need for security and to follow best practices for communication with the blockchain.&lt;/p&gt;

&lt;p&gt;Creating reusable components and services&lt;/p&gt;

&lt;p&gt;Reusable components and services can help to streamline your Angular project and reduce development time. When it comes to incorporating blockchain into your Angular application, reusable components and services can also help to simplify the integration process.&lt;/p&gt;

&lt;p&gt;One idea for a reusable component is a blockchain-powered login system. This component would allow users to log in to your application using their blockchain credentials and would help to secure the login process. Another idea is a blockchain-powered payment system, which would allow users to make payments directly from their blockchain wallets.&lt;/p&gt;

&lt;p&gt;When creating reusable components and services, it is important to consider their modularity and ease of use. By making components and services easy to use, you can help to encourage adoption and make it easier for other developers to incorporate them into their own projects.&lt;/p&gt;

&lt;p&gt;Conclusion&lt;/p&gt;

&lt;p&gt;Incorporating blockchain into an Angular project can be a challenging task, but it doesn't have to be. By using Angular-Ethereum or creating your own custom library, you can streamline the integration process and make it easier to develop blockchain-powered applications. Reusable components and services can also help to simplify the development process and encourage adoption. With Angular and blockchain, the sky is the limit for what you can build.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>angular</category>
    </item>
    <item>
      <title>Creating behavior tests for User Interfaces</title>
      <dc:creator>Ilyoskhuja</dc:creator>
      <pubDate>Mon, 30 Jan 2023 04:14:16 +0000</pubDate>
      <link>https://dev.to/ilyoskhuja/creating-behavior-tests-for-user-interfaces-1l2k</link>
      <guid>https://dev.to/ilyoskhuja/creating-behavior-tests-for-user-interfaces-1l2k</guid>
      <description>&lt;p&gt;Behavior Driven Development (BDD) is a software development methodology that emphasizes the behavior of a system and focuses on testing it against expected outcomes. BDD is particularly useful for testing user interfaces as it helps to validate that the UI behaves as expected given specific conditions.&lt;/p&gt;

&lt;p&gt;In this article, we will explore how to set up a testing infrastructure for user interfaces using BDD in Angular. The following main bullet points will be covered:&lt;/p&gt;

&lt;p&gt;What is BDD and how it applies to this talk: BDD is a software development methodology that focuses on the behavior of a system, as opposed to just its implementation. This approach is useful for testing user interfaces as it allows developers to validate that the UI behaves as expected.&lt;/p&gt;

&lt;p&gt;Setting up the testing environment: The concept of mixins and test preamble will be discussed. Mixins are reusable code snippets that can be used across multiple tests, while the test preamble sets up the testing environment by defining the necessary dependencies and configuration.&lt;/p&gt;

&lt;p&gt;Client satisfaction: We will learn how to organize our steps and make sure that all client requirements are covered using Gherkin syntax. Gherkin is a language used to write human-readable test scenarios that can be understood by both developers and clients.&lt;/p&gt;

&lt;p&gt;Trying a new approach of coverage by extending our tests' use cases: By extending our test use cases, we can increase the coverage of our tests and improve the reliability of our test suite.&lt;/p&gt;

&lt;p&gt;A bug was found: How to use regression testing to avoid it never comes back: If a bug is found, regression testing can be used to ensure that the bug does not reappear in future releases.&lt;/p&gt;

&lt;p&gt;In conclusion, BDD is a useful approach for testing user interfaces in Angular as it focuses on the behavior of the system, rather than just its implementation. By setting up a testing infrastructure using BDD and following best practices such as mixins, Gherkin syntax, and regression testing, developers can create a robust and reliable test suite for their user interfaces.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>angular</category>
    </item>
    <item>
      <title>Customizing Angular-Runtime modification of Web Apps with Module Federation</title>
      <dc:creator>Ilyoskhuja</dc:creator>
      <pubDate>Mon, 30 Jan 2023 03:57:39 +0000</pubDate>
      <link>https://dev.to/ilyoskhuja/customizing-angular-runtime-modification-of-web-apps-with-module-federation-3nob</link>
      <guid>https://dev.to/ilyoskhuja/customizing-angular-runtime-modification-of-web-apps-with-module-federation-3nob</guid>
      <description>&lt;p&gt;Module Federation is a feature in Angular that allows for modifying and customizing the runtime of web applications. It allows developers to split a monolithic application into smaller, independent modules that can be developed and deployed separately. This provides a number of benefits, including increased scalability, improved maintainability, and faster development times.&lt;/p&gt;

&lt;p&gt;In this article, we will go through the steps to customize an Angular application using Module Federation. To follow along, you will need to have a basic understanding of Angular and its architecture.&lt;/p&gt;

&lt;p&gt;Step 1: Set up the main application&lt;/p&gt;

&lt;p&gt;To begin, we need to set up the main application that will host the federated modules. In this example, we'll call it the "shell" application. The shell application should have its own set of dependencies and a default routing configuration.&lt;/p&gt;

&lt;p&gt;Step 2: Create the federated modules&lt;/p&gt;

&lt;p&gt;Next, we will create the federated modules that will be added to the main application. Each module should have its own set of dependencies and a unique routing configuration.&lt;/p&gt;

&lt;p&gt;Step 3: Configure the federated modules&lt;/p&gt;

&lt;p&gt;To configure the federated modules, we need to add a "remotes" property to the shell application's angular.json file. This property should include the name and location of each federated module.&lt;/p&gt;

&lt;p&gt;Step 4: Update the main application's routing configuration&lt;/p&gt;

&lt;p&gt;Once the federated modules have been added to the shell application, we need to update the main application's routing configuration to include the routes from each module. This can be done by using the Angular Router's lazy-loading feature.&lt;/p&gt;

&lt;p&gt;Step 5: Deploy the application&lt;/p&gt;

&lt;p&gt;Finally, we can deploy the application and test it to see if everything is working as expected.&lt;/p&gt;

&lt;p&gt;In conclusion, customizing the runtime of an Angular application using Module Federation provides a number of benefits, including increased scalability, improved maintainability, and faster development times. By following these steps, you can get started with customizing your own Angular application using Module Federation.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>angular</category>
    </item>
    <item>
      <title>How to Build Angular Applications for Performance Optimization</title>
      <dc:creator>Ilyoskhuja</dc:creator>
      <pubDate>Mon, 30 Jan 2023 03:53:01 +0000</pubDate>
      <link>https://dev.to/ilyoskhuja/how-to-build-angular-applications-for-performance-optimization-hi5</link>
      <guid>https://dev.to/ilyoskhuja/how-to-build-angular-applications-for-performance-optimization-hi5</guid>
      <description>&lt;p&gt;Building high-performing Angular applications is critical for providing a smooth user experience and ensuring the application's success. Here are some steps to optimize Angular applications for performance:&lt;/p&gt;

&lt;p&gt;Lazy Loading: Use lazy loading to defer loading of non-critical components until they are actually needed. This reduces the initial loading time and improves overall performance.&lt;/p&gt;

&lt;p&gt;Use Ahead-of-Time (AoT) Compilation: AoT compiles Angular components and templates at build time, improving runtime performance and reducing the size of the application.&lt;/p&gt;

&lt;p&gt;Minimize the Size of Dependencies: Keeping the size of dependencies small helps reduce the overall size of the application, making it faster to download and run.&lt;/p&gt;

&lt;p&gt;Use Change Detection Strategies: Angular provides multiple change detection strategies, including OnPush and Default. Choose the most appropriate strategy for your use case to optimize change detection performance.&lt;/p&gt;

&lt;p&gt;Use the Angular CLI: The Angular CLI provides a variety of performance optimization features, such as tree-shaking, which removes unused code, and minification, which reduces the size of the application.&lt;/p&gt;

&lt;p&gt;Use a Production Build: Use a production build for deploying to production, as it includes performance optimizations such as minification and tree-shaking.&lt;/p&gt;

&lt;p&gt;Monitor Performance: Regularly monitor the performance of your Angular application and make performance improvements as necessary. Use tools like the Angular Performance Tools and the Chrome DevTools Performance tab to get a detailed understanding of performance issues.&lt;/p&gt;

&lt;p&gt;Example: Let's say we have an e-commerce application with a home page that displays a list of products. To optimize the performance of this page, we could:&lt;/p&gt;

&lt;p&gt;Use lazy loading to defer loading the product details component until a user clicks on a product.&lt;/p&gt;

&lt;p&gt;Use AoT compilation to compile the home page components at build time.&lt;/p&gt;

&lt;p&gt;Minimize the size of dependencies by using a light-weight library for product images.&lt;/p&gt;

&lt;p&gt;Use the OnPush change detection strategy, as the list of products is unlikely to change frequently.&lt;/p&gt;

&lt;p&gt;Use the Angular CLI to build a production version of the application, which will include performance optimizations such as minification and tree-shaking.&lt;/p&gt;

&lt;p&gt;Monitor the performance of the home page regularly, and make improvements as necessary.&lt;/p&gt;

&lt;p&gt;By following these steps, you can build Angular applications that are optimized for performance, providing a smooth user experience and ensuring the application's success.&lt;/p&gt;

</description>
      <category>notion</category>
      <category>integrations</category>
      <category>toolings</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Import Maps- The Next evolution step for MicroFrontends</title>
      <dc:creator>Ilyoskhuja</dc:creator>
      <pubDate>Mon, 30 Jan 2023 03:42:38 +0000</pubDate>
      <link>https://dev.to/ilyoskhuja/import-maps-the-next-evolution-step-for-microfrontends-3anc</link>
      <guid>https://dev.to/ilyoskhuja/import-maps-the-next-evolution-step-for-microfrontends-3anc</guid>
      <description>&lt;p&gt;Import Maps is a relatively new browser feature that provides a way to control how modules are resolved and loaded in a web application. It enables developers to map a module identifier to a specific location, allowing them to load dependencies in a more organized and flexible manner. This feature is particularly useful for microfrontends, which are a popular architecture pattern in web development that involves breaking down a monolithic frontend application into smaller, independent components. In this article, we'll explore how Import Maps can be leveraged in Angular, a popular frontend framework, to further improve the development and maintenance of microfrontends.&lt;/p&gt;

&lt;p&gt;Import Maps in Angular&lt;br&gt;
Angular, like many other frontend frameworks, uses JavaScript modules to organize code into reusable components. With modules, you can import dependencies into your application and use them in your code. However, when building microfrontends, the module resolution mechanism can become more complicated, especially when trying to share common dependencies across multiple microfrontends.&lt;/p&gt;

&lt;p&gt;Import Maps provide a solution to this problem by allowing developers to specify how module identifiers should be resolved and loaded in their applications. With Import Maps, developers can specify a mapping between a module identifier and a specific location where the module can be loaded from. This means that instead of hardcoding the module location in the application code, you can use an import map to configure it dynamically.&lt;/p&gt;

&lt;p&gt;Setting up Import Maps in Angular&lt;br&gt;
To use Import Maps in Angular, you first need to add the import maps polyfill to your application. The polyfill provides support for Import Maps in older browsers that do not support the feature natively. Next, you can create an import map file in your application and add the mappings you need. Here's an example import map:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "imports": {
    "lodash": "/node_modules/lodash/lodash.js"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we're mapping the lodash module identifier to the location of the lodash library in the node_modules directory.&lt;/p&gt;

&lt;p&gt;Once you have created the import map, you can reference it in your application by adding the following code to your HTML file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script type="importmap"&amp;gt;
  {
    "imports": {
      "lodash": "/node_modules/lodash/lodash.js"
    }
  }
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this setup, you can now use the lodash library in your Angular application by importing it using the module identifier lodash.&lt;/p&gt;

&lt;p&gt;Benefits of Using Import Maps in Angular&lt;br&gt;
The use of Import Maps in Angular provides several benefits, including:&lt;/p&gt;

&lt;p&gt;Improved maintenance: By using Import Maps to map module identifiers to specific locations, you can make changes to the location of dependencies in your application without having to update the code that uses them. This makes it easier to maintain your microfrontends as they grow and change over time.&lt;/p&gt;

&lt;p&gt;Better organization: Import Maps allow you to better organize your dependencies by mapping them to specific locations. This makes it easier to find and manage your dependencies, especially in large and complex applications.&lt;/p&gt;

&lt;p&gt;Better performance: Import Maps provide a way to load dependencies in parallel, improving the overall performance of your application.&lt;/p&gt;

&lt;p&gt;Improved compatibility: By using Import Maps, you can make sure that your dependencies are loaded correctly and consistently across different browsers and platforms, even if they have different module resolution mechanisms.&lt;/p&gt;

&lt;p&gt;In conclusion, Import Maps are a powerful tool for improving the development and maintenance of microfrontends in Angular. By using Import Maps,&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>angular</category>
    </item>
    <item>
      <title>Hexagonal Architecture in Angular: An Overview with an Example</title>
      <dc:creator>Ilyoskhuja</dc:creator>
      <pubDate>Mon, 30 Jan 2023 03:37:44 +0000</pubDate>
      <link>https://dev.to/ilyoskhuja/hexagonal-architecture-in-angular-an-overview-with-an-example-1hc2</link>
      <guid>https://dev.to/ilyoskhuja/hexagonal-architecture-in-angular-an-overview-with-an-example-1hc2</guid>
      <description>&lt;p&gt;Hexagonal Architecture, also known as Ports and Adapters, is a software design pattern that focuses on the separation of concerns. It's a way to structure applications in such a way that they are decoupled from external factors like databases, third-party APIs, and user interfaces. In Angular, this architecture can be applied to build scalable and maintainable applications.&lt;/p&gt;

&lt;p&gt;In a hexagonal architecture, the application is seen as a central core with different ports for different external systems. The core contains the business logic and interacts with external systems through adapters. The core is isolated from changes in external systems, making the application more flexible and adaptable.&lt;/p&gt;

&lt;p&gt;Example of Hexagonal Architecture in Angular&lt;/p&gt;

&lt;p&gt;Here is an example of how you can implement hexagonal architecture in Angular:&lt;/p&gt;

&lt;p&gt;Core: The core contains the business logic of the application. It is the central component and should have no knowledge of external systems. The core is responsible for processing inputs and producing outputs.&lt;/p&gt;

&lt;p&gt;Ports: Ports are the interfaces between the core and external systems. They define what the core needs from external systems and what it provides to them.&lt;/p&gt;

&lt;p&gt;Adapters: Adapters are the components that implement the ports. They translate data between the core and external systems.&lt;/p&gt;

&lt;p&gt;Let's consider a simple to-do application where the core is responsible for creating, reading, updating, and deleting to-do items. The user interface is an external system, and the database is another external system.&lt;/p&gt;

&lt;p&gt;In this example, the core has two ports: one for the user interface and one for the database. The user interface port provides methods for retrieving and saving to-do items. The database port provides methods for reading and writing to-do items from the database.&lt;/p&gt;

&lt;p&gt;The adapters for the user interface and database ports implement the methods defined in the ports. The user interface adapter communicates with the user interface to retrieve and save to-do items. The database adapter communicates with the database to read and write to-do items.&lt;/p&gt;

&lt;p&gt;Benefits of Hexagonal Architecture in Angular&lt;/p&gt;

&lt;p&gt;Increased Flexibility: The separation of the core from external systems makes the application more flexible. Changes to external systems do not affect the core, and the core can continue to operate even if external systems are unavailable.&lt;/p&gt;

&lt;p&gt;Improved Testability: The isolation of the core makes it easier to test. The core can be tested in isolation, without the need for external systems. This improves the reliability and maintainability of the application.&lt;/p&gt;

&lt;p&gt;Improved Scalability: The separation of the core from external systems makes it easier to add new features and scale the application. New external systems can be added without affecting the core.&lt;/p&gt;

&lt;p&gt;Conclusion&lt;/p&gt;

&lt;p&gt;Hexagonal architecture is a powerful design pattern that can be used to build scalable and maintainable applications in Angular. By separating the core from external systems, the application becomes more flexible, testable, and scalable. The example provided in this article is a simple demonstration of how hexagonal architecture can be applied in Angular. With this architecture, you can build complex applications that can adapt to changing requirements and grow over time.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>angular</category>
    </item>
    <item>
      <title>Ngrx - Core Principles &amp; New Features</title>
      <dc:creator>Ilyoskhuja</dc:creator>
      <pubDate>Mon, 30 Jan 2023 03:30:22 +0000</pubDate>
      <link>https://dev.to/ilyoskhuja/ngrx-core-principles-new-features-4dj4</link>
      <guid>https://dev.to/ilyoskhuja/ngrx-core-principles-new-features-4dj4</guid>
      <description>&lt;p&gt;Ngrx is a powerful and popular library for building reactive applications in Angular. It provides a complete set of tools for managing state and side effects in your application. In this article, we'll cover the core principles of Ngrx and explore some of its new features.&lt;/p&gt;

&lt;p&gt;Core Principles&lt;/p&gt;

&lt;p&gt;Immutable State: Ngrx stores state as an immutable data structure, which means that state cannot be changed directly. Instead, state changes must be performed through actions and reducers.&lt;br&gt;
Unidirectional Data Flow: Ngrx follows the unidirectional data flow pattern, where data flows in a single direction from actions to reducers to state.&lt;br&gt;
Separation of Concerns: Ngrx separates state management from business logic, making it easier to maintain and test your application.&lt;/p&gt;

&lt;p&gt;New Features&lt;/p&gt;

&lt;p&gt;Facades: Ngrx 8 introduces facades, which provide a simple and intuitive way to access and manipulate state from components. Facades are generated automatically for you, and you can use them just like any other service in Angular.&lt;br&gt;
Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Injectable()
export class ProductsFacade {
  products$ = this.store.pipe(select(selectAllProducts));

  constructor(private store: Store&amp;lt;AppState&amp;gt;) {}

  addProduct(product: Product) {
    this.store.dispatch(addProduct({ product }));
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Actions: Ngrx 8 also introduces a new and improved way to create actions, using the createAction function. This makes it easier to define and manage your actions, and also provides better type checking for your action payloads.&lt;br&gt;
Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
export const addProduct = createAction(
  '[Products] Add Product',
  props&amp;lt;{ product: Product }&amp;gt;()
);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Selectors: Ngrx 8 provides improved support for selectors, making it easier to select and manipulate state in your application. Selectors can now be created as simple functions, and you can also use memoization to optimize performance.&lt;br&gt;
Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const selectAllProducts = createSelector(
  selectProductsState,
  (state: ProductsState) =&amp;gt; state.products
);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In conclusion, Ngrx provides a powerful and flexible toolset for building reactive applications in Angular. With its core principles of immutability, unidirectional data flow, and separation of concerns, and its new features like facades, actions, and selectors, Ngrx makes it easier to build and maintain complex applications.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>community</category>
      <category>feedback</category>
    </item>
    <item>
      <title>Streamlined Page Title Accessibility in Angular</title>
      <dc:creator>Ilyoskhuja</dc:creator>
      <pubDate>Mon, 30 Jan 2023 03:19:57 +0000</pubDate>
      <link>https://dev.to/ilyoskhuja/streamlined-page-title-accessibility-in-angular-33mo</link>
      <guid>https://dev.to/ilyoskhuja/streamlined-page-title-accessibility-in-angular-33mo</guid>
      <description>&lt;p&gt;Page titles play a crucial role in website accessibility, as they provide context and help users understand the content of a web page. In Angular, setting the page title dynamically can be achieved through various methods, but a common and efficient approach is using the Title service.&lt;/p&gt;

&lt;p&gt;Here's a step-by-step example of implementing dynamic page titles in Angular:&lt;/p&gt;

&lt;p&gt;Import the Title service in the component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Title } from '@angular/platform-browser';

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inject the Title service in the component's constructor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;constructor(private title: Title) {}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set the title in the component's ngOnInit lifecycle hook or in a method that gets called whenever the title needs to change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ngOnInit() {
  this.title.setTitle('Page Title');
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Include the title tag in the component's template file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;title&amp;gt;{{title}}&amp;lt;/title&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these steps, the page title will now dynamically change based on the component's logic.&lt;/p&gt;

&lt;p&gt;It's also a good practice to add meaningful and descriptive titles for each page, making it easier for users and search engines to understand the content of a web page. Moreover, screen readers and other assistive technologies use the page title to provide context to users with disabilities.&lt;/p&gt;

&lt;p&gt;In conclusion, implementing dynamic page titles in Angular is straightforward and can greatly improve the accessibility of a website. By using the Title service and following best practices, developers can ensure that their pages are accessible and user-friendly.&lt;/p&gt;

</description>
      <category>uidesign</category>
      <category>webdev</category>
      <category>showdev</category>
    </item>
    <item>
      <title>The State of End-to-end Testing with Angular - Prepare for Protractor Deprecation</title>
      <dc:creator>Ilyoskhuja</dc:creator>
      <pubDate>Mon, 30 Jan 2023 03:10:56 +0000</pubDate>
      <link>https://dev.to/ilyoskhuja/the-state-of-end-to-end-testing-with-angular-prepare-for-protractor-deprecation-3a81</link>
      <guid>https://dev.to/ilyoskhuja/the-state-of-end-to-end-testing-with-angular-prepare-for-protractor-deprecation-3a81</guid>
      <description>&lt;p&gt;Angular is a popular open-source framework for building web applications, and end-to-end (e2e) testing is a crucial part of ensuring that your application is working as expected. However, with the recent deprecation of Protractor, the e2e testing landscape for Angular has changed significantly. In this article, we'll explore the state of e2e testing with Angular and provide a step-by-step guide to prepare for the deprecation of Protractor.&lt;/p&gt;

&lt;p&gt;What is End-to-end Testing?&lt;/p&gt;

&lt;p&gt;End-to-end testing is a type of testing that involves testing an application from start to finish, simulating the user's experience. This type of testing helps to catch bugs and issues that may not have been detected through unit or integration testing. With Angular, e2e tests are written using the Protractor framework.&lt;/p&gt;

&lt;p&gt;Why is Protractor being Deprecated?&lt;/p&gt;

&lt;p&gt;Protractor was developed as an open-source e2e testing framework for Angular applications. However, over time, it has become increasingly complex, and its performance has become a concern for many developers. Additionally, Protractor is built on top of the deprecated WebDriverJS library, which has made it difficult to maintain and update. As a result, the Angular team has decided to deprecate Protractor and replace it with a new e2e testing tool called Playwright.&lt;/p&gt;

&lt;p&gt;How to Prepare for Protractor Deprecation?&lt;/p&gt;

&lt;p&gt;If you're currently using Protractor for e2e testing in your Angular applications, it's important to start planning for the transition to Playwright. Here's a step-by-step guide to help you prepare:&lt;/p&gt;

&lt;p&gt;Review your existing e2e tests: Take a look at your existing e2e tests and make a list of any test cases that you need to migrate to Playwright.&lt;/p&gt;

&lt;p&gt;Install Playwright: Playwright can be installed as a node module by running npm install -g playwright.&lt;/p&gt;

&lt;p&gt;Write Playwright tests: Playwright tests are written in JavaScript and are similar in structure to Protractor tests. Start by writing simple tests for your most important features and work your way up to more complex tests.&lt;/p&gt;

&lt;p&gt;Run your tests: Once you have written your tests, you can run them using the Playwright CLI by running playwright run .js.&lt;/p&gt;

&lt;p&gt;Debug and refine: As with any new testing tool, you may encounter bugs or issues. Use the Playwright debugging tools to identify and resolve these issues.&lt;/p&gt;

&lt;p&gt;In conclusion, the deprecation of Protractor marks an important turning point in the development of Angular e2e testing. However, by following the steps outlined in this article, you can prepare for this change and ensure that your Angular applications continue to be thoroughly tested and bug-free.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>angular</category>
    </item>
    <item>
      <title>Angular CLI Auto-Completion: Streamlining Your Workflow</title>
      <dc:creator>Ilyoskhuja</dc:creator>
      <pubDate>Mon, 30 Jan 2023 03:05:51 +0000</pubDate>
      <link>https://dev.to/ilyoskhuja/angular-cli-auto-completion-streamlining-your-workflow-2k80</link>
      <guid>https://dev.to/ilyoskhuja/angular-cli-auto-completion-streamlining-your-workflow-2k80</guid>
      <description>&lt;p&gt;Angular CLI Auto-Completion: Streamlining Your Workflow&lt;/p&gt;

&lt;p&gt;The Angular CLI is an essential tool for developers working on Angular projects. It provides a simple and efficient way to manage your project and perform common development tasks. One of its key features is the auto-completion capability, which streamlines your workflow and saves you time.&lt;/p&gt;

&lt;p&gt;How to Enable Angular CLI Auto-Completion&lt;/p&gt;

&lt;p&gt;To enable auto-completion for the Angular CLI, you will need to install the bash-completion package. This can be done by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g bash-completion

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the package is installed, you can activate auto-completion by adding the following line to your .bashrc file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source &amp;lt;(ng completion)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, whenever you use the Angular CLI in your terminal, you will have access to the auto-completion feature.&lt;/p&gt;

&lt;p&gt;Using Angular CLI Auto-Completion&lt;/p&gt;

&lt;p&gt;To see the power of auto-completion in action, let's look at an example. Suppose you want to create a new Angular project. You can start by typing the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng new

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, instead of typing out the entire command, you can press the Tab key. You will see a list of suggestions, including options like "--routing" and "--style". You can use the arrow keys to navigate the list and select the option you want to use.&lt;/p&gt;

&lt;p&gt;The auto-completion feature is also available when you work with existing projects. For example, if you want to generate a new component, you can start by typing the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng generate component

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, press the Tab key to see a list of suggestions, including options like "--inline-template" and "--inline-style".&lt;/p&gt;

&lt;p&gt;Conclusion&lt;/p&gt;

&lt;p&gt;The Angular CLI auto-completion feature is a valuable tool for streamlining your workflow and saving time. By providing suggestions for available commands and options, it reduces the need for manual typing and helps you avoid errors. Give it a try today and experience the difference it can make in your Angular development process.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>discuss</category>
      <category>workplace</category>
    </item>
  </channel>
</rss>
