<?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:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Fabio Zuin on Medium]]></title>
        <description><![CDATA[Stories by Fabio Zuin on Medium]]></description>
        <link>https://medium.com/@fabiozuin?source=rss-34f609eb4f1------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*NYWbDabHr6oFLj1pyUvtCA.jpeg</url>
            <title>Stories by Fabio Zuin on Medium</title>
            <link>https://medium.com/@fabiozuin?source=rss-34f609eb4f1------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 23:25:10 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@fabiozuin/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Big O for prompts… yeah, I know, it sounds crazy, but hear me out.]]></title>
            <link>https://medium.com/@fabiozuin/big-o-for-prompts-yeah-i-know-it-sounds-crazy-but-hear-me-out-1c144d716137?source=rss-34f609eb4f1------2</link>
            <guid isPermaLink="false">https://medium.com/p/1c144d716137</guid>
            <category><![CDATA[vibe-coding]]></category>
            <category><![CDATA[code]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[llm]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Fabio Zuin]]></dc:creator>
            <pubDate>Sat, 31 Jan 2026 01:42:41 GMT</pubDate>
            <atom:updated>2026-01-31T01:42:41.053Z</atom:updated>
            <content:encoded><![CDATA[<p>How delegating complex decisions to LLMs became a probabilistic problem</p><p>Ok, let me explain, this might sound a bit weird, but bear with me.</p><p>We learned to use Big O to think about code. To understand how algorithms scale, where the limits are, what trade-offs we’re making.</p><p>Big O gave us a common language to talk about complexity without depending on hardware or implementation details.</p><p>But what popped into my head wasn’t code — it was the <strong>limit of interactions with LLMs</strong>:</p><blockquote><em>when does delegation stop being reliable?</em></blockquote><p>or</p><blockquote><em>how complex can a prompt actually be?</em></blockquote><h3>The problem: Polymarket Bot #3… This Time It’ll Work…</h3><p>For me, Polymarket is a modern playground for <a href="https://en.wikipedia.org/wiki/Game_theory">game theory</a>.</p><p>Algorithms reacting to algorithms, under uncertainty, incomplete information, and a bunch of other variables.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/672/0*qLzKqz2H-KXoBwuO" /><figcaption>Polymarket for dummies</figcaption></figure><p>An almost perfect environment to test ideas, fail fast, adjust hypotheses, and discover where human intuition breaks… of course, all of this in paper trading mode (got 5 euros to lend me? 😉).</p><p>All of that to say: this has been my favorite place for <strong>vibe coding</strong> lately… and where my questioning started.</p><h3>An incremental flow, and a small mistake</h3><p>Basically, I have my LLM of choice, which I use to discuss possible solutions for my bot’s problems. I bring ideas, we debate what works and what doesn’t. After deciding what we should implement, I generate a prompt with the full step-by-step of that implementation (no code) for my other agent, which reviews and implements the whole solution.</p><p>In one of those interactions, a task was implemented correctly, as usual.</p><p>The code ran. Nothing broke.</p><p>But during implementation, an environment variable was duplicated. Both represented the same thing. Only one was actually used.</p><p>The other one existed, wasn’t read by anyone, and caused no errors.</p><p>The problem wasn’t functional.<br> It was <strong>consistency</strong>.</p><p>This kind of issue easily slips through a superficial review, because everything “works” — notice the quotes.</p><p>And I know: <em>“But Zuin, this error changes nothing.”</em><br> Yes, my dear reader, it changes nothing.</p><p>But in that massive vibe-coded feature, written at 9am at your kitchen counter, sipping a mocha made with a famous chocolate brand that rhymes with <em>cat, </em>did you really review all the code?</p><p>If that variable wasn’t used, what else there wasn’t actually implemented?</p><p>And that leads to an unavoidable question:</p><blockquote><strong>How do I evaluate how far I can delegate this problem?</strong></blockquote><blockquote>And more importantly:</blockquote><blockquote><strong>How do I reduce the probability of these errors showing up?</strong></blockquote><h3>Benchmarks…</h3><p>Benchmarks exist, including some very interesting ones about <a href="https://www.letta.com/blog/context-bench">context</a> length.</p><p>But let’s be honest: do you really know what each benchmark measures? How it’s built?</p><p>Today, you can ask an AI to:</p><ul><li>write code</li><li>structure ideas</li><li>explain concepts</li><li>support decisions</li></ul><p>So the real question becomes:</p><p><strong>How much understanding of a given problem can it sustain, amplified by other implicit problems stacked on top of it?</strong></p><p>Benchmarks isolate skills. Real problems stack decisions across different domains, in this case, for example: finance, machine learning, and software engineering.</p><h3>The limit is not static</h3><p>In many areas, an LLM can already provide information — often high quality.</p><p>But that limit is not fixed.</p><p>It changes across models and versions.<br> Sometimes it gets better.<br> Sometimes it gets worse.</p><p>It’s not a monotonic curve.</p><h3>A prompt is a probability question</h3><p>Given the same request, you can get different answers — some better, some worse.</p><p>The goal isn’t to eliminate variability. That’s not realistic.</p><p>The real question is:</p><p><strong>How do I reduce the probability of failure, given a specific request?</strong></p><p>Delegating to an AI is, inevitably, a probabilistic game (like everything in life?).</p><p>Maybe the right question isn’t:<br> <em>“How much context fits in a single prompt?”</em></p><p>But rather:</p><blockquote><strong>How many decisions am I asking to be made at the same time? And how good is this model at each one of them?</strong></blockquote><p>A request rarely involves a single decision.</p><p>And those decisions don’t have the same difficulty.</p><h3>Ok, but… where does Big O fit in?</h3><p>Big O is an inspiration: a way of thinking about limits without focusing only on implementation.</p><p>Maybe we need something similar — not for code, but for the <strong>effective size of a problem</strong>, given a model, a version, and a context.</p><blockquote>⚠️ <strong>WARNING: AI-generated, JUST AS AN EXAMPLE</strong><br> This does <em>not</em> measure what the AI can do.<br> It measures the <strong>risk of delegating everything at once</strong>.</blockquote><ul><li><strong>O(1) — Atomic task</strong><br> A clear instruction, no implicit context.<br> Example: <em>“Refactor this function to remove duplication.”</em><br> 👉 AI executes directly, near-zero error.</li><li><strong>O(n) — Linear requirement complexity</strong><br> Each new requirement adds proportional effort.<br> Example: <em>“Refactor, add tests, follow the style guide, and document.”</em><br> 👉 Works well, as long as requirements are explicit.</li><li><strong>O(n²) — Interacting requirements</strong><br> Decisions in one requirement affect others.<br> Example: performance × readability × backward compatibility<br> 👉 AI still helps, but starts needing checkpoints.</li><li><strong>O(2ⁿ) — Combinatorial Complexity</strong><br> Multiple domains with their own rules and subtle conflicts.<br> Example: finance + ML + software engineering + compliance<br> 👉 Each wrong assumption creates a cascade of plausible errors.</li><li><strong>O(?) — Unknown complexity</strong><br> Poorly defined requirements, moving goals, or conflicting incentives.<br> Example: <em>“Do it the right way.”</em><br> 👉 Neither humans nor AI know where to start.</li></ul><p><strong>I know this is simplistic, but I wanted to leave it here as food for thought.</strong></p><p>Continuing…</p><p><strong>Vibe coding</strong>: here I make higher-level decisions, using an agent to implement a full ML algorithm — with logs, metrics, and everything else.</p><p><strong>Professional life as a programmer</strong>: here, changes are more localized — specific functions, well-defined HTTP requests, isolated React components. Everything is much more controlled and reviewed. Even so, I feel the bar rising more and more, to the point where very little code is actually written by hand. (Seems like Dario was right.)</p><p>Vibe coding , which, in my view, could already be renamed, since the early days of the technology gave the term a bad reputation.</p><h3>Wrapping up</h3><p>Delegating to an LLM is not a binary decision (“I trust it” vs. “I don’t”).<br> It’s a <strong>granularity problem</strong>.</p><p>The more heterogeneous decisions I stack together, the higher the probability that something slips through.</p><p>The human role, then, is not to review everything line by line, but to decide where delegation should stop — or where the problem should be broken down until each part has an acceptable failure radius.</p><p>In the end, delegating to an AI is always a probabilistic game.<br> The question is: <strong>what takes more time, reviewing the prompt or reviewing the code it generates?</strong></p><p>Even though I haven’t yet presented a rigorous mathematical formulation for this “Big-O-like” idea, I believe the core intuition is captured in this article; the next step is to investigate if and how this idea can be formalized.</p><p><em>By the way, my bot so far 😉</em></p><pre>INFO - 📊 PAPER STATUS: Active: 0 | Balance: $54.80 | Tot PnL: $4.80 | W/L: 45/36 | Agent: Initializing</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1c144d716137" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The paradigm of shipping fast in the age of AI]]></title>
            <link>https://medium.com/@fabiozuin/the-paradigm-of-shipping-fast-in-the-age-of-ai-8fcf86b998d1?source=rss-34f609eb4f1------2</link>
            <guid isPermaLink="false">https://medium.com/p/8fcf86b998d1</guid>
            <category><![CDATA[startup]]></category>
            <category><![CDATA[shipping]]></category>
            <category><![CDATA[ai]]></category>
            <dc:creator><![CDATA[Fabio Zuin]]></dc:creator>
            <pubDate>Wed, 05 Nov 2025 22:32:03 GMT</pubDate>
            <atom:updated>2025-11-05T22:36:32.415Z</atom:updated>
            <content:encoded><![CDATA[<p>AI makes building fast. The challenge is deciding when to launch. Ship when value starts, refine with real users, keep momentum.</p><p>I don’t really need to explain how AI changed the world, right?</p><p>Developers and engineers now have a new way to ship fast, explore ideas, and rediscover the <strong>joy of coding</strong>. You know, before the AIs start deploying themselves 😉.</p><p>Now is the moment to build, that’s for fun, for learning, or for starting something serious.</p><h4>The Landscape</h4><p>Today, big companies are already reporting massive acceleration in their software development life cycles due to AI. For example, studies show that developers using AI code assistants complete tasks significantly faster — in some cases up to <strong>~55% faster</strong> on average. Large organizations are restructuring entire workflows around AI pair-programming to reduce development time and time-to-market, and I’ve felt this shift myself in the way I work, how I prototype, and how fast I can move.</p><p>And beyond the organizational level, there’s the accessibility aspect: the time it takes to generate the first working version of something has dropped dramatically. Even if the quality isn’t perfect on the first try, it’s now easier to go from <strong>idea → prototype → iteration</strong>. The cost of simply trying has become much smaller. In my opinion, it’s even worth taking on some tech debt. This is where your software engineer instincts matter: knowing what is bearable and what is not.</p><p>From my perspective, that’s actually exciting. It’s incredible what a single developer can ship today with an AI pair.</p><h4><strong>But when is your product “good enough” to launch?</strong></h4><p>We can spin up new things <strong>faster than ever</strong>, but the question now is <em>when</em> to actually ship. And here’s the plot twist: the same AI tools that helped you get your MVP out in a weekend are helping everyone else ship <em>their</em> MVP just as fast. Speed is no longer the differentiator.</p><p><strong>Shipping fast isn’t just about speed — it’s about deciding when something is “ready enough” to get real and compete with the wild new world.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*q207DWbtW8PCG6OX81sejA.png" /><figcaption>When to bet everything and launch?</figcaption></figure><p>I’ve been cooking something for a while now, and every time I’m in the shower, it starts with a simple <em>“What if…”</em>. Five minutes later I’m imagining a new interaction, a slick loading animation, or some small experience detail that I’m convinced would make it stand out.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/618/0*Jql1kDD7gkocteu2.jpg" /><figcaption>Meme: Marked safe from shipping a great product today.</figcaption></figure><p>But the more I’ve built, the more I’ve learned: <strong>shipping is about being practical.</strong></p><p>In the age of AI, scoping your MVP has become even more important. The question is no longer <em>“What else could I add?”</em> — because the answer is always <strong>a lot</strong>. Instead, the real question becomes:</p><blockquote><strong><em>At what point does this start generating real value for someone?</em></strong></blockquote><p>Once you reach that point where the core loop works and someone can actually benefit from it, that’s the moment to ship. The differentiators, the animations, the personality… still important, and I believe you need to keep improving it, but… much of it can come later , guided by real users and real feedback 😉</p><p>So yes, I’m still learning, still improving, still fighting that voice that says <strong>“add just one more feature.”</strong></p><p>And <strong>honestly</strong>, <strong>I think a lot of us are.</strong></p><p><strong>TL;DR: Momentum &gt; perfection</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8fcf86b998d1" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[You should try it now: NodeJS with Typescript natively]]></title>
            <link>https://medium.com/@fabiozuin/you-should-try-it-now-node-js-with-typescript-natively-4221724c29d5?source=rss-34f609eb4f1------2</link>
            <guid isPermaLink="false">https://medium.com/p/4221724c29d5</guid>
            <category><![CDATA[beginner]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[node]]></category>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[tutorial]]></category>
            <dc:creator><![CDATA[Fabio Zuin]]></dc:creator>
            <pubDate>Sun, 05 Jan 2025 21:53:39 GMT</pubDate>
            <atom:updated>2025-01-05T22:08:10.044Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/797/0*jMJ8F3r37S1saHIR.jpg" /></figure><p>Start a new NodeJS project with Typescript natively out-of-the-box, in minutes.</p><p>If you’re like me — a young software engineer (okay, maybe not that young!) who always doing some side project for fun — you’re going to <strong>love</strong> this!</p><p>Remember how setting up a compiler to convert TypeScript into JavaScript for NodeJS was such a pain (yea, maybe some minutes more, ok)? Well, not anymore! With <strong>native TypeScript support</strong>, things just got a whole lot easier.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FNDIiWKEQEgr3VA7aqM%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fgiphy.com%2Fgifs%2Fpeacocktv-parks-and-recreation-rec-peacock-tv-NDIiWKEQEgr3VA7aqM&amp;image=https%3A%2F%2Fmedia0.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExOXBjdGZvY29mN2h5eHpxMDJna2Jxendpa3kyeGRlZnVsNTZtb3RreiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FNDIiWKEQEgr3VA7aqM%2Fgiphy_s.gif&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="244" frameborder="0" scrolling="no"><a href="https://medium.com/media/6c83212a63673b82b9d684119de3594a/href">https://medium.com/media/6c83212a63673b82b9d684119de3594a/href</a></iframe><h4>Prerequisites</h4><p>You’ll need <strong>Node.js version 22.7.0 or higher</strong> (we want enums, right?). To manage Node.js versions efficiently, use <strong>NVM</strong>:</p><ul><li>Download and install it from <a href="https://github.com/nvm-sh/nvm">nvm GitHub</a>.</li></ul><h4>Install and Use Node.js</h4><pre>nvm install 23.5.0<br>nvm use 23.5.0<br>## Now using node v23.5.0</pre><h4>Setting up your project</h4><pre>npm init<br>## Fill some stuff<br>## Let&#39;s install some package and their types<br>npm install express ## adds it to create a quick HTTP server<br>npm i --save-dev @types/express ## Add types</pre><h4>Add tsconfig.json</h4><p>In the project root, create a tsconfig.json file:</p><pre>{<br>    &quot;compilerOptions&quot;: {<br>      &quot;target&quot;: &quot;ESNext&quot;,<br>      &quot;allowImportingTsExtensions&quot;: true,<br>      &quot;moduleResolution&quot;: &quot;nodenext&quot;,<br>      &quot;module&quot;: &quot;NodeNext&quot;,<br>      &quot;strict&quot;: true,<br>      &quot;esModuleInterop&quot;: true,<br>      &quot;skipLibCheck&quot;: true,<br>      &quot;forceConsistentCasingInFileNames&quot;: true,<br>      &quot;types&quot;: [&quot;node&quot;],<br>      &quot;noEmit&quot;: true <br>    }<br>  }</pre><p><strong>Why </strong><strong>NodeNext and </strong><strong>ESNext?</strong><br>These configurations enable the latest features of Node.js and ES6. For example, the toSpliced function: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toSpliced">MDN Documentation</a>.</p><p>You can find more details in the TypeScript configuration references:</p><ul><li><a href="https://www.typescriptlang.org/tsconfig/#target">Target</a></li><li><a href="https://www.typescriptlang.org/tsconfig/moduleResolution.html">Module Resolution.</a></li></ul><h4>Update Package.json</h4><p>Update the type attribute to &quot;module&quot; and add the dev property to the scripts section:</p><pre>{<br>  &quot;name&quot;: &quot;test&quot;,<br>  &quot;version&quot;: &quot;1.0.0&quot;,<br>  &quot;main&quot;: &quot;index.js&quot;,<br>  &quot;scripts&quot;: {<br>    &quot;dev&quot;: &quot;node --experimental-strip-types --experimental-transform-types --watch index.ts&quot;,<br>    &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;<br>  },<br>  &quot;author&quot;: &quot;&quot;,<br>  &quot;type&quot;: &quot;module&quot;,<br>  &quot;license&quot;: &quot;ISC&quot;,<br>  &quot;description&quot;: &quot;&quot;,<br>  &quot;dependencies&quot;: {<br>    &quot;express&quot;: &quot;^4.21.2&quot;<br>  },<br>  &quot;devDependencies&quot;: {<br>    &quot;@types/express&quot;: &quot;^5.0.0&quot;<br>  }<br>}</pre><ul><li><strong>--experimental-strip-types:</strong> Strips TypeScript annotations before execution.</li><li><strong>--experimental-transform-types:</strong> Supports TypeScript-specific syntax like enums and namespaces.</li></ul><h4>Add index.ts</h4><p>Create an index.ts (or app.ts) file in the root directory:</p><pre>import express from &quot;express&quot;;<br><br>class TypescriptService {<br>  testVariable: string;<br><br>  constructor() {<br>    this.testVariable = &quot;I&#39;m definitely a string, since my birth&quot;;<br>  }<br><br>  getTestVariable() {<br>    return this.testVariable;<br>  }<br>}<br><br>const app = express();<br>const typescriptService = new TypescriptService();<br><br>app.get(&quot;/&quot;, async (req: express.Request, res: express.Response) =&gt; {<br>  res.send(typescriptService.getTestVariable());<br>});<br><br>app.listen(3001, () =&gt; {<br>  console.log(&quot;Server is running on port 3001&quot;);<br>});</pre><h4>Run the Project</h4><pre>npm run dev</pre><h4>Check to localhost:3001/ and BOOM 💥💥💥💥💥</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kuAtMZixAOU0M678ZPud4Q.png" /><figcaption>An website showing a raw string: “I’m definitely a string, since my birth”</figcaption></figure><h3>Conclusion</h3><p>What a journey it’s been from the beginning of NodeJs to where we are today! I truly see the power of starting projects with native TypeScript, and to be honest, I’ve been working with this setup, and it’s been running smoothly so far. I hope this setup works well for you too. That’s it for now, peace out!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/509/0*XS-fNnOA_AENYMZD.jpg" /><figcaption>Guy in corner of party meme, with a saying: “They don’t know, but I run TypeScript natively on my side projects.”</figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4221724c29d5" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[React: Rethinking your app’s with Lazy and Suspense]]></title>
            <link>https://medium.com/@fabiozuin/react-rethinking-your-apps-with-lazy-and-suspense-7923f901c0e8?source=rss-34f609eb4f1------2</link>
            <guid isPermaLink="false">https://medium.com/p/7923f901c0e8</guid>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[react]]></category>
            <dc:creator><![CDATA[Fabio Zuin]]></dc:creator>
            <pubDate>Wed, 28 Feb 2024 18:51:40 GMT</pubDate>
            <atom:updated>2024-02-28T18:53:43.764Z</atom:updated>
            <content:encoded><![CDATA[<h3>React: Rethinking your app’s code reusability with Lazy and Suspense</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/564/0*dpLiDh7e5cZ4yJBK.jpg" /><figcaption>Sadness for people that don’t use the lazy capabilities.</figcaption></figure><p>While I was working on refactoring an application I came across the following scenario, a normal one in the life of Junior/Middle/Senior web developer.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2ckk4MPXfm2dSTpBkrbpMw.png" /><figcaption>Desktop: Sidebar Menu, Mobile: Top Navbar</figcaption></figure><p>Initially, it was an <strong>MVP</strong> intended for showcasing the refactor and certain architectural choices, I began with the desktop version. However, later on, we made the decision to also showcase the mobile version.</p><p>Well, as a Software Engineer, I typically rely on the <strong>Mobile First approach, and I think its important to mention here, that this should be the approach in normal situations.</strong></p><h4>Code reusability</h4><p>Initially, my instinct was to introduce some <strong>breakpoints</strong> and incorporate additional <strong>TypeScript</strong> to enhance the functionality to the existing component. However, upon a reflection at the <strong>coffee break</strong> — <em>one of the many joys of software development </em>— I recognized that these are distinct components, and adding more code might unnecessarily complicate the component while breaking the rule of SoD (<strong>Separation of Duties</strong>).</p><h4>The Solution</h4><p>Create two components, each with its own implementation. It seemed straightforward enough. Using <strong>Tailwind breakpoints</strong>, I could easily dictate when each component should be displayed.</p><pre>import { Outlet } from &quot;react-router-dom&quot;;<br>import &quot;./App.css&quot;;<br>import SideBar from &quot;./components/SideBar/SideBar&quot;;<br>import TopNavigation from &quot;./components/TopNavigation/TopNavigation&quot;;<br><br>function App() {<br><br>  return (<br>    &lt;div className=&quot;flex flex-col md:flex-row &quot;&gt;<br>      &lt;div className=&quot;md:fixed&quot;&gt;<br>            &lt;TopNavigation /&gt;<br>            &lt;SideBar /&gt;<br>      &lt;/div&gt;<br>      &lt;div className=&quot;md:ml-[250px] w-full&quot;&gt;<br>        &lt;Outlet /&gt;<br>      &lt;/div&gt;<br>    &lt;/div&gt;<br>  );<br>}<br><br>export default App;</pre><pre>import { memo } from &quot;react&quot;;<br>import { MenuIcon } from &quot;../Icons/Menu&quot;;<br>import { UserIcon } from &quot;../Icons/User&quot;;<br><br>interface TopNavigationProps {<br>  title?: string;<br>}<br><br>const TopNavigation = memo(({ title = &quot;&quot; }: TopNavigationProps) =&gt; {<br>  return (<br>    &lt;div className=&quot;md:hidden flex w-full h-14 rounded-md border border-gray-700 items-center p-5&quot;&gt;<br>      &lt;MenuIcon className=&quot;w-8&quot; /&gt;<br>      &lt;div className=&quot;flex-1 text-center font-inter text-[22px] font-normal text-gray-100&quot;&gt;<br>        {title}<br>      &lt;/div&gt;<br>      &lt;UserIcon className=&quot;w-8&quot; /&gt;<br>    &lt;/div&gt;<br>  );<br>});<br><br>export default TopNavigation;</pre><h3>Pretty Simple, right?</h3><p>But there’s a <strong>catch</strong> with this approach. <strong>Consider this scenario: What if the user is currently using a mobile browser? Why would we want to download the desktop code?</strong></p><h4>Lazy loading to the rescue</h4><p>Since react <a href="https://legacy.reactjs.org/blog/2018/10/23/react-v-16-6.html#reactlazy-code-splitting-with-suspense">16.6</a>, we have the option to implement <strong>lazy loading</strong> for components, loading them only when necessary. It’s quite simple. In our case, we can download the components dynamically based in the the user viewport size.</p><p>Let’s create a custom hook called <strong>useIsMobile, </strong>a straightforward hook that returns a boolean indicating whether the viewport has changed below <strong>768</strong>, which is the default <strong>MD breakpoint in Tailwind.</strong></p><pre>import { useState, useEffect } from &quot;react&quot;;<br><br>export const useIsMobile = () =&gt; {<br>  const TAILWIND_MD_BREAKPONT = 768;<br>  const [width, setWidth] = useState(window.innerWidth);<br><br>  useEffect(() =&gt; {<br>    const handleWindowResize = () =&gt; setWidth(window.innerWidth);<br>    window.addEventListener(&quot;resize&quot;, handleWindowResize);<br>    return () =&gt; window.removeEventListener(&quot;resize&quot;, handleWindowResize);<br>  }, []);<br><br>  const isMobile = width &lt; TAILWIND_MD_BREAKPONT;<br><br>  return isMobile;<br>};</pre><p>An important note is that we are listening to the window resize event. So, <strong>every time</strong> this event occurs, we trigger the useEffect, which updates the value and triggers a re-render, and of course remove the event listener on the cleanup.</p><p>Now we should do a slight change to our <strong>App.tsx and voilà.</strong></p><pre>import { Outlet } from &quot;react-router-dom&quot;;<br>import &quot;./App.css&quot;;<br>import { Suspense, lazy, useEffect } from &quot;react&quot;;<br>import { useIsMobile } from &quot;./hooks/use-is-mobile&quot;;<br><br>const SideBar = lazy(() =&gt; import(&quot;./components/SideBar/SideBar&quot;));<br><br>const TopNavigation = lazy(<br>  () =&gt; import(&quot;./components/TopNavigation/TopNavigation&quot;)<br>);<br><br>//For example let&#39;s create a loader component for the fallback of the suspense<br>//This should be a separeted component with your respective loader<br>const Loader = () =&gt; &lt;&gt;Loading...&lt;/&gt;;<br><br>function App() {<br>  const isMobile = useIsMobile();<br>  <br>  return (<br>    &lt;div className=&quot;flex flex-col md:flex-row &quot;&gt;<br>      &lt;div className=&quot;md:fixed&quot;&gt;<br>        {isMobile ? (<br>          &lt;Suspense fallback={&lt;Loader /&gt;}&gt;<br>            &lt;TopNavigation /&gt;<br>          &lt;/Suspense&gt;<br>        ) : (<br>          &lt;Suspense fallback={&lt;Loader /&gt;}&gt;<br>            &lt;SideBar /&gt;<br>          &lt;/Suspense&gt;<br>        )}<br>      &lt;/div&gt;<br>      &lt;div className=&quot;md:ml-[250px] w-full&quot;&gt;<br>        &lt;Outlet /&gt;<br>      &lt;/div&gt;<br>    &lt;/div&gt;<br>  );<br>}<br><br>export default App;</pre><p>With the power of &lt;Suspense/&gt;, we can display a fallback while the children are loading. It&#39;s highly recommended to always implement this for providing a better <strong>UX</strong>. Additionally, you can choose to display any component you like as the fallback.</p><h3>Conclusion</h3><p>Adopting lazy loading and Suspense in React applications can greatly enhance <strong>user experience</strong>, <strong>improve code maintainability, and optimize performance</strong>. By strategically implementing these features, we can ensure faster load times, and better scalability.</p><p>While lazy loading and Suspense aren’t new concepts, their adoption can significantly impact the quality and efficiency of your applications. So, don’t hesitate to rethink your app’s architecture and incorporate these powerful tools into your development workflow.</p><p><strong>Sometimes is better to separate some code then just adding complex logic to an exist component.</strong></p><p>Thank you for joining me on this journey.</p><p>Until next time, happy coding! <strong>#Peace</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7923f901c0e8" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Build once, Deploy anywhere with Angular + Docker + Nginx]]></title>
            <link>https://medium.com/@fabiozuin/build-once-deploy-anywhere-with-angular-17-bf477c49668f?source=rss-34f609eb4f1------2</link>
            <guid isPermaLink="false">https://medium.com/p/bf477c49668f</guid>
            <category><![CDATA[nginx]]></category>
            <category><![CDATA[angular]]></category>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[docker]]></category>
            <category><![CDATA[ci-cd-pipeline]]></category>
            <dc:creator><![CDATA[Fabio Zuin]]></dc:creator>
            <pubDate>Tue, 02 Jan 2024 17:36:52 GMT</pubDate>
            <atom:updated>2024-01-02T17:44:39.191Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/715/0*BB1ZSWcGQyDBanxG.jpg" /><figcaption>Building and deploying once will save a considerable amount of your time.</figcaption></figure><h3>Angular, Docker &amp; Nginx: Build once, Deploy anywhere.</h3><p>Github code: <a href="https://github.com/fbzz/angular-build-once-deploy-anywhere">https://github.com/fbzz/angular-build-once-deploy-anywhere</a></p><p>In software development is quite common to have multiple environments, each with different configurations. <strong>Angular </strong>offers a built-in system for managing environment variables, allowing for the <strong>replacement of files during build time</strong>. However, this approach often requires creating separate builds for each environment, which can be <strong>time-consuming</strong> but to avoid this we have a pretty common pattern in the industry.</p><h4>Build once, deploy anywhere…</h4><p>So, let’s have an example where we have two environments, <strong>DEV and PROD,</strong> and for that, we want to have <strong>ONE </strong>build. For that, we use:</p><ol><li>Angular — a front-end framework for building SPA applications.</li><li>Nginx — is a web server and reverse proxy server.</li><li>Docker — is a platform for developing, shipping, and running applications in containers, which are lightweight, portable, and self-sufficient environments.</li></ol><h3>1 - Angular</h3><p>Let’s create three files, those files will handle different configurations based on the environment:</p><p><strong>src\config</strong></p><ul><li><strong>app-config.dev.json</strong> — For Dev.</li><li><strong>app-config.prod.json </strong>— For Prod.</li></ul><p><strong>src\</strong></p><ul><li><strong>app-config.json</strong> — For local development, and to be replaced in the future.</li></ul><pre>//Example of an App config, it&#39;s a simple JSON.<br>{<br>  &quot;API_URL&quot;: &quot;LOCAL DEVELOPMENT&quot;,<br>}</pre><p>Now, let’s include it in our bundle. In your <strong>angular.json</strong> file, within the <strong>build </strong>section, add our config folder to the assets.<strong>:</strong></p><pre>  &quot;build&quot;: {<br>          &quot;builder&quot;: &quot;@angular-devkit/build-angular:browser-esbuild&quot;,<br>            ...<br>            &quot;assets&quot;: [<br>              &quot;src/favicon.ico&quot;,<br>              &quot;src/assets&quot;,<br>              &quot;src/app-config.json&quot;,<br>              &quot;src/config&quot;, // HERE<br>            ],<br>            ...<br>}</pre><p>Runningnpm run build we have our config folder at our dist</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/400/1*F4zKvK_qEy86Or2qhdww3g.png" /><figcaption>Bundle with the config folder</figcaption></figure><p><strong>1.2 -</strong> In Angular, we can create services that are singletons, capable of retaining data throughout the application, making them reusable across the entire application.</p><pre>import { Injectable } from &#39;@angular/core&#39;;<br>import { firstValueFrom } from &#39;rxjs&#39;;<br>import { HttpClient, HttpBackend } from &#39;@angular/common/http&#39;;<br><br>//Move this type to a shared folder<br>export interface AppConfig {<br>  API_URL: string;<br>}<br><br>@Injectable({<br>  providedIn: &#39;root&#39;,<br>})<br><br><br>export class ConfigService {<br>  //We create the configuration with default values in case anything fails<br>  private configuration: AppConfig = {<br>    API_URL: &#39;/api&#39;,<br>  };<br><br>  private http: HttpClient;<br>  constructor(private readonly httpHandler: HttpBackend) {<br>    this.http = new HttpClient(this.httpHandler);<br>  }<br><br>  //This function will get the current config for the environment<br>  setConfig(): Promise&lt;void | AppConfig&gt; {<br>    return firstValueFrom(this.http.get&lt;AppConfig&gt;(&#39;./app-config.json&#39;))<br>      .then((config: AppConfig) =&gt; (this.configuration = config))<br>      .catch(error =&gt; {<br>        console.error(error);<br>      });<br>  }<br><br>  //We&#39;re going to use this function to read the config.<br>  readConfig(): AppConfig {<br>    return this.configuration;<br>  }<br>}</pre><p><strong>1.3 -</strong> Angular provides us <a href="https://angular.dev/api/core/APP_INITIALIZER">APP_INITIALIZER</a>,a DI token, that you can use to provide one or more initialization functions, the function is <strong>executed </strong>during the <strong>application bootstrap process</strong>, and the <strong>needed data is available on startup.</strong></p><p><em>NgModules:</em></p><pre>//Here we have the function to receive the Config Service and use it for retrieving<br>//The config files.<br>export function initConfig(appConfig: ConfigService) {<br>  return () =&gt; appConfig.setConfig();<br>}<br><br>@NgModule({<br>  imports: [BrowserModule],<br>  declarations: [AppComponent],<br>  bootstrap: [AppComponent],<br>  providers: [<br>  {<br>      provide: APP_INITIALIZER,<br>      useFactory: initConfig,<br>      deps: [ConfigService], //We say to angular that this initializer depends of ConfigService<br>      //So config service will be available for the init config<br>      multi: true,<br>    },<br>  ],<br>})<br><br>export class AppModule {}</pre><p><em>Standalone:</em></p><pre>import { provideHttpClient } from &quot;@angular/common/http&quot;;<br>import { APP_INITIALIZER } from &quot;@angular/core&quot;;<br>import { bootstrapApplication } from &quot;@angular/platform-browser&quot;;<br>import { ConfigService } from &quot;./core/services/config.service&quot;;<br><br>  export function initConfig(appConfig: ConfigService) {<br>    return () =&gt; appConfig.setConfig();<br>  }<br><br>bootstrapApplication(App, {<br>  providers: [<br>    provideHttpClient(),<br>    {<br>      provide: APP_INITIALIZER,<br>      useFactory: initConfig,<br>      multi: true,<br>      deps: [ConfigService],<br>    },<br>  ],<br>});</pre><p><strong>1.4 - </strong>Now, consuming it in your component is a piece of cake!</p><pre>import { Component, inject } from &#39;@angular/core&#39;;<br>import { CommonModule } from &#39;@angular/common&#39;;<br>import { RouterOutlet } from &#39;@angular/router&#39;;<br>import { ConfigService } from &#39;../util/config.service&#39;;<br><br>@Component({<br>  selector: &#39;app-root&#39;,<br>  standalone: true,<br>  imports: [CommonModule, RouterOutlet],<br>  templateUrl: &#39;./app.component.html&#39;,<br>  //Note: We don&#39;t need to provide it at providers, because we already<br>  //provided on our application<br>  styleUrl: &#39;./app.component.scss&#39;,<br>})<br>export class AppComponent {<br>  //Note: this component is using standalone, for ngModules just import on module providers<br>  configService = inject(ConfigService);<br><br>  apiUrl = this.configService.readConfig().API_URL;<br><br>  constructor() {<br>    console.log(this.configService.readConfig().API_URL);<br>  }<br>}</pre><h3><strong>2 - Nginx config file</strong></h3><p>At the project’s root, we create a simple configuration file for serving the assets. <em>Note: Feel free to include your configurations.</em></p><pre>server {<br>  listen 80;<br><br>  gzip on;<br>  gzip_http_version 1.1;<br>  gzip_disable      &quot;MSIE [1-6]\.&quot;;<br>  gzip_min_length   256;<br>  gzip_vary         on;<br>  gzip_proxied      expired no-cache no-store private auth;<br>  gzip_types        text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;<br>  gzip_comp_level   9;<br>  client_max_body_size 5M;<br>  proxy_read_timeout 200s;<br><br>  location / {<br>    include /etc/nginx/mime.types;<br>    root /usr/share/nginx/html;<br>    add_header Cache-Control &quot;public, max-age=1M&quot;;<br>    try_files $uri $uri/ /index.html =404;<br>  }<br><br>  location /healthcheck {<br>        access_log off;<br>        add_header &#39;Content-Type&#39; &#39;text/plain&#39;;<br>        return 200 &quot;Healthy\n&quot;;<br>    <br>  }<br>}</pre><h3>3 - Docker</h3><p>Let’s containerize our application by creating the Dockerfile at the root of our project, inside of it we have all the steps for building our application.</p><pre># Use official node image as the base image<br>FROM node:lts as build<br><br>ADD ./package.json /tmp/package.json<br>RUN cd /tmp &amp;&amp; npm install<br>RUN mkdir -p /usr/local/app &amp;&amp; cp -a /tmp/node_modules /usr/local/app/<br><br>WORKDIR /usr/local/app<br><br># Add the source code from the app to the container<br>COPY ./ /usr/local/app/<br><br># Generate the build of the application<br>RUN npm run build<br><br># Stage 2: Serve app with nginx server<br># Use official nginx image as the base image<br>FROM nginx:latest<br><br># Copy the build output to replace the default nginx contents.<br>COPY --from=build /usr/local/app/dist/build/browser /usr/share/nginx/html<br><br># This line is IMPORTANT, we will breakdown it on a minute.<br>COPY ./entrypoint.sh /usr/local/app/entrypoint.sh<br><br># Copy the nginx conf that we created to the container<br>COPY ./nginx.conf  /etc/nginx/conf.d/default.conf<br><br># Expose ports<br>EXPOSE 80 443 6006 4200<br><br>RUN chmod +x /usr/local/app/entrypoint.sh<br>ENTRYPOINT [ &quot;/usr/local/app/entrypoint.sh&quot; ]</pre><p>In essence, our application is currently encapsulated within a container. However, we need to guide it in using a designated app-config. Let’s presume that the machines where you are running have<strong> environment variables</strong> that convey the current environment information. To facilitate this, at the project root, we can create the entrypoint.sh This script will determine a <strong>file replacement based on the specific environment</strong> in which our application is operating.</p><p>The “Entrypoint” serves as the initial command executed when your container starts, essentially initializing the container.</p><p><em>Note: The specifics might vary for your company, but the underlying concept remains applicable and can be adapted accordingly to project requirements.</em></p><pre>#!/bin/bash -e<br><br>#Check for the ENVIRONMENT variable and replace the file based on that<br>if [[ $ENVIRONMENT = &quot;Dev&quot; ]]; then<br>   cp /usr/share/nginx/html/config/app-config.dev.json /usr/share/nginx/html/app-config.json<br>fi<br><br>if [[ $ENVIRONMENT = &quot;Production&quot; ]]; then<br>   cp /usr/share/nginx/html/config/app-config.prod.json /usr/share/nginx/html/app-config.json<br>fi<br><br><br><br>nginx -g &#39;daemon off;&#39; </pre><h3>4 - Running your container</h3><pre># Build the image and assign a tag to it, run it at the root folder<br>docker build . -t angular-boda<br><br># After the build finish, we can start our application and use the port 8080<br># just for testing we set the environment as production to see our BODA working<br># for testing with other value just change to ENVIRONMENT=Dev<br>docker run -p 8080:80 -e ENVIRONMENT=Production -t angular-boda</pre><p>You should be able to see the application at localhost:8080:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xlHbKNCNrgb1r5xIHpD5ig.png" /><figcaption>Angular application with Build Once Deploy Anywhere.</figcaption></figure><h3>5. Wrapping Up</h3><p>Thank you all for reading. In this article, we harnessed the power of Angular, Docker, and Nginx to craft a versatile container capable of seamless deployment across diverse environments. This not only streamlines the development process but also optimizes the efficiency of CI/CD pipelines.</p><p>Feel free to explore the complete example on <a href="https://github.com/fbzz/angular-build-once-deploy-anywhere"><em>GitHub</em></a>.</p><p>Wishing you a prosperous New Year ahead! 🎆🎆</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bf477c49668f" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Angular 17: Inject or constructor? Signals or Observables?ChangeDetection?]]></title>
            <link>https://medium.com/@fabiozuin/angular-17-inject-or-constructor-signals-or-observables-changedetection-a1b48a5479d9?source=rss-34f609eb4f1------2</link>
            <guid isPermaLink="false">https://medium.com/p/a1b48a5479d9</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[angular]]></category>
            <category><![CDATA[typescript]]></category>
            <dc:creator><![CDATA[Fabio Zuin]]></dc:creator>
            <pubDate>Tue, 12 Dec 2023 17:17:16 GMT</pubDate>
            <atom:updated>2023-12-12T17:21:21.952Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/564/0*QqCeeGEjFKePUmO9.jpg" /><figcaption>Web ❤ Signals</figcaption></figure><p>Angular evolves, and so do the approaches to creating components. Join me on a journey through a guide to component development</p><p>It has been a lengthy journey to Angular 17. While maintaining backward compatibility, the Angular team is continuously evolving the framework. Like many others, I find myself constantly contemplating what to use and when to use it. In this article, I will express my thoughts on what you should use when creating your new component.</p><h3>Signals</h3><p>Signals have been available since version 16, and they are a <strong>must-have managing state on your application</strong>. If you’re not already using Signals, it’s time to start doing so. Initially, there might be a learning curve, but it’s quite simple, and it becomes natural over time. Combined with<strong> OnPush change detection</strong>, it provides finely-tuned reactivity, performance gain, and a delightful developer experience.</p><h3>Observables</h3><p><strong>If we have Signals, why do we need observables? </strong>Keep in mind that<strong> signals handle synchronous reactivity and observables handle asynchronous reactivity</strong>, for example, HTTP requests, while providing us tools for interacting with those values (map, switchMap).</p><h3>ChangeDetection.OnPush</h3><p>First, a brief explanation of each one:<br><strong>Default</strong>: Angular triggers change detection on browser events, timers, XHRs, and promises. The system then examines each component in the component tree sequentially from top to bottom. In large systems, this can lead to performance issues.</p><p><strong>OnPush: </strong>It disables the default change detection. In brief, the component only re-renders in a few specific situations:</p><ul><li>Async pipe new values</li><li>The input reference has been altered (reference, not the value, <a href="https://developer.mozilla.org/en-US/docs/Glossary/Immutable"><strong>immutability</strong></a>).</li><li>An event originating from the component or one of it children.</li><li>Manual Trigger</li></ul><p>So, just by reading the above, do you already know? Right?</p><p>Always use ChangeDetection.OnPush, and when combined with Signals, you can elevate your component performance to another level. Furthermore, when Angular completes the implementation for full zoneless, your application will be one step closer to achieving it.</p><h3>Control Flow</h3><pre>@if (a &gt; b) {<br>  {{a}} is greater than {{b}}<br>}</pre><p>Since V17, we have the new control flow for Angular. Yes, it’s in <strong>developer preview</strong>, but it feels so natural and powerful because is exactly like js syntax. Therefore, you should be using it. However, I find myself still using the good old <strong>*ngIf</strong> directive quite often. Sometimes you just want to hide a <em>&lt;span&gt;</em>, and I think that’s still easier than writing three lines. <strong>The available blocks are @If, @for, @switch.</strong></p><h3>Inject() VS constructor()</h3><p>This decision can be challenging. I currently utilize inject(), understanding the merits and demerits of both approaches, though a detailed exploration is beyond the scope of this discussion.</p><p>In my specific situation, the preference for inject() is largely due to syntax sugar. It aligns more seamlessly with conventions in other frameworks. Despite encountering resistance from some developers (myself included initially), the transition pays off in terms of code readability. However, it&#39;s important to note that we are not entirely liberated from using constructor(). I heavily rely on it, especially for Signal effect() because they need to run in the injection context. I find it to be the most straightforward method in such scenarios.</p><h3><strong>Component for Reference:</strong></h3><pre>import {<br>  ChangeDetectionStrategy,<br>  Component,<br>  inject,<br>  signal,<br>} from &#39;@angular/core&#39;;<br>import { MsalService } from &#39;@azure/msal-angular&#39;;<br>import { UsersService } from &#39;src/app/api/users-services&#39;;<br>import { Observable } from &#39;rxjs&#39;;<br>import { AsyncPipe, DatePipe } from &#39;@angular/common&#39;;<br><br>export interface UserDetail {<br>  id: string;<br>  key: string;<br>  timestamp: string;<br>}<br><br>@Component({<br>  selector: &#39;app-users-widget&#39;,<br>  template: `&lt;div&gt;<br>    @if ((detailsList$ | async); as userData){<br>    &lt;div&gt;<br>      @for(data of userData; track data.id){<br>      &lt;div (click)=&quot;setDetails(data)&quot;&gt;<br>        {{ data.id }}<br>      &lt;/div&gt;<br>      }<br>    &lt;/div&gt;<br>    } @if (openDetail(); as openDetail){<br>    &lt;h2&gt;User Details&lt;/h2&gt;<br>    &lt;p&gt;{{ openDetail.id }}&lt;/p&gt;<br>    &lt;p&gt;{{ openDetail.key }}&lt;/p&gt;<br>    &lt;p&gt;{{ openDetail.timestamp | date : &#39;long&#39; }}&lt;/p&gt;<br>    }<br>  &lt;/div&gt; `,<br>  standalone: true,<br>  imports: [DatePipe, AsyncPipe],<br>  changeDetection: ChangeDetectionStrategy.OnPush,<br>})<br><br>export class UsersWidgetComponent {<br>  usersService = inject(UsersService);<br>  //# for private modifier<br>  #authService = inject(MsalService);<br><br>  openDetail = signal&lt;UserDetail | null&gt;(null);<br>  detailsList$: Observable&lt;Array&lt;UserDetail&gt;&gt; = new Observable();<br>  <br>  //Using the constructor instead of the ng lifecycle<br>  constructor() {<br>    this.retrieveFlowHistoryData();<br>  }<br>  <br>  retrieveFlowHistoryData() {<br>    const { username } = this.#authService.instance.getAllAccounts()[0];<br>    this.detailsList$ = this.usersService.apiFlowsHistoryGet$Json({<br>      UserName: username,<br>    });<br>  }<br><br>  setDetails(detail: UserDetail) {<br>    this.openDetail.set(detail);<br>  }<br>}</pre><h3>Wrapping Up</h3><p>Navigating the ever-evolving landscape of libraries and frameworks can be a challenging task. I trust that this article has provided you with insights into some of the latest Angular conventions. Until next time!</p><p><strong>TL;DR </strong><br><strong>✅ Standalone<br>✅ Inject<br>✅ Control Flow<br>✅ Observables<br>✅ ChangeDetection.OnPush<br>✅ Typescript private # modifier<br>✅✅ Signals<br>✅ ‘as’ for store conditional in the variable</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a1b48a5479d9" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Performance: You should keep an eye on your bundle constantly, and here is how.]]></title>
            <link>https://medium.com/@fabiozuin/performance-you-should-keep-an-eye-on-your-bundle-constantly-and-here-is-how-40f0c00a64fb?source=rss-34f609eb4f1------2</link>
            <guid isPermaLink="false">https://medium.com/p/40f0c00a64fb</guid>
            <category><![CDATA[esbuild]]></category>
            <category><![CDATA[website-performance]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[webpack]]></category>
            <dc:creator><![CDATA[Fabio Zuin]]></dc:creator>
            <pubDate>Tue, 14 Nov 2023 20:55:53 GMT</pubDate>
            <atom:updated>2023-11-14T20:56:31.025Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/584/1*YhoRDEL56pt5ZVe37ud_LA.jpeg" /><figcaption>Bundle Analyzer: It plays a key role in web development, and you should use it constantly.</figcaption></figure><p>In this article, we’re going to see the role of bundlers and bundle analyzers in modern web development.</p><p>Developers have always faced a common problem since the beginning of programming— the<strong> size of their applications.</strong> This applies to mobile, web, and desktop development. A single npm install followed by an import statement and <strong>boom</strong>… you have a new code in your application.</p><p>In the realm of JavaScript, things are a bit distinct, as we’re frequently fetching and executing new code. Just one second of download and execution can alter the entire scenario for the future of our application.</p><blockquote>Slow page load times also affect how users see and interact with your website. <a href="https://unbounce.com/page-speed-report/">Over 70% of customers</a> say that page speed impacts their likelihood to purchase. Consequently, close to half of them are less likely to buy and return to the slow website in the future.</blockquote><p>As the years passed the javascript world saw an emerging solution to ship less code: <strong>bundlers.</strong></p><blockquote>A bundler combines and packages multiple files and dependencies into a single, optimized file for efficient web deployment. It helps manage and organize code, improving performance by reducing the number of HTTP requests and optimizing resources. Popular bundlers include Webpack and Parcel.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SA1AF8fgRy5v3oV3TRH-8g.png" /><figcaption>Webpack explanation of a bundler</figcaption></figure><h3>But it’s not magic…</h3><p>Despite the awesome capabilities of bundlers, poor development decisions can lead to the delivery of <strong>unnecessary </strong>code to the client. Additionally, using <strong>outdated dependencies</strong> that lack optimization can contribute to <strong>performance issues</strong>.</p><h3>So how can we open this Pandora&#39;s box?</h3><h4><strong>Bundle analyzers</strong></h4><p>They provide the capability to visualize the composition of our bundles and identify which modules contribute significantly to the overall size. <strong>Here is how to use it in some of the most famous bundlers:</strong></p><h4>Esbuild</h4><p>1. Add the <strong>metafile </strong>option to your build.</p><pre>esbuild app.js --bundle --metafile=meta.json --outfile=out.js</pre><p>2. Enter <a href="https://esbuild.github.io/analyze">https://esbuild.github.io/analyze</a> and import the generated meta.json</p><p>3. It is an interactive graph.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Cc_KELVeG4AzDTAe_kjxdg.png" /><figcaption>Sunburst chart of esbuild bundle</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*71ykgfedWrtfxEOMpGRZPg.png" /><figcaption>Flame chart of esbuild bundle</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XVjmQbtyNDJ0F-WDDjz6Wg.png" /><figcaption>Flame chart showing commonjs/ESM.</figcaption></figure><h4>Webpack</h4><ol><li>First of all, we should install it on the project</li></ol><pre>npm install --save-dev webpack-bundle-analyzer</pre><p>2. In this case we’re going to use it as a plugin, but you can check other ways 👉 <a href="https://www.npmjs.com/package/webpack-bundle-analyzer">https://www.npmjs.com/package/webpack-bundle-analyzer</a></p><pre>const BundleAnalyzerPlugin = require(&#39;webpack-bundle-analyzer&#39;).BundleAnalyzerPlugin;<br><br>module.exports = {<br>  plugins: [<br>    new BundleAnalyzerPlugin()<br>  ]<br>}</pre><p>3. It will generate an HTML output on your folder.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/908/0*60Y3xptZOcoDZACX.gif" /><figcaption>An interactive chart for checking your webpack bundles.</figcaption></figure><h4>Vite</h4><ol><li>Just npx <a href="https://www.npmjs.com/package/vite-bundle-visualizer">https://www.npmjs.com/package/vite-bundle-visualizer</a></li></ol><pre>npx vite-bundle-visualizer <br>## or<br>npx vite-bundle-visualizer -t sunburst</pre><p>2. It will automatically open your default browser for visualizing it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vb2xEtxA2E4Zgwlw-T9HFQ.png" /><figcaption>An interactive chart for checking your vite bundle.</figcaption></figure><h3>Strategies for Improvement</h3><p>With the ability to visualize your bundles, you can apply a few strategies to enhance your application.</p><ol><li><strong>Upgrade to Newer Packages</strong>: Consider replacing older packages with newer versions to benefit from performance enhancements, bug fixes, and additional features.</li><li><strong>Reevaluate Necessity</strong>: Rethink whether the application truly requires a specific package. Eliminating unnecessary dependencies can contribute to a more streamlined and efficient codebase.</li><li><strong>Optimize Initial Bundle Size</strong>: Always strive to minimize the size of the initial bundle. Reducing unnecessary components and optimizing code can enhance the application’s loading speed and overall performance.</li></ol><h3>Wrapping up</h3><p>In this article, we delved into the pivotal role of bundlers and bundle analyzers:</p><ul><li><strong>Continuous Monitoring</strong>: Vigilantly observing bundle sizes ensures an optimal user experience.</li><li><strong>Strategies for Improvement</strong>: Upgrading packages, reassessing dependencies, and minimizing the initial bundle size are crucial for enhanced performance.</li><li><strong>Empowered Decision-Making</strong>: Visualizing and optimizing bundles empower informed decisions, leading to a faster and more efficient web application.</li></ul><p>I hope this article provides valuable insights! If your bundler isn’t mentioned, there’s likely a bundle analyzer available for it. See you all. #peace<strong>…</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=40f0c00a64fb" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Angular: Rocking on your next interview ]]></title>
            <link>https://medium.com/@fabiozuin/angular-rocking-on-your-next-interview-99b50a9666af?source=rss-34f609eb4f1------2</link>
            <guid isPermaLink="false">https://medium.com/p/99b50a9666af</guid>
            <category><![CDATA[rxjs]]></category>
            <category><![CDATA[angular]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[typescript]]></category>
            <dc:creator><![CDATA[Fabio Zuin]]></dc:creator>
            <pubDate>Mon, 13 Nov 2023 17:02:15 GMT</pubDate>
            <atom:updated>2023-11-14T09:27:48.018Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*4w7DpZhbRLaaHavwY1ar1w.jpeg" /></figure><p><em>What are the most common angular interview questions?</em></p><p>As time passes, the IT sector becomes increasingly competitive. It is now common to see junior-level job openings with numerous applications. I have noticed that companies are increasingly hiring medium and senior-level engineers.</p><p>Therefore, it is important to be well-prepared for any opportunity that comes your way.</p><p>If a company is hiring for a specific framework, there is a high likelihood that part of the interview will focus on that particular aspect.</p><h4>With all that said…</h4><p>Angular is a well-known framework with a steep learning curve. However, once mastered, its countless benefits can significantly increase productivity. In the past, when conducting interviews, I would use three different levels of questions: <strong>beginner, intermediate, and advanced</strong>.</p><p><em>I often prefer home assignments, followed by an interview to understand the developer’s true skill level.</em></p><p>In the examples below, you will find concise explanations along with sources/references for further study!</p><h3>1. Beginner</h3><h4>1.1. What is a directive?</h4><p><strong>Answer: </strong>Directive is a way of attaching <strong>custom behavior</strong> for existing DOM elements.</p><p><a href="https://angular.io/api/core/Directive">Angular</a></p><h4>1.2. What is the difference between a component and a directive?</h4><p><strong>Answer:</strong> A directive is utilized to add supplementary behavior to an existing DOM element. In addition, <strong>Angular components are a subset of directives</strong>. They are always associated with a template and are specifically designed to create reusable UI blocks.</p><ul><li><a href="https://angular.io/api/core/Directive">Angular</a></li><li><a href="https://github.com/angular/angular/blob/3cf18bb6f2798020cbe8633fae79f920cf98816b/packages/core/src/metadata/directives.ts#L534">angular/packages/core/src/metadata/directives.ts at 3cf18bb6f2798020cbe8633fae79f920cf98816b · angular/angular</a></li></ul><h4>1.3. What is an Angular pipe? Can you give me an example of one?</h4><p><strong>Answer:</strong> <strong>Pipes </strong>are optimized functions used in templates to transform data. The <strong>AsyncPipe</strong> is employed to subscribe and unsubscribe from an asynchronous source, while the <strong>CurrencyPipe </strong>is used to transform a given value into currency.</p><p><a href="https://angular.dev/guide/pipes">Angular</a></p><h4>1.4. How to create a component using the Angular-cli?</h4><p><strong>Answer:</strong></p><pre># shortHand<br>ng g c example<br># complete<br>ng generate component example </pre><p><a href="https://angular.dev/tools/cli/schematics">Angular</a></p><h4>1.5. Angular is an SPA framework? If yes, what is a SPA?</h4><p><strong>Answer:</strong> Yes, in a Single Page Application (SPA), all functions of your application are contained within a single HTML page. As users navigate through your application, <strong>the browser only needs to render the relevant sections</strong>, avoiding the need to load an entirely new page.</p><p><a href="https://angular.dev/guide/routing/router-tutorial#">Angular</a></p><h4>1.6. What is a NgModule?</h4><p>Answer: <strong>NgModules organizes components, directives, and pipes into functional blocks</strong>, addressing specific features or business domains. They also integrate services, which can be internally developed or sourced externally, like the Angular router and HTTP client. We can also import other modules, and we can even set which components/directives/pipes this module will export.</p><p><a href="https://angular.dev/guide/ngmodules">Angular</a></p><h4>1.7. What is a standalone component?</h4><p><strong>Answer:</strong> Standalone components directly import other components, directives, and pipes used in their templates, basically a standalone component is a <strong>self-contained module</strong> and can be used in other components or modules.</p><p><a href="https://angular.dev/guide/components/importing#">Angular</a></p><h4>1.8. Can we use standalone components inside NgModule?</h4><p><strong>Answer:</strong> Yes, just add them to the import array.</p><p><a href="https://angular.io/guide/standalone-components">Angular</a></p><h4>1.9. What is a typescript decorator? Can you give an example of an Angular decorator?</h4><p><strong>Answer:</strong> A TypeScript decorator is a way to add extra features or modify a class, method, or property with a special label like<strong> @Component an Angular decorator.</strong></p><p><a href="https://www.typescriptlang.org/docs/handbook/decorators.html">Documentation - Decorators</a></p><h4>1.10. What is an Rxjs Observable? What is the main difference between a Promise and an Observable?</h4><p><strong>Answer</strong>: Observables are functions utilized to encapsulate data streams. The values of this observable are consumed only when there is a subscriber.<strong> It’s closely related to the Observer pattern in design patterns.</strong></p><p><strong>Both are used to handle asynchronous events</strong>. The most significant difference is that <strong>promises deal with one async event at a time</strong>, while observables can handle a sequence of async events over a period of time.</p><ul><li><em>Note: There are a bunch of differences between them, take some time to read about them.</em></li></ul><ul><li><a href="https://www.syncfusion.com/blogs/post/angular-promises-vs-observables.aspx">Angular Promises Versus Observables</a></li><li><a href="https://blog.bitsrc.io/promises-vs-observables-674f4bc8ca5e">What is the Difference Between Promises and Observables?</a></li></ul><h4>1.11. What is the difference between a Subject and a BehaviourSubject?</h4><p>Answer: Essentially, when we subscribe to a subject, we receive the values emitted after the subscription. In contrast, with a BehaviorSubject, when we subscribe to it, we receive the latest value of the source right at the moment of subscription.</p><p><a href="https://www.learnrxjs.io/learn-rxjs/subjects/behaviorsubject">BehaviorSubject</a></p><h4>1.12. What is the component lifecycle? Can you give 3 examples?</h4><p>Answer: A component’s <strong>lifecycle</strong> is the<strong> sequence of steps</strong> that happen between the component’s creation and its destruction.</p><p>ngOnInit(), ngOnChanges() &amp; ngOnDestroy()</p><p><a href="https://angular.dev/guide/components/lifecycle">Lifecycle * Angular</a></p><h4>1.13. What are the available types of compilations in Angular? And what is the difference between them?</h4><p>Answer: <strong>JIT</strong> (Just-in-Time) and <strong>AOT </strong>(Ahead-of-Time)</p><p><strong>JIT</strong>: Compile your application in the <strong>browser at runtime</strong>.</p><p><strong>AOT</strong>: Compile your application at <strong>build time</strong>.</p><p><a href="https://angular.dev/tools/cli/aot-compiler#choosing-a-compiler">Angular</a></p><h4>1.14. What are the available change detections in Angular? And what are the differences between them?</h4><p><strong>Answer:</strong> <strong>Default </strong>and <strong>OnPush</strong></p><p><strong>Default</strong>: The default strategy initiates change detection for various events such as DOM events, timers, promises, XHR, and observables. As a result, whenever there is a change in our application, change detection runs on all components to ensure the view is updated.</p><p><strong>OnPush: </strong>Utilizing the OnPush strategy, Angular initiates a change detection cycle for a component and its children solely upon changes in the component’s input properties or triggered events. This approach enhances performance, albeit at the cost of introducing some additional complexity to the component code.</p><p><a href="https://angular.dev/guide/components/advanced-configuration#changedetectionstrategy">Angular</a></p><h4>1.15. The developer can trigger the change detection manually? If so, how?</h4><p>Answer: Injecting the <strong>ChangeDetectionRef</strong>, and calling <strong>markForCheck()</strong> or <strong>detectChanges()</strong></p><h4>1.16. What is lazy loading? And how can we achieve it?</h4><p><strong>Answer: </strong>By default, all NgModules are eagerly loaded. Lazy loading, on the other hand, is a design pattern that <strong>loads modules or components as needed</strong>. It helps to keep the <strong>initial bundle as small as possible</strong>, and we can take advantage of it with NgModules and standalone components, just by using:<br><strong>loadChildren()on routes for NgModules</strong></p><p><strong>loadComponent() on routes for standalone components</strong></p><ul><li><a href="https://angular.io/guide/standalone-components">Angular</a></li><li><a href="https://angular.dev/guide/ngmodules/lazy-loading">Angular</a></li></ul><h4>BONUS: What are Signals?</h4><p><strong>Answer: </strong>A signal serves as an encapsulation for a <strong>value, signaling interested consumers when the underlying value undergoes changes</strong>. Signals can encompass a wide range of values, from basic primitives to intricate data structures. This enables something called fine-grained update/reactivity, which enables us to optimize the render/Dev experience.</p><p><a href="https://angular.dev/guide/signals#writable-signals">Angular</a></p><h3>2. Intermediary</h3><h4>2.1. Are you familiar with content projection? Can you describe it?</h4><p><strong>Answer: </strong>Yes, content projection is employed often using &lt;ng-container&gt; to create a component that acts as a container for content. When using a component with &lt;ng-content&gt;, any children of the component’s host element are rendered or projected to the specified location.</p><pre>&lt;!--Component1--&gt;<br>&lt;div id=&quot;component1&quot;&gt;&lt;ng-content&gt;&lt;/ng-content&gt;&lt;/div&gt;<br><br>&lt;!--Component2--&gt;<br>&lt;app-component1&gt;<br>&lt;span id=&quot;component2&quot;&gt;HELLO&lt;/span&gt;<br>&lt;/app-component1&gt;<br><br>&lt;!--Rendered--&gt;<br>&lt;div id=&quot;component1&quot;&gt;<br>&lt;span id=&quot;component2&quot;&gt;Hello&lt;/span&gt;<br>&lt;/div&gt;</pre><p><a href="https://angular.dev/guide/components/content-projection#">Angular</a></p><h4>2.2. How can we change easily the currency of the CurrencyPipe</h4><p><strong>Answer: </strong>The<strong> first parameter of the pipe should be the currency</strong> you want to display, at the template.</p><p>&lt;div&gt;{{money | <a href="https://angular.io/api/common/CurrencyPipe">currency</a>:’EUR’}}&lt;/div&gt;</p><p><a href="https://angular.dev/api/common/CurrencyPipe">Angular</a></p><h4>2.3. I want to create my own pipe extending some of the <a href="https://angular.dev/guide/pipes#built-in-pipes">Built-in pipes</a>, how?</h4><p><strong>Answer:</strong> Use Typescript extends with the class of the <strong>Pipe </strong>that you want, for example, DatePipe,<strong> and implement the PipeTransform interface</strong>.</p><p>export class DaylightDatePipe extends DatePipe implements PipeTransform</p><p><a href="https://angular.io/guide/pipes-custom-data-trans">Angular</a></p><h4>2.4. What is a polyfill?</h4><p><strong>Answer:</strong> A polyfill is a code snippet, typically written in JavaScript for web applications, <strong>that serves to enable modern functionality on older browsers </strong>lacking native support. For instance, a few years ago, Internet Explorer lacked certain native APIs, so we used polyfills to replicate that functionality.</p><p><a href="https://developer.mozilla.org/en-US/docs/Glossary/Polyfill">Polyfill - MDN Web Docs Glossary: Definitions of Web-related terms | MDN</a></p><h4>2.5. Why should you unsubscribe from Observables?</h4><p><strong>Answer: </strong>Not unsubscribing can lead to <strong>data leaks</strong>, which, in turn, can result in <strong>performance issues</strong>.</p><p><a href="https://angular.dev/guide/pipes/unwrapping-data-observables#">Angular</a></p><h4>2.6. How to unsubscribe from Observables?</h4><p><strong>Answer: </strong>There are several ways to unsubscribe. We can do it manually by calling the unsubscribe() method. Alternatively, we can use the <strong>async pipe</strong>, which automatically unsubscribes from the observable. Another option is to use the takeUntil() RxJS operator, which completes the output Observable when a specified Observable emits a value. This is often combined with a subjecttriggering for example, in the ngOnDestroy()</p><p><a href="https://angular.dev/guide/pipes/unwrapping-data-observables#">Angular</a></p><h4>2.7. What is a Hot and a Cold Observable?</h4><p><strong>Answer:</strong> A <strong>hot observable</strong> can begin even if no observers are currently subscribed and can persist after the last observer has unsubscribed. In contrast, a <strong>cold observable</strong> typically initiates only upon subscription and concludes when the subscription terminates. It can execute a process separately for each subscribed observer.</p><p><a href="https://www.christianfindlay.com/blog/rx-hot-vs-cold#:~:text=A%20hot%20observable%20can%20start,process%20for%20each%20subscribed%20observer">Reactive Programming: Hot Vs. Cold Observables</a></p><h4>2.8. Difference between template-driven and Reactive Forms?</h4><p><strong>Answer: </strong>Reactive forms offer developers greater control over form elements, <strong>facilitating customization of form behavior and validations</strong>. They are also more convenient <strong>for unit testing</strong>, thanks to <strong>their reactive programming mode</strong>l, which allows more precise control over form data.</p><p>On the other hand, <strong>template-driven forms</strong> are a <strong>quick </strong>and efficient option for creating<strong> simple forms with minimal code</strong>. They are well-suited for straightforward use cases that do not demand extensive customization or complexity.</p><p><a href="https://angular.dev/guide/forms">Angular</a></p><h4>2.9. Are you familiar with Strictly typed Forms? What is the advantage of using it?</h4><p><strong>Answer: </strong>Yes, enabling the developer to build more complex forms, better autocomplete in IDEs, and more predictability.</p><p><a href="https://angular.dev/guide/forms/typed-forms">Angular</a></p><h4>2.10. How can we generate Observables from Event sources?</h4><p>Answer: Using the fromEvent()function from <strong>Rxjs</strong>.</p><p><a href="https://www.learnrxjs.io/learn-rxjs/operators/creation/fromevent">fromEvent</a></p><h3>3. Advanced</h3><h4>3.1. How can we use the *ngTemplateOutlet directive?</h4><p><strong>Answer: </strong>*ngTemplateOutlet <strong>directive </strong>in Angular allows us to have a more <strong>complex content projection</strong>. While it can be applied to any HTML element, it is often paired with &lt;ng-container&gt; for <strong>optimal use</strong>.</p><p>With *ngTemplateOutlet, you can define <strong>reusable and customizable templates that leverage variables within their scope</strong>. For instance, consider the following example:</p><pre>&lt;!--HTML from Component1, the selector is app-component1 --&gt;<br>&lt;ng-container *ngTemplateOutlet=&quot;customTemplate; context: { data: myData }&quot;&gt;&lt;/ng-container&gt;<br><br>&lt;!--HTML from Component2--&gt;<br>&lt;app-component1&gt;<br>&lt;ng-template #customTemplate let-data&gt;<br>  &lt;div&gt;<br>    &lt;p&gt;{{ data.property1 }}&lt;/p&gt;<br>    &lt;p&gt;{{ data.property2 }}&lt;/p&gt;<br>  &lt;/div&gt;<br>&lt;/ng-template&gt;<br>&lt;/app-component1&gt;</pre><p><a href="https://angular.dev/api/core/ng-container#mat-tab-content-88-0">Angular</a></p><h4>3.2 What are Angular elements? Can you give a user case for it?</h4><p><strong>Answer: </strong>Angular elements are essentially Angular components encapsulated as custom elements, also known as <strong>Web Components</strong>. These adhere to a web standard that defines the creation of new HTML elements in a manner <strong>independent of any specific framework</strong>. One practical use case for Angular elements is the creation of a library intended for clients who do not use Angular.</p><p>By packaging Angular components as <strong>custom elements</strong>, the resulting library becomes<strong> framework-agnostic</strong>. This means that clients utilizing different frontend frameworks or even plain HTML can seamlessly incorporate and benefit from the functionality provided by the Angular components. <strong>This approach enhances the reusability and interoperability of Angular components across diverse projects and technology stacks</strong></p><p><a href="https://angular.dev/guide/elements">Angular</a></p><h4>3.3. How can we use SSR/SSG on Angular?</h4><p><strong>Answer: </strong>There are some steps to it, first of all, we should add SSR package to our project ng add @angular/ssr, we should make our application be served from the <strong>server.ts</strong> and migrate our component to be <strong>server-compatible</strong> because some of the browser’s <strong>APIs are not available</strong> on the server.</p><p><em>Note: of course, this is a big simplification of the process.</em></p><p><a href="https://angular.dev/guide/prerendering">Angular</a></p><h4>3.4. What is the difference between SSR and SSG?</h4><p><strong>Answer:</strong></p><p><strong>SSR: </strong>involves generating HTML on the <strong>server dynamically for each request</strong>, and is well-suited for applications with<strong> real-time or frequently changing data</strong> because the server generates content dynamically <strong>for each request</strong>.</p><p><strong>SSG: </strong>involves pre-generating HTML during the build phase of the application which can be served <strong>statically to clients</strong>, it can offer faster <strong>initial page loads</strong> as the HTML is already available <strong>and doesn’t need to be generated on the server for each request</strong>. However, if <strong>content changes</strong>, the application needs to be <strong>rebuilt </strong>to reflect those changes, making SSG less suitable for real-time or frequently updated content.</p><p><a href="https://angular.dev/guide/prerendering">Angular</a></p><h4>3.5. What is the difference between @ViewChild and @ViewChildren?</h4><p><strong>Answer:</strong> @Viewchild()will retrieve the <strong>first element</strong> matching the selector while @ViewChildren() will return a <strong>query list of all elements</strong> matching the given selector.</p><p><a href="https://angular.dev/guide/components/queries#view-queries">Angular</a></p><h3>Wrapping Up</h3><p>The first version of Angular 2 was published back in 2016. Therefore, it is not possible to cover all the points about it in just one post, this open a possibility for a part 2, right?😉</p><p>I hope this article will help you guys to rock the interviews!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/553/0*tRrgqGny8w7QUG9z.jpg" /><figcaption>This is my feeling when I receive a clap.</figcaption></figure><p>Let me know if you enjoyed it and please share some insight ❤… #peace</p><p>#angular #typescript #rxjs #interview #javascript</p><p><em>Thanks to </em><a href="https://medium.com/u/9b0a2aa34996"><em>Sai</em></a><em> for the suggestion of the article!</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=99b50a9666af" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Angular: Why You Should Start Using @Input() to Read Angular Route Parameters]]></title>
            <link>https://medium.com/@fabiozuin/angular-why-you-should-starts-use-input-to-read-angular-route-parameters-1005d5a4f934?source=rss-34f609eb4f1------2</link>
            <guid isPermaLink="false">https://medium.com/p/1005d5a4f934</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[rxjs]]></category>
            <category><![CDATA[angular]]></category>
            <category><![CDATA[typescript]]></category>
            <dc:creator><![CDATA[Fabio Zuin]]></dc:creator>
            <pubDate>Fri, 10 Nov 2023 19:56:46 GMT</pubDate>
            <atom:updated>2023-11-10T19:58:42.894Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*XVwfd1n2I_YAw0dEHHumVA.jpeg" /><figcaption>LIFE IS MADE OF CHOICES</figcaption></figure><p>Since the beginning of Angular, I have consistently enjoyed the process of creating routes. It is simple, straightforward, and well-structured. It’s quite easy to create your initial route and incorporate parameters, but the experience of retrieving those parameters in the component has always been the same, a bit unecessary let’s say.</p><pre>import { Component, OnInit, inject } from &#39;@angular/core&#39;;<br>import { ActivatedRoute } from &#39;@angular/router&#39;;<br><br>@Component({<br>  selector: &#39;page-details&#39;,<br>  template: ` &lt;div&gt;<br>    &lt;h1&gt;{{ pageId }}&lt;/h1&gt;<br>  &lt;/div&gt;`,<br>  standalone: true <br>})<br><br>export class DetailsComponent implements OnInit {<br>  pageId: number = 0;<br>  private route = inject(ActivatedRoute);<br>  ngOnInit(): void {<br>    this.pageId = Number(this.route.snapshot.paramMap.get(&#39;pageId&#39;));<br>    // OR<br>    this.route.params.subscribe((params) =&gt; {<br>      this.pageId = Number(params[&#39;pageId&#39;]);<br>      //Do something with the other pageId<br>    });<br>  }<br>}</pre><p>Cons of those approaches:</p><ol><li>It is always necessary to implement the OnInit lifecycle.</li><li>Ensure the type of the parameter.</li><li>Inject the ActivatedRoute service.</li></ol><h3>Presenting… bindToComponentInputs</h3><p>Since <strong>Angular 16</strong>, we have a new method for retrieving the parameters. First and foremost, you should be aware of the type of the bootstrapping that your application is using.</p><h4>Standalone</h4><p><strong>main.ts</strong></p><pre>import { bootstrapApplication } from &#39;@angular/platform-browser&#39;;<br>import { appConfig } from &#39;./app/app.config&#39;;<br>import { AppComponent } from &#39;./app/app.component&#39;;<br><br><br>bootstrapApplication(AppComponent, appConfig).catch((err) =&gt; console.error(err)); </pre><p>So in <strong>app.config.ts </strong>(<em>Only generated when using the </em><em>--standalone option of the ng new…)</em></p><pre>import { ApplicationConfig } from &#39;@angular/core&#39;;<br>import { provideRouter, withComponentInputBinding } from &#39;@angular/router&#39;;<br><br>const routes: Routes = [<br>  { path: &#39;/:pageId/:viewName&#39;, component: DetailComponent },<br>];<br><br>export const appConfig: ApplicationConfig = {<br>  providers: [<br>    provideRouter(routes, withComponentInputBinding())<br>  ]<br>};</pre><p>In the provideRouter we add the <strong>withComponentInputBinding()</strong>…</p><h4>NgModule</h4><p><strong>main.ts</strong></p><pre>import { enableProdMode } from &#39;@angular/core&#39;;<br>import { platformBrowserDynamic } from &#39;@angular/platform-browser-dynamic&#39;;<br><br>import { AppModule } from &#39;./app/app.module&#39;;<br>import { environment } from &#39;./environments/environment&#39;;<br><br>if (environment.production) {<br>  enableProdMode();<br>}<br><br>platformBrowserDynamic().bootstrapModule(AppModule)<br>  .catch(err =&gt; console.error(err));</pre><p>In almost all projects the <strong>AppModule(that I’m not showing here)</strong>will be importing the <strong>app-routing.module.ts, </strong>that should look something like<strong>:</strong></p><pre>import { NgModule } from &#39;@angular/core&#39;;<br>import { RouterModule, Routes } from &#39;@angular/router&#39;;<br>import { DetailComponent } from &#39;./feature/pages/detail/detail.component&#39;;;<br><br>const routes: Routes = [<br>  { path: &#39;:pageId/:viewName&#39;, component: DetailComponent },<br>];<br><br>@NgModule({<br>  imports: [RouterModule.forRoot(routes, { bindToComponentInputs: true })],<br>  exports: [RouterModule],<br>})<br>export class AppRoutingModule {}</pre><p>In the <strong>RouterModule.forRoot</strong> we add to the second parameter the <strong>object </strong>with the property <strong>bindToComponentInputs</strong></p><h4>And now… the grand finale…</h4><pre>import { Component, OnInit, inject } from &#39;@angular/core&#39;;<br>import { ActivatedRoute } from &#39;@angular/router&#39;;<br><br>@Component({<br>  selector: &#39;page-details&#39;,<br>  template: ` &lt;div&gt;<br>    &lt;h1&gt;{{ pageId }}&lt;/h1&gt;<br>  &lt;/div&gt;`,<br>  standalone: true //Depends on your bootstrap type...<br>})<br><br>export class DetailsComponent implements OnInit {<br>  @Input({transform: numberAttribute}) pageId = 0;<br>  @Input(&quot;viewName&quot;) pageName = &quot;&quot;;<br><br>  ngOnInit(): void {<br>   console.log(this.pageId); //Logs a number<br>   console.log(this.pageName); //Logs a string<br>  }<br>}</pre><p>So, in the final code, we achieve more with less:</p><ul><li>There’s no longer a need for the ActivatedRoute service.</li><li>We can ensure the type of the input, and we can even transform it using the new transform function inside the @Input decorator. (It’s available in the 16.1.0 version)</li><li>In cases where we don’t need an ngOnInit.</li></ul><h3>Wrapping Up</h3><p>Now, after Angular 16, I recommend that almost all components relying on routing parameters retrieve them from input properties. It’s very clean to understand and ensures more safety with less code.</p><p>That’s all, folks! #peace.</p><p>#typescript #angular #javascript #rxjs</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1005d5a4f934" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Angular Control Flow… TRY IT, NOW!]]></title>
            <link>https://medium.com/@fabiozuin/angular-control-flow-try-it-now-927df7ad616f?source=rss-34f609eb4f1------2</link>
            <guid isPermaLink="false">https://medium.com/p/927df7ad616f</guid>
            <category><![CDATA[developer]]></category>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[angular]]></category>
            <category><![CDATA[js]]></category>
            <dc:creator><![CDATA[Fabio Zuin]]></dc:creator>
            <pubDate>Wed, 08 Nov 2023 16:26:17 GMT</pubDate>
            <atom:updated>2023-11-08T16:32:13.846Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/750/1*QELZRmuDjxGDlwOA-UXYTw.jpeg" /><figcaption>Things moves… fast…</figcaption></figure><p>I have been working with Angular since the days of AngularJS, and I must say that when you work with other frameworks that use JSX, sometimes developing in Angular HTML and directives can be a quite “different experience”.</p><p>I’ve been keeping an eye on the RFC (Request for Comments) about the new control flow, but after watching the Angular keynote, I became really interested in trying it out. So today, I updated my project to Angular 17.0.0.</p><p>By fate, I’m currently working on creating a searchable select with options fetched from the server, that’s a great component for testing it.<br>Let’s take a look at the first version. In this initial version, I didn’t include a loader or empty feedback for the user, and I was using the built-in directives. Here’s the code snippet:</p><pre>&lt;div [formGroup]=&quot;form&quot; class=&quot;configuration-select&quot; #selectInput&gt;<br>  &lt;app-input<br>    [required]=&quot;required&quot;<br>    [formControlName]=&quot;key&quot;<br>    (focusEvent)=&quot;displayOptions = true&quot;<br>  &gt;&lt;/app-input&gt;<br>  &lt;div<br>    class=&quot;select-options&quot;<br>    [style.width.px]=&quot;searchSize$.asObservable() | async&quot;<br>    *ngIf=&quot;displayOptions&quot;<br>    (clickOutside)=&quot;displayOptions = false&quot;<br>  &gt;<br>    &lt;span<br>      *ngFor=&quot;let option of search$ | async&quot;<br>      class=&quot;option&quot;<br>      (click)=&quot;selectOptions(option)&quot;<br>      [ngClass]=&quot;{ selected: option.text === form.controls[key].value }&quot;<br>      &gt;{{ option.text }}&lt;/span<br>    &gt;<br>  &lt;/div&gt;<br>&lt;/div&gt;</pre><p>So, what we can see here is that experienced Angular developers can easily understand what’s happening just by looking at the template directives. As I mentioned earlier, it works, but there’s room for improvement and the Angular team and community knew that.</p><p>For better clarification, here is the TypeScript code. Basically, the observable $search is responsible for the service response (in this case, it’s mocked as an array). By the way, I’m always trying to be more declarative and work with the RXJS, just by looking the ngOnInit we can understand what is happening.</p><pre>import { AfterViewInit, Component, ElementRef, HostListener, Input, OnInit, ViewChild } from &#39;@angular/core&#39;;<br>import { FormGroup } from &#39;@angular/forms&#39;;<br>import {<br>  BehaviorSubject,<br>  Observable,<br>  delay,<br>  distinctUntilChanged,<br>  finalize,<br>  mergeMap,<br>  of,<br>  startWith,<br>  tap,<br>} from &#39;rxjs&#39;;<br>import { IConfigAction } from &#39;src/app/api/dynamic-config-models&#39;;<br><br>interface Option {<br>  text: string;<br>  value: string;<br>}<br><br>@Component({<br>  selector: &#39;app-configuration-select&#39;,<br>  templateUrl: &#39;./configuration-select.component.html&#39;,<br>  styleUrls: [&#39;./configuration-select.component.scss&#39;],<br>})<br><br>/**<br> * This component will handle a state and a connection with a service, because makes much more sense to be responsible for the own call<br> */<br>export class ConfigurationSelectComponent implements OnInit, AfterViewInit {<br>  @ViewChild(&#39;selectInput&#39;) selectInput!: ElementRef;<br><br>  @Input() key = &#39;&#39;;<br>  @Input() form: FormGroup = new FormGroup({});<br>  @Input() style: &#39;DEFAULT&#39; | &#39;LINE&#39; = &#39;DEFAULT&#39;;<br>  @Input() required = false;<br>  @Input() label = &#39;&#39;;<br>  @Input() action!: IConfigAction;<br>  displayOptions = false;<br><br>  constructor() {}<br><br>  search$: Observable&lt;Option[]&gt; = new Observable();<br>  searchSize$: BehaviorSubject&lt;number&gt; = new BehaviorSubject(0);<br>  loading = false;<br><br>  @HostListener(&#39;window:resize&#39;)<br>  onResize() {<br>    this.searchSize$.next(this.selectInput.nativeElement.offsetWidth);<br>  }<br><br>  ngAfterViewInit(): void {<br>    setTimeout(() =&gt; {<br>      this.searchSize$.next(this.selectInput.nativeElement.offsetWidth);<br>    }, 0);<br>  }<br><br>  /**<br>   * Basically our entire logic happens on the ngOnInit, remember try always to achive declarative code with rxjs<br>   * It&#39;s better to understand searching for imperative code<br>   */<br>  ngOnInit(): void {<br>   this.search$ = this.form.controls[this.key].valueChanges.pipe(<br>      distinctUntilChanged(),<br>      debounceTime(200),<br>      startWith((starterValue: string) =&gt; this.requestOptions(starterValue)),<br>      tap(() =&gt; (this.loading = true)),<br>      mergeMap((value: string) =&gt; this.requestOptions(value)),<br>      finalize(() =&gt; (this.loading = false))<br>    );<br> }<br><br>  /**<br>   * Basically the endpoint call, but here we&#39;re simulating it with observables<br>   * @param searchString to send to the backend for a fuzzy search<br>   * @returns<br>   */<br>  requestOptions(searchString: string) {<br>    const options = [<br>      { text: &#39;Something&#39;, value: &#39;something&#39; },<br>      { text: &#39;new&#39;, value: &#39;new&#39; },<br>      { text: &#39;another one&#39;, value: &#39;another&#39; },<br>    ];<br><br>    const filtered = options.filter((option) =&gt; {<br>      return option.text.includes(searchString);<br>    });<br><br>    return of(filtered.length &gt; 0 ? filtered : options).pipe(<br>      delay(2000),<br>      tap(() =&gt; (this.loading = false))<br>    );<br>  }<br><br>  selectOptions(option: Option) {<br>    this.displayOptions = false;<br>    this.form.controls[this.key].setValue(option.text);<br>  }<br>}</pre><h4>Breakdown with the new Control Flow</h4><pre>&lt;div [formGroup]=&quot;form&quot; class=&quot;configuration-select&quot; #selectInput&gt;<br>  &lt;app-input [required]=&quot;true&quot; [formControlName]=&quot;key&quot; (focusEvent)=&quot;displayOptions = true&quot; /&gt;<br>  @if (displayOptions){<br>  &lt;div class=&quot;select-options&quot; [style.width.px]=&quot;searchSize$.asObservable() | async&quot;&gt;<br>    @if (loading === false &amp;&amp; (search$ | async); as searchResults){ <br>     @for (option of searchResults; track option.value){<br>     &lt;span<br>       class=&quot;option&quot;<br>       (click)=&quot;selectOptions(option)&quot;<br>       [ngClass]=&quot;{ selected: option.text === form.controls[key].value }&quot;<br>       &gt;{{ option.text }}&lt;/span&gt;<br>     }@empty {<br>     &lt;span class=&quot;option&quot;&gt;No options found&lt;/span&gt;<br>     } <br>    }@else{<br>    &lt;app-spinner /&gt;<br>    }<br>  &lt;/div&gt;<br>  }<br>&lt;/div&gt;</pre><p>By the way, I’m using the new self-closing tag feature that helps keep the code cleaner. Why did we wait so long for this?</p><h4>Highlights:</h4><ul><li>You can do more with lesscode</li><li>It feels very natural to work/view that.</li><li>It’s get way easiear to have for example a empty treatment for your lists.</li><li>It’s more optimized by default, angular maintaners says something around 30% on the @for statement</li></ul><h4>New Syntax</h4><p><strong>“@if”</strong> works like a normal <strong>“if”</strong> in any programming language, and we can even take advantage of the<strong> async pipe</strong> to work with observables, similar to the good old <strong>*ngIf</strong>. Another significant difference here is that we can now use the <strong>“@elseif”</strong> and even the <strong>“@else” </strong>block.</p><p><strong>“@for” </strong>now replaces <strong>*ngFor</strong> and looks quite similar to TypeScript’s for loop. The difference now is that we need to use a “<strong>track</strong>” (similar to the old <strong>trackBy, but required</strong>), which improves the performance of rendered lists. Another valuable addition is the “<strong>@empty</strong>” block, which allows us to render something when the list is empty, eliminating the need for manual checks with *ngIf.</p><p>Beyond this example, we also have the “<strong>@switch</strong>” case, which behaves exactly like <strong>*ngSwitch</strong>. The main difference is that it does not require a container element to hold the condition expression or each conditional template. You can see the example below:</p><pre>@switch (condition) {<br>  @case (caseA) {<br>    Case A.<br>  }<br>  @case (caseB) {<br>    Case B.<br>  }<br>  @default {<br>    Default case.<br>  }<br>}</pre><h4>Not everything that shine is gold…</h4><p>Because it’s in developer preview, I still encounter some problems, such as formatting. Other issue that maybe it’s related to the new ESBuilder is: sometimes, when I save my HTML, it doesn’t recompile, and occasionally, I need to go to a TypeScript file and simply press CTRL + S to trigger the compiler.</p><h4>But with that said…</h4><h3>I recommend installing the new Angular version and starting development with the control flow. It feels very comfortable, and the learning curve is not too steep. It comes naturally to Angular developers and even to other developers. With this new approach, we can think differently, reduce the boilerplate, and have much more structured code in the HTML.</h3><p>The next step will be trying out ‘<strong>@defer</strong>’ which will enable us to defer some components that don’t need to be executed immediately.</p><p>And, of course, there are the new stable <strong>SIGNALS API.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/260/0*fT-fbBMKD-RqYT1j.gif" /><figcaption>POV: @if(endOfTheArticle === true)</figcaption></figure><p><strong>Stay tuned for the next… #peace</strong></p><p>#angular #typescript #rxjs #controlflow</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=927df7ad616f" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>