<?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 Kamil Maraz on Medium]]></title>
        <description><![CDATA[Stories by Kamil Maraz on Medium]]></description>
        <link>https://medium.com/@kamylko?source=rss-b6c216d24584------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*TQnb95CDL1DoMHYpryGOWA.jpeg</url>
            <title>Stories by Kamil Maraz on Medium</title>
            <link>https://medium.com/@kamylko?source=rss-b6c216d24584------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 03:52:35 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@kamylko/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[What Hell’s Kitchen Taught Me About Engineering Teams]]></title>
            <link>https://medium.com/slido-dev-blog/what-hells-kitchen-taught-me-about-engineering-teams-a64c0a712184?source=rss-b6c216d24584------2</link>
            <guid isPermaLink="false">https://medium.com/p/a64c0a712184</guid>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[engineering-management]]></category>
            <category><![CDATA[leadership]]></category>
            <category><![CDATA[team-performance]]></category>
            <category><![CDATA[systems-thinking]]></category>
            <dc:creator><![CDATA[Kamil Maraz]]></dc:creator>
            <pubDate>Mon, 09 Feb 2026 08:06:30 GMT</pubDate>
            <atom:updated>2026-02-09T09:12:13.854Z</atom:updated>
            <content:encoded><![CDATA[<p>I’ve watched every episode of <a href="https://en.wikipedia.org/wiki/Hell%27s_Kitchen_(American_TV_series)"><em>Hell’s Kitchen</em>,</a> including <a href="https://www.youtube.com/watch?v=Y3VPeVfJAG0">the raw service cuts.</a> Strip away the TV format and you’re left with a masterclass in running high-pressure, high-throughput systems. What Gordon Ramsay does in that kitchen maps surprisingly cleanly to how effective engineering teams operate. Especially product engineering at scale, like <a href="https://www.slido.com/">Slido.</a></p><p>This is about systems.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0MBM1duwKan8vaoaC8YANQ.png" /></figure><h3>One system, multiple teams, one output</h3><p>In <em>Hell’s Kitchen</em> there are usually two teams competing, but only one dining room experience. Later in the show, those teams are merged into a single group of seniors, intentionally. At that stage, individual performance matters less than whether the system can run smoothly without training wheels.</p><p>Customers never care which individual cooked which dish. They experience one system.</p><p>This mirrors engineering reality. Frontend, backend, infrastructure, data. Users experience one product. If one team optimizes locally while another lags, the whole system fails. Ramsay never evaluates teams in isolation during service. He evaluates throughput and correctness of the entire pipeline.</p><p><strong>Lesson:</strong> team success is meaningless without system success.</p><h3>Service is production</h3><p>There is no “almost done” during service. An order that is late or wrong is a failure. You cannot pause, refactor, or explain context. You ship or you fail.</p><p>Each dish is produced by multiple people at once. One person handles the protein, another the garnish, another the sauce, another the plating. Everything must land within seconds of each other, cooked to exact standards. If any single component is slightly off, the entire dish is scrapped and restarted.</p><p>This is on-call, incidents, releases, and live customer impact. Planning matters, but execution under pressure is the real test. In Ramsay’s kitchen, the multiple-hour service is 100% peak load from start to finish. From preparing garnishes to plating and cleaning the last dish. The kitchen is built to survive this sustained intensity, not ideal conditions.</p><p><strong>Lesson:</strong> design teams and processes for reality, not calm days.</p><h3>Clear contracts and zero ambiguity</h3><p>Orders are explicit. Timing, ownership, and sequencing are clear. Cooks are trained in advance: they know recipes, standards, and techniques. What they initially lack is experience operating together as a system.</p><p>When ambiguity appears, failure is immediate. A common example is plating: if no one clearly owns finishing the dish, food sits, overcooks, or goes out incomplete. “I thought you were doing it” is enough to derail the service.</p><p>This translates directly to API contracts, ownership boundaries, and responsibility clarity. In Slido terms: who owns the data shape, who owns accessibility behavior, who owns failure recovery. Ramsay enforces contracts ruthlessly because ambiguity multiplies errors under load.</p><p><strong>Lesson:</strong> unclear ownership is a defect, not a cultural issue.</p><h3>The leader guides, mentors, and enables</h3><p>Ramsay can outcook anyone in the room. He usually doesn’t, because his primary role is orchestration, prioritization, and correction. But when he <em>does</em> step in, it is intentional. He intervenes to set a standard, demonstrate the expected level, reset a broken process, or unblock the service. His involvement is deliberate and purposeful, not heroic firefighting.</p><p>The same applies to engineering leadership at Slido. Leaders contribute actively and continuously, bringing experience and output into the system. That contribution is not about taking over, but about mentoring, coaching, modeling quality, and making gaps visible. Leadership is not stepping away from the work; it is stepping into it at the right moments to strengthen the system and enable others to grow.</p><p><strong>Lesson:</strong> effective leaders intervene deliberately. To teach, align, and stabilize, so the system can operate independently at a higher level.</p><h3>Fast, brutal feedback loops</h3><p>Mistakes are surfaced immediately and publicly. Not because of cruelty, but because latency hides defects. A dish sent back ten minutes later is far worse than an error caught instantly on the pass.</p><p>This maps to strict CI, fast alerts, explicit code review, and unambiguous postmortems. Gentle, delayed feedback feels human but scales poorly. Systems need fast, high-signal correction.</p><p><strong>Lesson:</strong> kindness that delays truth degrades quality.</p><h3>Single source of truth</h3><p>Ramsay knows every order, every table, and every state change. Not by memory alone, but because the system makes state visible. In the kitchen, communication is constant: chefs call out what they are doing, confirm tasks, and alert each other to timing or mistakes. Ramsay’s yelling enforces this flow. If someone stops communicating, it immediately becomes a problem.</p><p>Engineering equivalents are dashboards, logs, metrics, and shared visibility of system health. The goal is the same: the system must communicate clearly without relying on verbal status updates.</p><p><strong>Lesson:</strong> if the system requires leaders to ask for updates, state is not observable; constant, reliable communication is essential.</p><h3>Discipline before creativity</h3><p>Creativity is allowed only after execution is reliable. Basic dishes must be flawless before improvisation is tolerated. Innovation built on shaky fundamentals collapses under load.</p><p>Engineering is no different. Refactors, experiments, and innovation only work on top of reliable basics: tests, accessibility, deployment safety, and clear ownership.</p><p><strong>Lesson:</strong> freedom without discipline increases entropy.</p><h3>Teams are designed for uneven skill</h3><p>Ramsay assumes people will fail. Systems are designed to catch, correct, and contain mistakes before they reach customers. Weak performers only collapse the kitchen if the system allows them to.</p><p>Strong engineering systems work the same way. Processes and tooling compensate for natural variation in human performance.</p><p><strong>Lesson:</strong> good systems absorb human variance; bad systems amplify it.</p><h3>Final takeaway</h3><p><em>Hell’s Kitchen</em> demonstrates operation of a complex system under constant pressure with no tolerance for excuses.</p><p>The real inspiration for engineering teams is simple:</p><ul><li>clarity over comfort</li><li>systems over individuals</li><li>execution over theory</li></ul><p>That is how you scale without chaos.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a64c0a712184" width="1" height="1" alt=""><hr><p><a href="https://medium.com/slido-dev-blog/what-hells-kitchen-taught-me-about-engineering-teams-a64c0a712184">What Hell’s Kitchen Taught Me About Engineering Teams</a> was originally published in <a href="https://medium.com/slido-dev-blog">Slido developers blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Transpile debug and other npm packages to es5]]></title>
            <link>https://medium.com/slido-dev-blog/transpile-debug-and-other-npm-packages-to-es5-5acd87a087c2?source=rss-b6c216d24584------2</link>
            <guid isPermaLink="false">https://medium.com/p/5acd87a087c2</guid>
            <category><![CDATA[tutorial]]></category>
            <category><![CDATA[best-practices]]></category>
            <category><![CDATA[es5]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[webpack]]></category>
            <dc:creator><![CDATA[Kamil Maraz]]></dc:creator>
            <pubDate>Sun, 13 Sep 2020 20:33:59 GMT</pubDate>
            <atom:updated>2020-09-13T20:33:59.166Z</atom:updated>
            <content:encoded><![CDATA[<h3>Transpile “debug” and other npm packages to es5</h3><h4>You have tried everything, but nothing really works! But why? — you may ask yourself.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2eRJMTe3y9R2fp7sUMzw2Q.jpeg" /><figcaption><a href="https://unsplash.com/photos/xekxE_VR0Ec">https://unsplash.com/photos/8KfCR12oeUM</a>, Thanks to Markus Spiske.</figcaption></figure><p>As for front-end developers, we are often forced by a business strategy to support archaic web browsers. IE11 et al. immediately comes to mind. We are using a lot of 3rd party vendors and are heavily dependent on it. But what if package maintainers decide to simplify their continuous integration (CI) pipelines? Or build processes and stop supporting es5?</p><p>Developers run amok. Just a <a href="https://github.com/visionmedia/debug/issues?q=ie11">quick search of github issues shows us</a>, that we often struggle to come up with proper solutions for this problem. Let’s dive into the solution that works for us.</p><blockquote>Note: This is certainly not the only way. Also, we are using Webpack.</blockquote><h4>TL;DR</h4><p>If you’d like to see a working example, here it is:</p><p><a href="https://github.com/kmaraz/debug-to-es5">kmaraz/debug-to-es5</a></p><pre>git clone <a href="https://github.com/kmaraz/debug-to-es5">https://github.com/kmaraz/debug-to-es5</a><br>npm install<br>npm run build</pre><h4>A little bit more</h4><p>If you’ve scrolled here, probably you want to understand how it works, so read on.</p><p>First, we need to configure babel-loader:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b8522ac5100c70c0ea1150f39d9facc0/href">https://medium.com/media/b8522ac5100c70c0ea1150f39d9facc0/href</a></iframe><p>That’s it, very easy. Now we move on to use the loader in the rule for JS files:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2b1c9ba67df548886ecd80033c3672e8/href">https://medium.com/media/2b1c9ba67df548886ecd80033c3672e8/href</a></iframe><p>excludeNodeModulesExcept function is our savior. Huge thanks to <a href="https://github.com/jh3141"><em>@jh3141</em></a><em>, </em>who mentioned this in this GitHub comment: <a href="https://github.com/webpack/webpack/issues/2031#issuecomment-317589620"><em>https://github.com/webpack/webpack/issues/2031#issuecomment-317589620</em></a></p><p>Let’s look at this beauty.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/942f6df7086cb0c61da01280d44a7af1/href">https://medium.com/media/942f6df7086cb0c61da01280d44a7af1/href</a></iframe><p>It takes modules array as an input (line 5). Then it returns a function (line 13) which for each currently processed module evaluates if it should be transpiled by Babel or not. It does so based on regular expressions (line 10).</p><h4>Wrap-up</h4><p>In this short tutorial, we have learned that even selective transpilling can be easily solved. For any suggestions or ideas please use the comments below, or email me directly.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5acd87a087c2" width="1" height="1" alt=""><hr><p><a href="https://medium.com/slido-dev-blog/transpile-debug-and-other-npm-packages-to-es5-5acd87a087c2">Transpile debug and other npm packages to es5</a> was originally published in <a href="https://medium.com/slido-dev-blog">Slido developers blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Performance benefits of using Service Worker in Angular app]]></title>
            <link>https://medium.com/slido-dev-blog/performance-benefits-of-using-service-worker-in-angular-app-b89125689f94?source=rss-b6c216d24584------2</link>
            <guid isPermaLink="false">https://medium.com/p/b89125689f94</guid>
            <category><![CDATA[angular]]></category>
            <category><![CDATA[performance]]></category>
            <category><![CDATA[ngrx]]></category>
            <category><![CDATA[service-worker]]></category>
            <category><![CDATA[caching]]></category>
            <dc:creator><![CDATA[Kamil Maraz]]></dc:creator>
            <pubDate>Thu, 12 Dec 2019 08:26:24 GMT</pubDate>
            <atom:updated>2019-12-12T08:26:24.268Z</atom:updated>
            <content:encoded><![CDATA[<h4>Have you ever tried to cache responses from APIs? Try Service Workers.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-ULMCum7EqEynGF8bvFweQ.jpeg" /><figcaption><a href="https://unsplash.com/photos/8KfCR12oeUM">https://unsplash.com/photos/8KfCR12oeUM</a>, Thanks to Christopher Burns.</figcaption></figure><p>We all strive to deliver the best performance of our apps. So, how would you do it? You can reduce bundle size and split bundle into multiple chunks. Then lazy load and cache everything. You can do this or that but after everything is done perfectly, <em>what should be the next step?</em></p><p>You guessed right: <a href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API">Service Workers.</a></p><p>In this article, you will learn how to set up Service Worker using <a href="https://developers.google.com/web/tools/workbox">Workbox</a> with custom <a href="https://webpack.js.org/">Webpack</a> configuration. For state management, let’s use <a href="https://ngrx.io/">NgRx.</a> But anything will do. You can be as hardcore as you want. This setup will improve bootstrap of our application by caching assets and, most importantly, GET requests.</p><blockquote>In this example, our guinea-pig will be <a href="http://admin.sli.do/">Slido Admin</a> mentioned in <a href="https://medium.com/slido-dev-blog/angular-hybrid-app-ahead-of-time-compilation-204ced918ec7">previous articles.</a></blockquote><h4>So, let’s begin</h4><p>As usual, the first step in our journey is:</p><pre>npm install workbox-webpack-plugin workbox-window @types/workbox-window --save</pre><p>The next step is to configure Webpack. It is essential to configure SSL properly. Service Worker <a href="https://developers.google.com/web/fundamentals/primers/service-workers#you_need_https">needs valid SSL certificate</a> to be able to run in a browser.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/682/1*V1JGuYwRrAwsmW_T9rsOgg.png" /><figcaption><a href="https://gist.github.com/kmaraz/8c4ae70de24d9b11659713bd408dbd5f">https://gist.github.com/kmaraz/8c4ae70de24d9b11659713bd408dbd5f</a></figcaption></figure><p>Now you should configure Service Worker file.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/680/1*GkmcaRnOW8vGjWnog8UrBQ.png" /><figcaption><a href="https://gist.github.com/kmaraz/82eef036aa2eb0991316ba8d8736fbb9">https://gist.github.com/kmaraz/82eef036aa2eb0991316ba8d8736fbb9</a></figcaption></figure><p>The Service Worker lifecycle consists of 5 phases. parsed, installing, installed (waiting), activating, activated. When Service Worker is parsed, it tries to install itself. When it is installed, the skipWaiting command will force it to activate itself immediately.</p><blockquote>“… you can use skipWaiting and clientsClaim to force the new service worker to immediately take control of open pages.¹”</blockquote><p>If you want to understand it in more depth, read the official documentation <a href="https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle#skip_the_waiting_phase">here</a> and <a href="https://developers.google.com/web/tools/workbox/guides/generate-complete-sw#skip_waiting_and_clients_claim">here.</a></p><p>Now is the time to install Service Worker. Depending on your application, the best place should be somewhere during its bootstrap phase. Preferably in Injectable.</p><blockquote>In <a href="https://admin.sli.do/">Admin</a>, we need to make sure that both AngularJs and Angular parts are loaded before doing any Service Worker magic. This article about <a href="https://medium.com/slido-dev-blog/angular-flux-a-hybrid-app-9113c2e2b872">Angular hybrid architecture</a> will give you more detail.</blockquote><p>You can set it up like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/680/1*kS3LzU_j49SBIF88ckC7cg.png" /><figcaption><a href="https://gist.github.com/kmaraz/a2f5b0f0d4b084f8187e1b7cc52c0db5">https://gist.github.com/kmaraz/a2f5b0f0d4b084f8187e1b7cc52c0db5</a></figcaption></figure><p>And then write WorkerService Injectable:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/680/1*XfeSgtmDyNVoACcCrwHPlg.png" /><figcaption><a href="https://gist.github.com/kmaraz/bea955a4c6d4bbb14c54cc94a9f52ec2">https://gist.github.com/kmaraz/bea955a4c6d4bbb14c54cc94a9f52ec2</a></figcaption></figure><p>In the snippet above the Workbox is imported dynamically (a matter of taste). Provided that everything went according to plan, your Service Worker is now installed and running.</p><h4>What about performance goals?</h4><p>The first thing that comes to mind is cache. Let’s do that straight away.</p><p>For caching assets, you need to <a href="https://developers.google.com/web/tools/workbox/modules/workbox-routing">register a route</a>. Then pick a <a href="https://developers.google.com/web/tools/workbox/modules/workbox-strategies">caching strategy.</a> For the purpose of this example, we are using Cache first strategy.</p><blockquote>“Offline web apps will rely heavily on the cache, but for assets that are non-critical and can be gradually cached, a <a href="https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#cache-falling-back-to-network">cache first</a> is the best option.²”</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/680/1*_2qmxevnpGIs8rF6xXoiTA.png" /><figcaption><a href="https://gist.github.com/kmaraz/a8dadab4378e2686591ea700c150179b">https://gist.github.com/kmaraz/a8dadab4378e2686591ea700c150179b</a></figcaption></figure><p>Expiration plugin sets the life of cache and manages its resetting when memory quota is reached.</p><p>The next caching strategy in this example is called State while revalidate. Let’s demonstrate it by caching Google Fonts used in Admin application.</p><blockquote>“The <a href="https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#stale-while-revalidate">stale-while-revalidate</a> pattern allows you to respond to the request as quickly as possible with a cached response if available, falling back to the network request if it’s not cached. The network request is then used to update the cache.³”</blockquote><p>You should use it for all the data which can be updated more often. However, you still want to benefit from speed of local cache.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/680/1*VwdwXi1tJX3ThfK9zdW7Mw.png" /><figcaption><a href="https://gist.github.com/kmaraz/837b999087601379bd8ff46b82bcdbd1">https://gist.github.com/kmaraz/837b999087601379bd8ff46b82bcdbd1</a></figcaption></figure><p>Simple as that.</p><h4>Those were quick wins. Now is the time for magic.</h4><p>Imagine that during bootstrap, your application is doing a few GET requests.</p><p>For example:</p><pre>1. request: GET https://api.example.com/users<br>2. request: GET https://api.example.com/accounts<br>3. request: GET https://api.example.com/things</pre><p>Now, let’s suppose we identified the following:</p><ul><li>Requests for users and accounts have very small payload and change only once in a while</li><li>Request for things is often very heavy and takes very long time to download but could potentially change frequently</li></ul><p>The first two endpoints are clearly the case for caching responses. Depending on the update frequency of things endpoint, it might be a good idea to cache the responses locally, too.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/680/1*vrAgGgFVjqwwjFOmZWmoIw.png" /><figcaption><a href="https://gist.github.com/kmaraz/c180c5dad9c6af825521688a7f76ec69">https://gist.github.com/kmaraz/c180c5dad9c6af825521688a7f76ec69</a></figcaption></figure><p>The next time this request is made, it will also be cached by Service Worker. Easy, right? Cached response will be used every time GET request is made.</p><p>What if the response has changed? What is the best way to notify your application and reflect this change in UI?</p><p>To communicate with your application, use the Broadcast update plugin. channelName is self-explanatory. headersToCheck is an array of headers for comparing request response and cached values. If there is a difference, the plugin will replace cached response and notify the application. Checking headers is way faster than comparing the whole response body.</p><p>Remember how you initialized Service Worker? The next step is to listen to it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/680/1*EeSPuSFGLp7VHQslUHB4xA.png" /><figcaption><a href="https://gist.github.com/kmaraz/b17853cbf00a313f5f1719e122fac54c">https://gist.github.com/kmaraz/b17853cbf00a313f5f1719e122fac54c</a></figcaption></figure><p>First, listen to BroadcastChannel initialized by broadcastUpdate plugin in Service Worker. Message handler will notify your application about cache updates. Then, you should collect all the changes from the browser caches.</p><p>Next, send it to your application. The nice thing about <a href="https://ngrx.io/">NgRx</a> is that you can reuse the same <a href="https://ngrx.io/guide/effects">Effects</a> as you use for your standard API call processing.</p><p>Here is an example of how ThingsEffects can look:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/680/1*zCpDcz9Ow-M5DP_iKQiTyw.png" /><figcaption><a href="https://gist.github.com/kmaraz/b03e361aefa627fc43debdccf6b355a8">https://gist.github.com/kmaraz/b03e361aefa627fc43debdccf6b355a8</a></figcaption></figure><p>As you can see in the snippet above, after fetching things the update action is called. You can call this action also from method dispatchData in WorkerService. That way you achieve state (and UI) update easily.</p><h4>Quick tip #1</h4><p>You can use Logout action or actions fired when the user is not authorized to clear browser cache. The same as you do with tokens and cookies.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/680/1*lDgsL4-6Zj0HzIeyM_G4LQ.png" /><figcaption><a href="https://gist.github.com/kmaraz/f833f9960996afd20f002e7382853ccc">https://gist.github.com/kmaraz/f833f9960996afd20f002e7382853ccc</a></figcaption></figure><h4>Quick tip #2</h4><p>Sometimes during the bootstrap of a hybrid application (NgUpgrade), resources can be loaded in AngularJs service before Injectables are initialized.</p><p>You can use a temporary solution which includes storing updated data in a global variable (I know, I know…) and using it in Injectable later.</p><p>Here is the very top of app.module.ts:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/680/1*IL_NLibJqPre0ePkhJzWAw.png" /><figcaption>app.module.ts</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/680/1*Qv66PFPmFMh1eP8G_u_jTg.png" /><figcaption><a href="https://gist.github.com/kmaraz/239aea696d297da0a533f8576232e731">https://gist.github.com/kmaraz/239aea696d297da0a533f8576232e731</a></figcaption></figure><p>The update to the initialize function looks like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/680/1*BA1Z7MT44SrSzvGT6FpjPw.png" /><figcaption><a href="https://gist.github.com/kmaraz/0553eddec5298bdd830cd942648aec8f">https://gist.github.com/kmaraz/0553eddec5298bdd830cd942648aec8f</a></figcaption></figure><p>There are many ways how this could go wrong for the users. Make sure you implement everything mentioned in this article carefully and test it properly.</p><h4>A real-world example</h4><p>Everything until this point was a source code sitting in the comfort of your localhost. Now you are going test it in the wilderness.</p><p>The aim for this article is to help you improve bootstrap time. Slido Admin is pretty heavy, so we saw improvements immediately.</p><p>We measured load times without and with the Service Worker enabled. Also, we simulated network speeds used by our clients.</p><p>Here are some numbers:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/726/1*lN1xclt3BMpvHOww4w7j2g.png" /></figure><p>In this case, the bootstrap time decreased significantly. The improvements can be even bigger in applications that are more network heavy.</p><h4>Wrap up</h4><p>As you can see, setting up a Service Worker in Angular application is easy. Even when it needs to be done manually and not by using Angular CLI. You can easily manage perceived bootstrap time by caching data. Even network data.</p><p>If this is the case, then Service Workers play on your side. The performance benefits of using this approach can be minuscule or huge. It depends on your use case. So, remember to do performance tests after every step mentioned in this article. You never know.</p><h4>Sources</h4><p>[1]: <a href="https://developers.google.com/web/tools/workbox/guides/generate-complete-sw#skip_waiting_and_clients_claim">https://developers.google.com/web/tools/workbox/guides/generate-complete-sw#skip_waiting_and_clients_claim</a></p><p>[2]: <a href="https://developers.google.com/web/tools/workbox/modules/workbox-strategies">https://developers.google.com/web/tools/workbox/modules/workbox-strategies</a></p><p>[3]: <a href="https://developers.google.com/web/tools/workbox/modules/workbox-strategies">https://developers.google.com/web/tools/workbox/modules/workbox-strategies</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b89125689f94" width="1" height="1" alt=""><hr><p><a href="https://medium.com/slido-dev-blog/performance-benefits-of-using-service-worker-in-angular-app-b89125689f94">Performance benefits of using Service Worker in Angular app</a> was originally published in <a href="https://medium.com/slido-dev-blog">Slido developers blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to enable ahead-of-time compilation in an Angular hybrid app]]></title>
            <link>https://medium.com/slido-dev-blog/angular-hybrid-app-ahead-of-time-compilation-204ced918ec7?source=rss-b6c216d24584------2</link>
            <guid isPermaLink="false">https://medium.com/p/204ced918ec7</guid>
            <category><![CDATA[angular]]></category>
            <category><![CDATA[productivity]]></category>
            <category><![CDATA[tech]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[typescript]]></category>
            <dc:creator><![CDATA[Kamil Maraz]]></dc:creator>
            <pubDate>Wed, 06 Mar 2019 08:34:39 GMT</pubDate>
            <atom:updated>2019-04-09T20:44:30.930Z</atom:updated>
            <content:encoded><![CDATA[<h3>How to enable Ahead-of-Time compilation in an Angular hybrid app</h3><h4>And why you’ll want to do this</h4><p>This article is a part of a series:</p><ol><li><a href="https://medium.com/@kamylko/angular-flux-architecture-introduction-f051a24aedfe">Angular+FLUX architecture — Introduction</a></li><li><a href="https://medium.com/@kamylko/angular-flux-a-hybrid-app-9113c2e2b872">Angular+FLUX — A hybrid app</a></li><li><a href="https://medium.com/@kamylko/angular-hybrid-app-ahead-of-time-compilation-204ced918ec7"><strong>Angular Hybrid app — Ahead-of-Time compilation</strong></a></li></ol><p>Ahead-of-time (AOT) compilation is a big word in the Angular community. Everybody wants to get it running. If you are starting with a new project using <a href="https://cli.angular.io/">Angular CLI</a>, you’ve won. There is nothing simpler than to <a href="https://angular.io/guide/aot-compiler#angular-compilation">include “ — aot” option </a>in your terminal.</p><p>But what if you have a custom Webpack configuration? Or you are using <a href="https://angular.io/guide/upgrade">Upgrade module</a> and you have a hybrid Angular application? Have a look at how we dealt with this particular problem in <a href="https://admin.sli.do/">Admin </a>— administration interface for <a href="https://slido.com/">Slido</a> users.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iF8uCp-Dx8BfuCSgkbHvnQ.jpeg" /></figure><h4>Ahead-of-Time vs. Just-in-Time</h4><p>The difference between AOT and Just-in-Time compilation (JIT) rests in the step in which compilation happens. With AOT, we are talking about the build phase. It happens before running the application in the browser. JIT compilation is happening when the application is running in the browser.</p><p>As it is stated in the <a href="https://angular.io/guide/aot-compiler#the-ahead-of-time-aot-compiler">Angular guide:</a></p><blockquote>“The Angular Ahead-of-Time compiler converts your Angular HTML and TypeScript code into efficient JavaScript code during the build phase before the browser downloads and runs that code.”</blockquote><p>One of the advantages of enabling AOT is <strong>faster application rendering.</strong> As all of the application parts are already compiled when downloaded by the browser, there is a significant decrease of bootstrap time of application as well as the rendering times during its use.</p><p>Another benefit can be a <strong>smaller bundle size.</strong> When you are using AOT, you do not need to include <a href="https://angular.io/api/core/Compiler">@angular/compiler</a> as it is no longer needed. The compiled application can increase in its bundle size, but this strongly depends on the specifics of your application.</p><p>Thirdly, there is a much higher possibility to <strong>spot compilation errors in templates, </strong>as you will be notified by the compiler during build time. If you are using Visual Studio Code, you can use <a href="https://marketplace.visualstudio.com/items?itemName=Angular.ng-template">Angular Language Service extension</a> as it has AOT diagnostics enabled in real-time.</p><h4>Steps necessary to enable AOT</h4><p>The first step, as it happens, is to run <em>npm install </em><a href="https://www.npmjs.com/package/@ngtools/webpack"><em>@ngtools/webpack</em></a>.</p><p>Next, you have to configure Webpack properly. In this step, you want to configure AngularCompilerPlugin which comes with @ngtools. Using configuration parameters you will set up locations of tsconfig and entry files. Most of the time you want to use separate tsconfigs for JIT and for AOT. You will see why in a moment.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5d3af886f77d2e11c471f71b4007ca58/href">https://medium.com/media/5d3af886f77d2e11c471f71b4007ca58/href</a></iframe><p>In your standard tsconfig you need to exclude main.aot.ts file, which is the entry point for applications compiled using AOT. In this file, you will import files which will be available only during the build time. This way you can separate between JIT and AOT builds easily, without any errors.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/92a44c29870b833a3d84d63c3fb5f9a3/href">https://medium.com/media/92a44c29870b833a3d84d63c3fb5f9a3/href</a></iframe><p>Tsconfig for AOT is ordinary. There is nothing special about it.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f2eacc6db253d227e3769117906c69d1/href">https://medium.com/media/f2eacc6db253d227e3769117906c69d1/href</a></iframe><p>Next file is here to demonstrate how we can split builds between JIT and AOT. In this case, JIT is used in a dev environment and AOT is used in the production.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/66a9fbd557429b741c69226a2f7f31e8/href">https://medium.com/media/66a9fbd557429b741c69226a2f7f31e8/href</a></iframe><p>AOT uses platformBrowser instead of platformBrowserDynamic. Next important step is to import factory files which will be available during the build time.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/14f89872617a3dffb8a6f27ae6b87966/href">https://medium.com/media/14f89872617a3dffb8a6f27ae6b87966/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/17148ade22e8ed6eea7bdb4d862e5d71/href">https://medium.com/media/17148ade22e8ed6eea7bdb4d862e5d71/href</a></iframe><h4>Performance improvements</h4><p>From the start, we wanted to have AOT enabled for a reason — to have better performance of <a href="https://admin.sli.do/">Admin</a> application. This is a short comparison of what improved and what remained the same:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/70c4b21d5bb603335d3acf88031629ea/href">https://medium.com/media/70c4b21d5bb603335d3acf88031629ea/href</a></iframe><p>As you can see, the initial load time significantly decreased even when the bundle size increased slightly.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*E9l7k2n4OsqbiQtlg26ANw.png" /><figcaption>Apdex measured before and after the release of AOT to the production.</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lgQobPbYaeh8duw-2ePnTg.png" /><figcaption>Average load times decreased even when throughput remained the same.</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/1*LKYyX2rAR0r1p8zaUA2-kA.png" /><figcaption>Average load times compared in a histogram overlay (dark=JIT,light=AOT).</figcaption></figure><h4>Wrap up</h4><p>Enabling AOT resulted in a notable improvement for all of our users. Initial load times improved significantly and the application sped up as well.</p><p>If you’ve never considered enabling AOT in production, now is the time. Do you have any questions about this topic? Feel free to contact me.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=204ced918ec7" width="1" height="1" alt=""><hr><p><a href="https://medium.com/slido-dev-blog/angular-hybrid-app-ahead-of-time-compilation-204ced918ec7">How to enable ahead-of-time compilation in an Angular hybrid app</a> was originally published in <a href="https://medium.com/slido-dev-blog">Slido developers blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Angular+FLUX — A hybrid app]]></title>
            <link>https://medium.com/slido-dev-blog/angular-flux-a-hybrid-app-9113c2e2b872?source=rss-b6c216d24584------2</link>
            <guid isPermaLink="false">https://medium.com/p/9113c2e2b872</guid>
            <category><![CDATA[redux]]></category>
            <category><![CDATA[angularjs]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[angular]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Kamil Maraz]]></dc:creator>
            <pubDate>Wed, 25 Apr 2018 14:18:02 GMT</pubDate>
            <atom:updated>2019-03-06T08:35:12.333Z</atom:updated>
            <content:encoded><![CDATA[<p>This article is a part of a series:</p><ol><li><a href="https://medium.com/@kamylko/angular-flux-architecture-introduction-f051a24aedfe">Angular+FLUX architecture — Introduction</a></li><li><a href="https://medium.com/@kamylko/angular-flux-a-hybrid-app-9113c2e2b872"><strong>Angular+FLUX — A hybrid app</strong></a></li><li><a href="https://medium.com/@kamylko/angular-hybrid-app-ahead-of-time-compilation-204ced918ec7">Angular Hybrid app — Ahead-of-Time compilation</a></li></ol><p>It has been a while since AngularJs was considered a modern framework. The latest version (<a href="https://github.com/angular/angular.js/blob/master/CHANGELOG.md">currently 1.6.9</a>) does not give us any substantial improvements and even its authors recommend transition to Angular as soon as possible.</p><p>While <a href="https://medium.com/slido-dev-blog/angular-flux-architecture-introduction-f051a24aedfe">we were developing Admin</a> — an application that uses AngularJs — there came a point when we needed to make a decision about the <strong>upgrade process.</strong></p><p>We were considering two options: <br> <em>1. develop a new application from scratch; or<br> 2. continue with a more suitable solution — a hybrid application</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*HT2mTAGdq7O_H3BAZnFQ1w.jpeg" /></figure><p>Our decision was influenced by several different factors. For instance, some parts of Admin are still written in old versions of CoffeeScript. Also, we are trying to create new features in Admin all the time. Extensive refactoring is very rare, because we would have to allocate too much of our resources.</p><p>What is more, high priorities of the business are often in direct conflict with priorities of a programmer. It was for these and many other reasons that in the end we picked the <em>hybrid application approach.</em></p><blockquote>In a hybrid application you run both AngularJs and Angular at the same time.</blockquote><p>This is why we came up with the idea to create a completely new feature in such application. However, we were concerned that it would only add new technical debt to our current situation. We knew that every change of this kind usually comes with a risk of new unknown problems (<a href="https://www.pmi.org/learning/library/characterizing-unknown-unknowns-6077">unknown unknowns</a>).</p><h4>How the upgrade started</h4><p>We attempted the migration from AngularJs to Angular on multiple occasions. None of them was successful. In some attempts it was the lack of knowledge, in others it was caused by incomplete documentation on the side of Angular team. Also, there were various complications specific to Admin on top of that (for example custom Webpack configuration, multiple out-dated vendors and so forth). Our team realized that Admin was not ready for such change.</p><p>The last opportunity to upgrade emerged when we decided to renew one of Admin’s core features — the <em>EventSettings </em>module. The vision was to get rid of the buggy code although our main goal was to improve UX and UI. Therefore, we decided to rewrite this module completely.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3UpQceYCyY_aRDIMJLY9QA.png" /><figcaption>The EventSettings module is a core part of the administration interface of Admin application. It gives the user the ability to turn the Slido features on and off, and it allows them to manage the event in real time.</figcaption></figure><p>It was a separate part of Admin and, if necessary, we could A/B test it on a small sample of the Slido user base easily enough.</p><h4>Creating a root module</h4><p>The first step was and always should be — an extensive research. A list of recommended publications is included at the bottom of this article.</p><p>And the outcome of our research? It was a few lines of code which represented a root module for our hybrid application:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e7d25925bb8a45a0b3a119835a1d3c76/href">https://medium.com/media/e7d25925bb8a45a0b3a119835a1d3c76/href</a></iframe><p>Root module contains the original AngularJs module (line 2), new Angular module (line 10) and bootstrap of hybrid application (lines 22 and 26). And that is it. Simple.</p><p><em>Bootstrapping of a hybrid application is described in detail in</em><a href="https://angular.io/guide/upgrade#bootstrapping-hybrid-applications"><em> guide provided by Angular team.</em></a></p><p>The above example shows how easily you can initialize all modules needed to run a hybrid application. But the reality is always more complicated than that. That is why the following part of this article will look at other commonly used files in this type of application.</p><h4>Finding out about NgRx</h4><p>In our <a href="https://medium.com/slido-dev-blog/angular-flux-architecture-introduction-f051a24aedfe">previous article</a> we described the problems we faced in relation to our custom implementation of FLUX architecture.</p><p>During the upgrade process, we considered trying some kind of a vendor which already implements FLUX, or which could help us with it. There were multiple options available, for example: <a href="https://redux.js.org/">Redux</a>, <a href="https://github.com/ngrx/platform">NgRx</a>, <a href="https://github.com/reflux/refluxjs">RefluxJs</a> and so forth.</p><p>In the end we chose NgRx due to its full compatibility with <a href="https://en.wikipedia.org/wiki/Reactive_programming">Reactive programming paradigm,</a> which is<a href="https://blog.nrwl.io/reactive-programming-in-angular-7dcded697e6c"> very popular in Angular world.</a></p><h4>Change of architecture diagram</h4><p>Now we will explain how the original diagram changed after using NgRx. Later, we will move on to particular changes in our application and compare it with our custom solution.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/505/1*P4tLsICIEVqT1nD6VuVJ4Q.jpeg" /><figcaption>FLUX represented by combination of Angular+NgRx</figcaption></figure><p>In implementation of FLUX using NgRx the data flows from components through Dispatcher to Reducers directly. Reducers are modifying parts of global state of application.</p><p>Instead of emitting an event about state change from Store, we have implemented Selectors, on which we can subscribe in components controller (we are using “reactiveness” of environment).</p><p>Selectors are methods mostly used for obtaining slices of store state. Therefore, business logic from Stores is now divided into Reducers and Selectors. Effects are used for handling of the so-called side-effects.</p><blockquote>Effects listen for actions dispatched from @ngrx/store. They isolate side effects from components, allowing for more pure components that select state and dispatch actions. They provide new sources of actions to reduce state based on external interactions such as network requests, web socket messages and time-based events.</blockquote><p>Effects will implement business logic which was in Actions before.</p><p>The following examples of EventsModule will be used to compare differences against our custom implementation described in our previous article.</p><h4>Code examples FTW</h4><p>The updated folder structure could be as follows:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/508/1*b6xdu4utFOqOxlWw9LEqFQ.png" /><figcaption>Example of the new folder structure</figcaption></figure><h4>I. View + Controller</h4><p>As we can see, View has not changed much:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/89d4356ad830f53ab71b6bec0f48d8ea/href">https://medium.com/media/89d4356ad830f53ab71b6bec0f48d8ea/href</a></iframe><p>Perhaps the most important change is related to Actions from which the bindings for specific component action callbacks are removed. After the upgrade, we are calling them directly from controller of <em>EventsEventItem </em>component. This change was made because of our unwritten rule:<em> there should be only one file for Actions per module. Same applies for Effects, Reducers, or Selectors.</em></p><p>Controller is also much simpler:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e00f3b1608b1bca2846d8a27e67283be/href">https://medium.com/media/e00f3b1608b1bca2846d8a27e67283be/href</a></iframe><p>In our solution subscriptions replaced event handlers from the previous one. We are subscribing during initialization phase of component in constructor method and unsubscribing in ngOnDestroy method.</p><p>An interesting thing to metion is that the last action we call in the lifecycle of component is <em>resetting of the current feature state </em>for this particular module. Generally, this is considered good practice.</p><h4>II. Actions</h4><p>Actions is a list of actions which can be used in this module:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1411ff318b58cc0e6079fc80d6809ff0/href">https://medium.com/media/1411ff318b58cc0e6079fc80d6809ff0/href</a></iframe><p>The main advantage of this approach si <a href="https://github.com/ngrx/platform/blob/master/docs/store/actions.md">strong type control</a>. Every programmer working on a big project would ceratinly appreciate this.</p><h4>III. Effects</h4><p>This is how so-called Effects can look like:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/32eca5cc8e302bb0958a6d7eabafc7a2/href">https://medium.com/media/32eca5cc8e302bb0958a6d7eabafc7a2/href</a></iframe><p>Effects are used for handling side-effect in data flow. In practice, it means for example, handling of asynchronous operations (AJAX calls, or other API communication). Business logic stored in Actions from our custom implementation is also moved there.</p><p>Effects require the highest entry effort from a programmer because, as they use mostly RxJs, they contain every part of the reactive programming paradigm. When a programmer overcomes this “obstacle” a big AHA! moment follows, after which everything becomes crystal clear.</p><h4>IV. Reducers + Selectors</h4><p>Last parts of our jigsaw are Reducers and Selectors:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b4d4ab397b6b20b21a1e169048726541/href">https://medium.com/media/b4d4ab397b6b20b21a1e169048726541/href</a></iframe><p>Reducer is a pure function, that receives two parameters on input: the <em>current application state </em>and <em>action that should be handled</em>. Taking those parameters into account, it clones previous state and returns new updated state.</p><p>So what we did was moving business logic from Store from previous custom implementation to Reducer while “get” methods from Store were replaced by Selectors.</p><h4>V. Module</h4><p>Now we want to glue all the pieces together, so we create EventsModule. See below.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1b4e240ac95588c47ee7d26901ff90a6/href">https://medium.com/media/1b4e240ac95588c47ee7d26901ff90a6/href</a></iframe><p>Apart from common parts of the module, we need to register Services, Components and so forth. Here we registered also Effects and Reducers.</p><h4>Specifics of hybrid application</h4><p>Use of hybrid application comes with a multitude of specifics, one of which is registering of Effects. The following is our last example which shows how the root module looks after this change:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/04d04370ba78b346f5dcc90dfe1a7f40/href">https://medium.com/media/04d04370ba78b346f5dcc90dfe1a7f40/href</a></iframe><p>In the modified root module we have added initialization of Reducers and Effects. Effects for particular submodules in hybrid application are registered in a special way (line 40).</p><p>And finally, the last step is simple:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7227b2b4123d8c027bb1451255e985ae/href">https://medium.com/media/7227b2b4123d8c027bb1451255e985ae/href</a></iframe><p>Sadly, you can’t find this approach in an official documentation. That’s why we had to study Github issues. However, this is likely to change in the future.</p><h4>What problems does NgRx solve?</h4><p><a href="https://medium.com/slido-dev-blog/angular-flux-architecture-introduction-f051a24aedfe">In the previous article</a> we mentioned a few problems we faced with custom FLUX implementation. We had a problem with using of multiple stores. Also we considered our implementation as too excessive. And probably the biggest flaw was copying or cloning of the data. Now we will take a look if something improved.</p><p><strong>Multiple stores:</strong> They were replaced by one global store, which is provided by NgRx. Selectors take care of handling special cases caused by asynchronous nature of application. For every substate we have implemented a dedicated Selector and whenever we need to use combined states, we use combined Selectors.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b77385b878588b09156428aefae6c563/href">https://medium.com/media/b77385b878588b09156428aefae6c563/href</a></iframe><p>Those are memoized, so there is no overhead on application performance.</p><p><strong>Too much writing:</strong> This has not changed so much. We maintain clarity of the code by following all the best practices recommended by authors of NgRx and RxJs. It can be easily seen in Effects, but also in the split of business logic to Reducers and Selectors.</p><p><strong>Cloning the data:</strong> The problem with copying/cloning of object references is still there. But to prevent this sort of problems we are using great toolkit that comes with NgRx. One of those tools is ngrx-store-freeze (a metareducer), that uses Object.freeze() under the hood and notifies us about misusing the global state. Also we must mention Redux DevTools.</p><h4><strong>Wrap up</strong></h4><p>The migration to hybrid application was a good choice. Our decision to go with a custom FLUX implementation at the start helped us clarify what needed to be changed and what was to be kept during the migration process. NgRx clarified for us how code structure should look like. The well-beaten path helped us with the transition to reactive programming. And the results have definitely paid off.</p><h4>Sources</h4><ul><li><a href="https://angular.io/guide/upgrade">https://angular.io/guide/upgrade</a></li><li><a href="https://angular.io/guide/lifecycle-hooks">https://angular.io/guide/lifecycle-hooks</a></li><li><a href="https://en.wikipedia.org/wiki/Reactive_programming">https://en.wikipedia.org/wiki/Reactive_programming</a></li><li><a href="https://angular.io/guide/dependency-injection#injection-token">https://angular.io/guide/dependency-injection</a></li><li><a href="https://github.com/ngrx/platform/tree/master/docs">https://github.com/ngrx/platform/tree/master/docs</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9113c2e2b872" width="1" height="1" alt=""><hr><p><a href="https://medium.com/slido-dev-blog/angular-flux-a-hybrid-app-9113c2e2b872">Angular+FLUX — A hybrid app</a> was originally published in <a href="https://medium.com/slido-dev-blog">Slido developers blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Angular+FLUX architecture — Introduction]]></title>
            <link>https://medium.com/slido-dev-blog/angular-flux-architecture-introduction-f051a24aedfe?source=rss-b6c216d24584------2</link>
            <guid isPermaLink="false">https://medium.com/p/f051a24aedfe</guid>
            <category><![CDATA[upgrade]]></category>
            <category><![CDATA[flux]]></category>
            <category><![CDATA[redux]]></category>
            <category><![CDATA[ngrx]]></category>
            <category><![CDATA[angular]]></category>
            <dc:creator><![CDATA[Kamil Maraz]]></dc:creator>
            <pubDate>Wed, 28 Mar 2018 12:18:07 GMT</pubDate>
            <atom:updated>2019-03-06T08:35:23.193Z</atom:updated>
            <content:encoded><![CDATA[<p>This article is a part of a series:</p><ol><li><a href="https://medium.com/@kamylko/angular-flux-architecture-introduction-f051a24aedfe"><strong>Angular+FLUX architecture — Introduction</strong></a></li><li><a href="https://medium.com/@kamylko/angular-flux-a-hybrid-app-9113c2e2b872">Angular+FLUX — A hybrid app</a></li><li><a href="https://medium.com/@kamylko/angular-hybrid-app-ahead-of-time-compilation-204ced918ec7">Angular Hybrid app — Ahead-of-Time compilation</a></li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Phg_9259Vl8tNHyCh_W3sg.jpeg" /></figure><p>In recent years in the front-end (<a href="https://en.wikipedia.org/wiki/Front-end_web_development">FE</a>) world, especially with the rise of React as an AngularJs alternative, a hot debate has broken out on the following topic: “The <em>best</em> architecture for the FE application.”</p><p>So we asked ourselves: What architecture suits our needs the best, and why? How do we pick one, considering that we want to reduce the technical debt and grow the team and/or the codebase? This might be the most common problem every programmer will face at least once in his or her career.</p><p>In this article we will explain why we picked the <a href="https://facebook.github.io/flux/">FLUX architecture</a> and how it can be used in a medium-sized AngularJs application. We will break down the architecture fundamentals and apply them to a real world scenario. And finally, we will discuss the pros and cons of this approach.</p><h4>What is Admin about?</h4><p><a href="https://admin.sli.do/">Admin</a> is one of several Single-page applications (<a href="https://en.wikipedia.org/wiki/Single-page_application">SPA</a>) in <a href="https://www.sli.do/">Slido</a>. Admin gives the user to create and set up an event according to his or her needs. It gives the user the ability to turn the <a href="https://www.sli.do/features-questions">Slido features</a> on and off, and it allows him or her to manage the event in real time. It is the “single source of truth” (<a href="https://en.wikipedia.org/wiki/Single_source_of_truth">SSOT</a>) for conference or meeting organizers. The user should be able to find everything he or she needs for the event to be successful there.</p><blockquote>Slido is a technology company that enhances communication and increases interaction at events and meetings. We enable users to crowdsource top audience questions to drive meaningful conversations, engage participants with live polls and capture valuable event data. We focus on simplicity. Both for meeting planners who can create an event in less than a minute and participants who can join via any device with a simple code. Slido has helped to power audience interaction and engage millions of participants at over 120,000 events. We are proud to have worked with renowned conferences such as SXSW, Money20/20, and Web Summit and high-profile clients such as Adobe, Spotify, Lufthansa, BBC and Oracle.</blockquote><p>At one point, Admin was a part of a monolithic structure. It covered only a few use-cases that the the organizer had at his or her disposal. Our vision was to make a complete overhaul of Admin UX/UI and to add more new features to it. Therefore — as the first step — we decided to rewrite Admin as an SPA. I was the only one responsible for the programming part but we were sure that it would not be the case in the near future.</p><p><strong>This became a challenge in itself which prompted us to make the following critical decisions:</strong></p><ol><li>Pick the technologies we will use: <em>AngularJs, React, JavaScript, CoffeeScript, etc.</em></li><li>Select a suitable architecture on which Admin will be built on: <em>MVC, MVP, MVVM, FLUX, etc.</em></li><li>Other things, such as: <em>code style, maintenance, testability, code clarity, speed of development, learning curve, workflow, extreme programming principles, …</em></li></ol><p>Taking the pragmatic approach we decided to use the technologies which we were familiar with, i.e. AngularJs, CoffeeScript, Grunt, Less and so forth. Later it partially transformed into AngularJs, TypeScript, Webpack and Sass.</p><p>As for the workflow we were accustomed to <a href="https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow">Gitflow</a>. We agreed that the new parts of the code would be covered by unit tests. Pretty basic decisions and commitments. We have been dealing with things like code review, pair programming and some other core principles of XP and it has been increasingly gaining our attention as our team grew.</p><h4>We decided to use the FLUX architecture.</h4><p>The most important decision was to pick a suitable architecture type. We had to consider factors such as team work, complexity of the application, or the potential and very probable growth of the codebase.</p><p>After extensive research (as our team was quite junior and these decisions were made on a ‘one-person show’ basis) we decided to try FLUX architecture. FLUX was one of many trends in the world of the front-end development at that time. Therefore, I tried to approach it very skeptically and I wanted to rationalize my decisions as much as I could.</p><p><em>Detailed description of this architecture </em><a href="https://facebook.github.io/flux/"><em>can be found here</em></a><em>, or </em><a href="https://github.com/facebook/flux"><em>here on GitHub.</em></a></p><h4>What the FLUX?!</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/361/1*Eg2fhokFZcJU-6UI853wMg.jpeg" /><figcaption>FLUX (simplified diagram)</figcaption></figure><ul><li><strong>View</strong> represents the components in React or the components/directives in AngularJs.</li><li><strong>Actions</strong> is a set of operations in our component the user can make manually or automatically, such as initialization of a component or button press, opening of the modal window or showing of the confirmation dialog. Bear in mind that <em>Actions are the only place in the architecture where we want to make asynchronous calls,</em> like calling our external web APIs.</li><li><strong>Dispatcher</strong> is our central point (SSOT) and all the data in the app will flow through it. There is only one <em>Dispatcher.</em> It can be an ideal place for logging service, wiring web-view wrappers and so on.</li><li><strong>Store </strong>is the place where the internal state of the app is stored. In contains the app data from our APIs, or it can hold the state of our UI. There can be multiple stores, but most of the time only one per module. When the data is dispatched, Store will usually consume it, and if it wants, it will notify the application by emitting the <em>“change”</em> event. Usually there is a View subscribed to this event and after receiving it, the View will get the preprocessed data from the Store. And the circle is closed.</li></ul><h4>Pros and Cons of FLUX Architecture.</h4><p>The most often mentioned <strong>pros</strong> of this architecture include:</p><ol><li><strong>Unidirectional data flow.</strong> In this case, it means that the data will flow from the View through Actions and the Dispatcher to the Store.</li><li><strong>Minimized amount of the cognitive load. </strong>Each part of this architecture has a very specific role. Therefore, it is very easy to find about where the particular portions of the code are located. Or where and how the data is processed. Also, it simplifies the debugging process.</li></ol><p>As for the <strong>cons </strong>of our implementation, I would like to emphasize:</p><ol><li><strong>Multiple stores. </strong>On multiple occasions, we needed to set special conditions for initializing the data and handling of multiple stores in one component. For example: the <em>questions </em>or the <em>polls</em> can be fetched from the API only <strong>after </strong>the <em>User </em>is logged in, but the <em>QuestionsComponent </em>or the <em>PollsComponent</em> can be initialized <strong>before </strong>the <em>User</em> is logged in.</li><li><strong>Too much writing.</strong> Each part of the architecture has a specific role. Therefore, it happens that for a very simple action — which could be contained in one controller — we need to create a file with Actions, Stores, etc.</li><li><strong>Cloning the data vs. references. </strong>Most of the implementation (except the Dispatcher) is custom made, so we needed to cope with basic problems, such as copying the data from the Stores to the Views. Sometimes we unintentionally passed the object reference to the View which instantly resulted in a bug.</li></ol><h4>Implementation in the AngularJs.</h4><p>Once we had chosen to use FLUX architecture, the next step was to implement it in Admin. In AngularJs MVVM is a standard architecture, so we needed to map the particular parts of FLUX to fit our needs.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/505/1*P3UIWSMecJgggkyUzAE6mA.jpeg" /><figcaption>FLUX in combination with AngularJs</figcaption></figure><p>The change was very easy. In practice, it means the following:</p><ol><li>View becomes a part of the Component/Directive and it is controlled from the Controller.</li><li>Controller calls the Actions. Actions is a class with a set of methods in it.</li><li>Methods in the Actions are calling the Dispatcher, on which the callbacks in the Stores are registered upon.</li><li>Store consumes the data through the registered callbacks and then preprocessees it somehow. At the end it can report about itself that it is changed so it will emit an event.</li></ol><h4>Example: Events module.</h4><p>Now we will explain the FLUX architecture in a real-world scenario to show you how it is used in combination with AngularJs. We will explore in more detail how this approach can enhance the migration from AngularJs to Angular in our next article.</p><p>Firstly, there is an <em>Events </em>module, which is used to manage the list of events in Slido. Following code examples will contain the main components and a few sub-components, its actions and store, in which its state will be stored, i.e. the event list. The user will be able to make a few actions over the event list.</p><p>Folder structure could be as follows:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/498/1*SQ_M7s2yXIV3h85kdkPrAA.png" /><figcaption>Example of the folder structure</figcaption></figure><h4><strong>I. View</strong></h4><p>As we have seen above, Views are the Components or the Directives. This is an example of how a very simple View can look like:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3009cc52facde9e60960adb0ff466201/href">https://medium.com/media/3009cc52facde9e60960adb0ff466201/href</a></iframe><p>Actions can be called from the Controller of the View or from the View itself. In this view we have multiple actions, for example: <em>selectEvent, duplicateEvent, deleteEvent</em> and so forth. At the same time the action <em>fetchAll</em>, which initializes the event list, is available. It is invoked automatically during the component initialization phase.</p><p>This is the example of a controller:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/90c0103a8d9b9b45c299a445c65a1726/href">https://medium.com/media/90c0103a8d9b9b45c299a445c65a1726/href</a></iframe><p>After the initizalization of the component we are validating the user data. If the user is initialized correctly, we are trying to fetch the event list. Also, the current configuration of the component is fetched from the <em>EventsStore</em>. It can contain filters, ordering schemas, search patterns, etc. All actions are called from the component (or from the Actions itself).</p><h4><strong>II. Actions</strong></h4><p>Have a look at a simple <em>EventsActions </em>class:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8472d786b66a82f93eeaf7a4ddcb23fb/href">https://medium.com/media/8472d786b66a82f93eeaf7a4ddcb23fb/href</a></iframe><p><em>EventsActions </em>is an AngularJs service. There is nothing special to it. All of the API calls are made from the Actions. A few actions are available. Each of them can dispatch multiple calls, depending on our needs. The <em>ActionTypes </em>service is s simple class in which the properties are strings representing our action names.</p><h4><strong>III. Store</strong></h4><p>There can be multiple Stores. Usually one per module. This one is for the <em>Events</em> module:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/dfd54db2f2604fc2d83f87f8192a44f5/href">https://medium.com/media/dfd54db2f2604fc2d83f87f8192a44f5/href</a></iframe><p>In the <em>EventsStore’s</em> constructor we register the callbacks from the Dispatcher. So it is a given that the data from the Dispatcher will flow through our store. All other commonly used operations over the data collections are contained in the <em>ListStore</em>. <em>Store is the only place where the state is mutated.</em> This is one of many aspects of decreasing cognitive load for programmers.</p><h4>Pros and cons of this approach.</h4><p>Implementation of FLUX architecture in Admin helped us to think about the application as a set of jigsaw pieces, each with a specific role and meaning. It also helped us to maintain a universal code style, which emerged from it and we have been upgrading it ever since. Technical debt means nothing to us, because the application can be very easily refactored. And since the refactoring is the daily routine of a programmer, we couldn’t be happier.</p><p>Despite the more verbose codebase, we maintain a generally clean code. The fact that our colleague was able to build new, production ready features in our application within only two weeks after taking on the role is our “proof”.</p><h4>What’s next?</h4><p>The next article in this series will explain how applications with FLUX architecture can be easily modified to hybrid AngularJs+Angular applications. We will demonstrate the implementation of this architecture using NgRx vendor and the near future of our beloved Admin.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f051a24aedfe" width="1" height="1" alt=""><hr><p><a href="https://medium.com/slido-dev-blog/angular-flux-architecture-introduction-f051a24aedfe">Angular+FLUX architecture — Introduction</a> was originally published in <a href="https://medium.com/slido-dev-blog">Slido developers blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>