<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: David Lorenz</title>
    <description>The latest articles on DEV Community by David Lorenz (@activenode).</description>
    <link>https://dev.to/activenode</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F357625%2F65bae289-c92c-45f1-a3bf-7647ab646d0d.jpeg</url>
      <title>DEV Community: David Lorenz</title>
      <link>https://dev.to/activenode</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/activenode"/>
    <language>en</language>
    <item>
      <title>unglitch - Ultra-Simple State Management for React</title>
      <dc:creator>David Lorenz</dc:creator>
      <pubDate>Mon, 05 Sep 2022 08:06:17 +0000</pubDate>
      <link>https://dev.to/activenode/unglitch-ultra-simple-state-management-for-react-4j92</link>
      <guid>https://dev.to/activenode/unglitch-ultra-simple-state-management-for-react-4j92</guid>
      <description>&lt;p&gt;Stop thinking about side-effects, solve them with locked functions.&lt;/p&gt;




&lt;p&gt;Imagine this: You create your React or Next.js setup and you need a store to seamlessly share your data across components. This will very likely include some data fetching logic which provides the data to the store.&lt;/p&gt;

&lt;p&gt;In the old days everybody would scream &lt;code&gt;Redux&lt;/code&gt; and you'd check with some kind of state property if fetching data was already done or is currently being done. Nowadays we have &lt;code&gt;Redux&lt;/code&gt; + a bunch of other options - same goal, different architectures.&lt;/p&gt;

&lt;p&gt;The existing stores are awesome, partially damn easy (e.g. &lt;code&gt;zustand&lt;/code&gt;) and do work fine.&lt;/p&gt;

&lt;h2&gt;
  
  
  But (!) stores do not solve side-effect problems
&lt;/h2&gt;

&lt;p&gt;The problem is that within the React Lifecycle you can have the following situation: 3 components need data, hence 3 components make use of your custom hook &lt;code&gt;useData&lt;/code&gt; and that hook checks in the store if data is already available e.g. with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// my custom hook&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;useData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useZustand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/** some fetching logic **/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;But this is troublesome - and I am unfortunately seeing this more and more on websites: The data is being fetched multiple times, multiple requests are sent.  The reason is easier explained by providing some visual help in the following diagram:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UDLpfTRG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xphmyixsn186zampch77.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UDLpfTRG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xphmyixsn186zampch77.png" alt="Dataflow Diagram" width="880" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All components are using the hook &lt;code&gt;useData()&lt;/code&gt;. And &lt;code&gt;useData&lt;/code&gt; in that lifecycle will have empty state data. Still the &lt;code&gt;useEffect()&lt;/code&gt; of &lt;code&gt;useData()&lt;/code&gt; will be called 3 times as we have 3 components using it - reminder: Reused hooks are not &lt;a href="https://en.wikipedia.org/wiki/Singleton_pattern"&gt;Singletons&lt;/a&gt;. And the problem continues: You cannot really check the &lt;em&gt;provided&lt;/em&gt; state data as you get the state of &lt;strong&gt;this&lt;/strong&gt; lifecycle so another component might've called the fetching function but the other components will be notified in the next lifecycle run and hence also trigger fetching the data.&lt;/p&gt;
&lt;h2&gt;
  
  
  This is not a React problem
&lt;/h2&gt;

&lt;p&gt;Now it might sound like "Isn't this bad as per architecture?". No. You get a state per lifecycle across your components such that all components will have the same, in-sync-state which is required for your components not to behave weird.&lt;/p&gt;
&lt;h2&gt;
  
  
  It's your problem: You need to orchestrate
&lt;/h2&gt;

&lt;p&gt;At the end of the day you have to avoid that functions running outside of the React lifecycle (such as data fetching methods) will be ran multiple times. This is possible with all major State Management Libraries because they do update the state before components get notified.&lt;/p&gt;

&lt;p&gt;E.g. in Redux (with &lt;code&gt;redux-thunk&lt;/code&gt;) you'd have your reducer something like:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getState&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;isFetchingData&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UPDATE_DATA&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;
    &lt;span class="p"&gt;}));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;or in &lt;code&gt;zustand&lt;/code&gt; you could build it like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;isFetchingData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;isFetchingData&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;}));&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Works but also is additional &lt;code&gt;if&lt;/code&gt;-overhead - and you have to remember to do it.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;unglitch&lt;/code&gt; provides &lt;em&gt;Lock-or-Leave&lt;/em&gt; calls
&lt;/h2&gt;

&lt;p&gt;I wanted a simple state management solving that problem. I could've adapted &lt;code&gt;zustand&lt;/code&gt; but then I went with digging into building an even simpler system: &lt;code&gt;unglitch&lt;/code&gt;.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/activenode"&gt;
        activenode
      &lt;/a&gt; / &lt;a href="https://github.com/activenode/unglitch"&gt;
        unglitch
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A straightforward, unwanted-side-effect-avoiding store for React
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
&lt;em&gt;Unglitch&lt;/em&gt; - another store?&lt;/h1&gt;
&lt;p&gt;Yes. React 18+ only and not planning to port to anything else. Get your sh*t up-to-date. No Context Provider needed, hooks only.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;But will there be Support for Vanilla, Vue, Stencil, etc?&lt;/strong&gt;
Maybe. Not the highest prio on my roadmap but shouldn't be a big deal to provide it. Feel free to contribute.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/a1b31b28d97d8510ba671737e0a6dc3c525fb298212ab6c279edeb9d5f142baa/68747470733a2f2f6d656469612e67697068792e636f6d2f6d656469612f50495241434d326a58524150316c373774742f67697068792e676966"&gt;&lt;img src="https://camo.githubusercontent.com/a1b31b28d97d8510ba671737e0a6dc3c525fb298212ab6c279edeb9d5f142baa/68747470733a2f2f6d656469612e67697068792e636f6d2f6d656469612f50495241434d326a58524150316c373774742f67697068792e676966" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Simple Usage&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;npm i unglitch&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class="highlight highlight-source-ts notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;// Filename: store.ts&lt;/span&gt;
&lt;span class="pl-k"&gt;type&lt;/span&gt; &lt;span class="pl-smi"&gt;GlobalState&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-c1"&gt;user&lt;/span&gt;?: &lt;span class="pl-kos"&gt;{&lt;/span&gt;
    &lt;span class="pl-c1"&gt;prename&lt;/span&gt;: &lt;span class="pl-smi"&gt;string&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
    &lt;span class="pl-c1"&gt;lastname&lt;/span&gt;: &lt;span class="pl-smi"&gt;string&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
    &lt;span class="pl-c1"&gt;mail&lt;/span&gt;?: &lt;span class="pl-smi"&gt;string&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
  &lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;

&lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-s1"&gt;state&lt;/span&gt;: &lt;span class="pl-smi"&gt;GlobalState&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-c1"&gt;user&lt;/span&gt;: &lt;span class="pl-kos"&gt;{&lt;/span&gt;
    &lt;span class="pl-c1"&gt;prename&lt;/span&gt;: &lt;span class="pl-s"&gt;"Spongebob"&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
    &lt;span class="pl-c1"&gt;lastname&lt;/span&gt;: &lt;span class="pl-s"&gt;"Squarepants"&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;

&lt;span class="pl-k"&gt;export&lt;/span&gt; &lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt; useStore&lt;span class="pl-kos"&gt;,&lt;/span&gt; update &lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-en"&gt;create&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-smi"&gt;GlobalState&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="pl-s1"&gt;state&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class="highlight highlight-source-tsx notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;// Filename: MyApp.ts&lt;/span&gt;
&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-s1"&gt;useStore&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt; &lt;span class="pl-s1"&gt;update&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;"./store"&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-k"&gt;function&lt;/span&gt; &lt;span class="pl-smi"&gt;App&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-kos"&gt;[&lt;/span&gt;&lt;span class="pl-s1"&gt;prename&lt;/span&gt;&lt;span class="pl-kos"&gt;]&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/activenode/unglitch"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;&lt;code&gt;unglitch&lt;/code&gt; is pretty similiar to &lt;code&gt;zustand&lt;/code&gt; and it &lt;em&gt;kinda&lt;/em&gt; uses the same technology. However built-in with the State Management do come locked calls. &lt;/p&gt;

&lt;p&gt;It's easiest explained with the following code snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;update&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./my-store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;releaseLock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;realtimeData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// we can check the live data outside of the lifecycle  &lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;realtimeData&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ..fetch some data...&lt;/span&gt;
    &lt;span class="c1"&gt;// ...then update it:&lt;/span&gt;
    &lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="cm"&gt;/** your data here */&lt;/span&gt;&lt;span class="p"&gt;]});&lt;/span&gt;

    &lt;span class="c1"&gt;// release the lock so it can be called again&lt;/span&gt;
    &lt;span class="nx"&gt;releaseLock&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LOCK_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FETCH_DATA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lockedCall&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;lockedCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt; 

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;LOCK_TOKEN&lt;/code&gt; is grabbed automatically when you run the &lt;code&gt;lockedCall&lt;/code&gt;. If the &lt;code&gt;LOCK_TOKEN&lt;/code&gt; is not present you will be facing an error so don't worry about forgetting it. Sure, you could still manually call that function but as long as you run &lt;code&gt;lockedCall&lt;/code&gt; it will take care of running it only once.&lt;/p&gt;

&lt;p&gt;The function that is being called always receives a function as first parameter that will free the lock again and the second parameter is exactly the provided state data in &lt;code&gt;useStore&lt;/code&gt; so here it is &lt;code&gt;state.data&lt;/code&gt;.&lt;br&gt;
The difference is however: The function that is being called receives the &lt;code&gt;realtimeData&lt;/code&gt; and not the data that is currently available in the lifecycle. This allows you to check if you need to fetch data or not.&lt;/p&gt;

&lt;p&gt;Besides this lock mechanism the store works pretty much similiar to &lt;code&gt;zustand&lt;/code&gt;. Check it out.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>react</category>
    </item>
    <item>
      <title>The Amazon Interview Experience</title>
      <dc:creator>David Lorenz</dc:creator>
      <pubDate>Mon, 28 Feb 2022 18:08:34 +0000</pubDate>
      <link>https://dev.to/activenode/the-amazon-interview-experience-83l</link>
      <guid>https://dev.to/activenode/the-amazon-interview-experience-83l</guid>
      <description>&lt;p&gt;First I declined to write this article but I got the feedback that people are truly interested in interviewing processes about the Big Ones (FAANG = Facebook, Amazon, Apple, Netflix, Google...) so here we go ♥️&lt;/p&gt;

&lt;p&gt;tl;dr: This Post explains how I got interviewed by Amazon and eventually got an offer. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why I declined
&lt;/h2&gt;

&lt;p&gt;Before the question pops up let me reveal upfront: The offer was legit. However I declined the Amazon offer. Simply because I had a counter-offer at the time which was kinda identical and it didn't require me to relocate - which I didn't want to in pandemic times of embracing remote work more and more (only to notice I am going to be in Home Office in a different city).&lt;/p&gt;

&lt;h2&gt;
  
  
  Who the F cares?
&lt;/h2&gt;

&lt;p&gt;This is for people that want to understand how interviews in bigger companies work and for people that want to understand if it is "impossible" to get in. It's not. And you got not much too lose for trying. &lt;/p&gt;

&lt;h2&gt;
  
  
  Take it with a grain of salt
&lt;/h2&gt;

&lt;p&gt;Please be aware of the fact that I report all of this from a perspective of someone that's been long time into tech. But that doesn't mean I know all the algorithms. In fact I barely know algorithms - sure it would be easy to re-learn those but I just didn't need to by now (business-wise). I'm certainly not learning any Dijkstra Algorithm by heart for an interviewing process. If they want me to then I'm out, for sure. &lt;/p&gt;




&lt;h2&gt;
  
  
  The &lt;strong&gt;Flow&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I got contacted by a recruiter person for Amazon when I was working for Mercedes-Benz.io so maybe that was the reason, maybe not - who knows. But at the end of the day, the overall process would've been the same if I had applied or if you are recruited - there's no difference.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Having talked to the recruiter I was like "Yeah sure, Amazon, why not give it a try?" (I am never &lt;em&gt;hyped&lt;/em&gt; about a job since being hyped upfront might be the mother of disappointment. Amazon and Google are also just companies with people like you and me). &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The process explanation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Talk to the recruiter&lt;/li&gt;
&lt;li&gt;Have a Codility Test&lt;/li&gt;
&lt;li&gt;Run through a Live-Coding Test&lt;/li&gt;
&lt;li&gt;Meet the Team ~6 hours&lt;/li&gt;
&lt;li&gt;The offer&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  3.1. The Recruiter Call
&lt;/h2&gt;

&lt;p&gt;I don't remember every single bit of the call but the internal Recruiter was a different one than the one that initially got in touch with me. Seems like they do split the work in that regard. The Recruiter was pretty friendly and available for all questions that I had upfront. He explained that there's gonna be a Coding Test and if that succeeds they will continue. I'm honestly not sure anymore if he exactly told me WHAT kind of process will follow but I am certain he would have if I had asked.&lt;/p&gt;

&lt;h2&gt;
  
  
  3.2. Codility Test
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.codility.com/"&gt;Codility&lt;/a&gt; is a famous tool for big companies to pre-select candidates. tldr: If you fail those tests fatally there is a good chance no person will even look at it. The tasks can vary extremely in complexity and type of challenge. But these can be chosen by the company. Codility is a time-limited Challenge. This was indeed stressful for me because knowing that you have limited time and there is no one to explain to what you might be currently stuck at stressed me out. Also there is no pause button. When you start it the time runs. The timespan was 125mins. I think I finished after like 70mins but eventually left everything open to check over and over again every line of code so I stopped at around 90mins or so.&lt;/p&gt;

&lt;p&gt;The tasks are extremely clear. There is not much room for interpretation. Of course you can google stuff but that doesn't mean that your code will get better. Take care of your code structure, make it readable and even more so code properly. E.g. if Codility says that you can assume that the input is a number then don't build something like &lt;code&gt;if (isNumber)&lt;/code&gt;. You waste your time and probably worsen your score.&lt;/p&gt;

&lt;p&gt;Codility DOES provide a little bit of insights if you're completely wrong or not. Because there is a good amount of tests already added that you are free to run - and that really helps reassuring that you didn't code complete bullshit. But: Don't be fooled. Only because the 10 provided Tests run successfully doesn't mean that ALL TESTS will run - and you don't see all tests.&lt;/p&gt;

&lt;p&gt;The Tasks I got weren't "out-of-universe" challenges. I felt like they were "real use-cases" which actually made the tasks fun. But still stressful.&lt;/p&gt;

&lt;h2&gt;
  
  
  3.3. Livecoding
&lt;/h2&gt;

&lt;p&gt;Apparently my Codility challenge was very convincing so I got invited to the next step: A Coding Challenge with an actual person - Livecoding. I am not as stressed with those because meeting actual humans means that you are able to explain what you're doing. If you hate Livecoding then you will have a bad time honestly. &lt;/p&gt;

&lt;p&gt;I am anxious as well in some situations but you simply have to get over it. There is a company that potentially wants to hire you and you have to learn to not get a blackout. It's a person in front of you, not a killer. Maybe it helps to think of Teddy Bears instead, I don't know. If you do get blackouts with all live-codings then the really only thing I can recommend is: Seek help / consult the internet for tricks to overcome it. There is a lot of lovely tips out there. Seeking help is good and no sign of weakness. Everybody has their own weaknesses. &lt;/p&gt;

&lt;p&gt;Back to topic. The Livecoding was open for any language. The person asked me to process a few things and how I would approach certain things programmatically. &lt;/p&gt;

&lt;p&gt;I wasn't pinpointed to JavaScript. I could have equally used Python. The online editor provided supported syntax of multiple languages. However it didn't have a "Run" button which was kinda odd for me. So you couldn't confirm if what you're doing is "correct" - but maybe that was intentionally to pinpoint you more to explanations than actual results. You have to talk and explain. Talk a lot! You can't ever talk too much. Every single step of thinking: Say it. This allows the other person to follow your steps. Don't just be quiet and say "Here that's the result".&lt;/p&gt;

&lt;p&gt;Also I had been asked a few other questions but the recruiter  prepared me upfront to read the Amazon STAR Technique (Find Info here: &lt;a href="https://www.amazon.jobs/en-gb/landing_pages/in-person-interview"&gt;https://www.amazon.jobs/en-gb/landing_pages/in-person-interview&lt;/a&gt;). So it wasn't anything that came "unexpected" really.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Again&lt;/strong&gt;: The Recruiter is your go-to person. See that person as your personal trainer for the processes. There is no "dumb" question - well maybe if you ask them what you should eat today, maybe that would be a "dumb" question.&lt;/p&gt;

&lt;h2&gt;
  
  
  3.4. Meet the Team
&lt;/h2&gt;

&lt;p&gt;I was honestly right before backing off. I was told the next step would be to have &lt;em&gt;several&lt;/em&gt; interviews in an overall timespan of &lt;strong&gt;6 hours&lt;/strong&gt;. I hate long-running interview processes. I appreciate it when companies give you options to talk but I have other stuff to do and lots of other people would've to take vacation days for that. &lt;/p&gt;

&lt;p&gt;What did I do? &lt;strong&gt;I told the Recruiter&lt;/strong&gt;. Honesty is what's important for you and the company! I said: "I don't wanna be rude but I never in my life was thrown into such a huge process and I feel like I'm backing off after the first hour if I find it intimidating or not helpful".&lt;/p&gt;

&lt;p&gt;The Recruiter was again very nice and said "Fair points, David." and continued to explain me why they do this.&lt;/p&gt;

&lt;p&gt;The idea behind it is to &lt;em&gt;actually&lt;/em&gt; meet the team and have the different people in the team ask questions that might be more related to the field they are working in. Not only that but also it provides the candidate the option to get in touch with more than just the "gatekeepers of the company" (HR people).&lt;/p&gt;

&lt;p&gt;Eventually, I found it nice because I liked the idea of meeting the team before making decisions. &lt;br&gt;
But it wasn't really a meet-and-greet. It was very friendly but serious at the same time (some more serious, some funnier).&lt;/p&gt;

&lt;p&gt;In one Interview (I think there were 6 in total, one hour each) I was asked to do a little bit of Systems Design which I found a legit task for the role I was going for (Senior Frontend Engineer).&lt;/p&gt;

&lt;p&gt;There were never more than 2 people from Amazon in each session. Mostly one asking, one ghosting (ghosting = learning how to do interviews).&lt;/p&gt;

&lt;p&gt;The Team also asked me questions regarding the &lt;a href="https://www.amazon.jobs/en-gb/principles"&gt;Leadership Principles&lt;/a&gt; of Amazon, especially in relation to my previous experience. Since I have a lot of experience I prepared those questions very well as well as I could.&lt;/p&gt;

&lt;p&gt;The exact questions really don't matter because they are different each time anyway but they're in the format of "When was the last time you got a difficult challenge and how did you tackle it?".&lt;/p&gt;

&lt;p&gt;But &lt;strong&gt;none&lt;/strong&gt; of it like: "Where do you see yourself in 10 billion years?" - fortunately.&lt;/p&gt;

&lt;p&gt;If you don't have a lot of work experience it might help to find relatable experiences within your life and answer with those but I would clarify with the internal recruiter upfront. The recruiter will certainly help you out with your concerns.&lt;/p&gt;

&lt;p&gt;At the end of the 6-hour session, I was kinda exhausted. Not in a negative way but it's still a long time in which you meet different people that all have questions.&lt;/p&gt;

&lt;p&gt;Normally that session would've been onsite. I was lucky enough for it to be online due to the Pandemic. And I also do think they should stick with keeping it online as I find it more convenient and avoid traveling (#environment).&lt;/p&gt;

&lt;h2&gt;
  
  
  3.5. The Offer
&lt;/h2&gt;

&lt;p&gt;The Recruiter wrote me first before sending over the offer like "David when's a good time to call you?". He said something like: "The team really liked you, you made an awesome impression and I would like to explain you the offer we have for you."&lt;/p&gt;

&lt;p&gt;The Offer was good - especially if you consider its overall compensation package. I think it was an increase of about 15% salary as compared to my job at Mercedes-Benz.io at that time. It was slightly below my requested salary but that's okay because of what I'll explain now.&lt;/p&gt;

&lt;p&gt;The Package included a signing bonus which would definitely cover a good part of moving costs including new furniture.&lt;/p&gt;

&lt;p&gt;Far more interesting is the fact how they help you to get started. They want to free your thoughts from "doing all of the organizational stuff" &lt;/p&gt;

&lt;p&gt;I would get an individual that will help me find a flat -  so that person will literally take care of that so you can focus on the company - which is pretty neat.&lt;/p&gt;

&lt;p&gt;At Amazon, you will often get additional RSUs (Restricted Stock Units). Those are Stocks from the Company which are provided to you in parts over time. So a &lt;em&gt;random example&lt;/em&gt; of RSUs is: You get 50 RSUs promised now and you will get 10 after 6 months, another 10 after 12 months, etc. And since one Stock at Amazon is worth a lot it comes down to a very awesome compensation package the longer you stay.&lt;/p&gt;

&lt;p&gt;RSUs are also a very good benefit keeping you in the company for a longer time.&lt;/p&gt;

&lt;p&gt;Last but not least they will help your significant other to find a new job as well - if required. So they will make sure that you can move carefree together with your family. Which I indeed really appreciated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;I hope this helps understanding potential interviewing workflows in big companies. To understand general recommendations about interviewing please also read my other post &lt;a href="https://blog.activenode.de/mastering-frontend-interviews"&gt;Mastering Frontend Interviews&lt;/a&gt; which is definitely also for non-Frontend people.&lt;/p&gt;

&lt;h2&gt;
  
  
  Questions?
&lt;/h2&gt;

&lt;p&gt;Post all your questions here in the comments. I'd also appreciate to connect on Twitter: Find me on Twitter &lt;a href="https://twitter.com/activenode"&gt;@activenode&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yeah, I think that's it. Hope you liked it.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>career</category>
      <category>motivation</category>
    </item>
    <item>
      <title>beamco.de: A new code snippet creator is in town 🌈</title>
      <dc:creator>David Lorenz</dc:creator>
      <pubDate>Sun, 13 Feb 2022 20:16:44 +0000</pubDate>
      <link>https://dev.to/activenode/beamcode-a-new-code-snippet-creator-is-in-town-4d7a</link>
      <guid>https://dev.to/activenode/beamcode-a-new-code-snippet-creator-is-in-town-4d7a</guid>
      <description>&lt;p&gt;When the sun was shining I could hardly read my own Code Snippets shared on Twitter as they lacked contrast and thickness. &lt;/p&gt;

&lt;p&gt;I know there is carbon and ray but those didn't exactly fit my needs of a fancy theme, &lt;em&gt;simplicity&lt;/em&gt; and readability.&lt;/p&gt;

&lt;p&gt;So I decided to go and create a new one and here we go:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://beamco.de" rel="noopener noreferrer"&gt;beamco.de&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsiad9w2hoaldm37q1w98.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsiad9w2hoaldm37q1w98.png" alt="Sample image containing code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have constructive feedback and ideas for improvement please reach out to me.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>tooling</category>
      <category>productivity</category>
    </item>
    <item>
      <title>`float:left` is not dead 🙇‍♂️</title>
      <dc:creator>David Lorenz</dc:creator>
      <pubDate>Thu, 23 Dec 2021 10:11:03 +0000</pubDate>
      <link>https://dev.to/activenode/floatleft-is-not-dead-384i</link>
      <guid>https://dev.to/activenode/floatleft-is-not-dead-384i</guid>
      <description>&lt;p&gt;In the Tech Community in the last few years there have been strong opinions on things. But some things are not opinions. Some things can simply be explained by facts.&lt;/p&gt;

&lt;p&gt;One of it is the assumption that &lt;code&gt;display: flex&lt;/code&gt; or &lt;code&gt;display: grid&lt;/code&gt; are alternatives for floating. &lt;strong&gt;They are not&lt;/strong&gt;. Period.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/l41lIsOThQpma23wA/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/l41lIsOThQpma23wA/giphy.gif" alt="Drake Dancing" width="452" height="254"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;At this point you &lt;em&gt;might&lt;/em&gt; think that I am crazy but let me elaborate before you agressively type comments destroying your keyboard.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;display: flex&lt;/code&gt; is born out of a requirement that CSS hasn't solved before: Proper Layouting. In other words: Using &lt;code&gt;display: block; float: ...&lt;/code&gt; for layouts always was a workaround. Same as in the old times when we used &lt;code&gt;&amp;lt;table ..&amp;gt;&lt;/code&gt; for layouting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Okay but then why should I still use &lt;code&gt;float: ...&lt;/code&gt; ?
&lt;/h2&gt;

&lt;p&gt;As I said: It was never built for "layouting" in the sense of what we understand as "layouting" today. Such that we have to get back to what it's actually supposed to do.&lt;/p&gt;

&lt;p&gt;As the term &lt;code&gt;float&lt;/code&gt; already states it is supposed to let things &lt;code&gt;float&lt;/code&gt; (no shit sherlock) as opposed to &lt;code&gt;display: flex&lt;/code&gt; which &lt;strong&gt;cannot&lt;/strong&gt; let things float. So it's an awesome helper to wrap text around any kind of &lt;code&gt;figure&lt;/code&gt; which makes up for a very awesome reading experience if used correctly.&lt;/p&gt;

&lt;p&gt;The pragmatic explanation will be done via my &lt;a href="https://codepen.io/activenode/pen/XWeeZGe"&gt;CodePen&lt;/a&gt; where Drake will help you to understand better:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/activenode/embed/XWeeZGe?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Reach out to me via Follow-Up Questions if you have any. 🔥&lt;/p&gt;

</description>
      <category>css</category>
      <category>frontend</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Mastering Frontend Interviews - For real</title>
      <dc:creator>David Lorenz</dc:creator>
      <pubDate>Tue, 21 Dec 2021 21:32:17 +0000</pubDate>
      <link>https://dev.to/activenode/mastering-frontend-interviews-for-real-3pkl</link>
      <guid>https://dev.to/activenode/mastering-frontend-interviews-for-real-3pkl</guid>
      <description>&lt;h2&gt;
  
  
  Why should you even listen to me?
&lt;/h2&gt;

&lt;p&gt;I am a Frontend Architect with People Management Experience (So besides the technical experience I was happy to be working together with People Management, leading peers, building up interview processes etc.)&lt;/p&gt;

&lt;p&gt;Amazon, Mercedes-Benz.io, JvM, nodus medical and many more gave me the opportunity to work for them (meaning: I got an actual offer). Besides those few mentioned there were &lt;strong&gt;innumerable&lt;/strong&gt; amounts of other interviews I was allowed to be part of - both as candidate as well as interviewer. I don't like to have tunnel vision when it comes to jobs. I do like to check opportunities from time to time because that helps me understanding the options out there as well as helps me staying in the routine of interviews.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this post is about
&lt;/h2&gt;

&lt;p&gt;This post is not about which exact weird technical challenge you should prepare for (No you don't have to learn the Quicksort implementation in 10 languages by heart other than if you are applying for a company that's name is "Quicksort in 10 languages Inc"). This is about understanding what's behind the curtains of every good interview. I won't be talking about salary in this post because salary is just something so unique that it wouldn't fit the overall context of this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  The CV and your application letter
&lt;/h2&gt;

&lt;p&gt;I appreciate your effort but honestly no one is special enough for anyone to read a book load of pages about what you've been doing and what kind of food you eat at 5am in the morning.&lt;/p&gt;

&lt;p&gt;Most of the companies love a one page CV, one page application letter. If you say "that doesn't fit on simply one page" then you are showing your incapability of prioritisation. I know you want to show everything but the company just doesn't have the time to read the story of your life.&lt;/p&gt;

&lt;p&gt;So if you have worked with 30 different stacks and technologies then you are very much kicking yourself out of being even invited if you list all of those next to each other. Being a FE Developer you should be highlighting your primary FE Skills. If you have worked with Cloud Technologies and Backend then that's cool but keep it short e.g. "Also I have worked with a lot of cloud and backend technologies and I love getting my hands dirty at databases". &lt;/p&gt;

&lt;p&gt;Also don't send the exact same letter for every single position. If the role you are applying for states "You will be working on an Angular 9 Product" then it is helping you a lot if you highlight that technology first. This can obviously lead to the fact that you &lt;strong&gt;should&lt;/strong&gt; mention your cloud technologies if the role specifically states that this is beneficial - if not, leave it out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prepare
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prepare structurally
&lt;/h3&gt;

&lt;p&gt;If you get invited to an interview and the interview process is professional then the responsible person is superhappy to tell you how the interview will be structured - if you ask for it. If you don't ask for it you will literally be expecting anything.&lt;/p&gt;

&lt;p&gt;Send them a nice mail or call them and ask "Could you tell me how the interviewing process is structured? Will there be time for questions and will there be a live challenge?" etc.&lt;/p&gt;

&lt;p&gt;There is nothing wrong with asking how the interview will be processed and what to expect - every client can be different so every interview can have different workflows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prepare contentual
&lt;/h3&gt;

&lt;p&gt;I remember those times of "inform yourself about what the company does". IMO this is not necessary anymore. No one will reject to hire you because you didn't know that the company has 120 employees - so forget about that stuff.&lt;/p&gt;

&lt;p&gt;But you should still prepare and inform yourself about the company to be able to ask proper questions and hence impressing with showing your underlying motivation.&lt;br&gt;
This allows both of you to see if it is a fit or not. You don't necessarily have to "lie" that you "love" the products the company creates. It is sufficient if you like its process around the development part that is part of the products - on which you will work.&lt;/p&gt;

&lt;p&gt;If you read on the roles description: "We are a high performing team" and you feel that this sounds like "we are doing a lot of over-hours" then write it down and prepare to ask if they can clarify what "high performing team" means. &lt;/p&gt;

&lt;p&gt;But not just that. Ask what &lt;strong&gt;exactly&lt;/strong&gt; you'd be doing. That is a completely valid question. As in "So I read you are working for multiple clients here, how does a typical Frontend Coders Day/Week look like in your company?".&lt;/p&gt;

&lt;p&gt;Also ask about the culture which helps both of you identifying if this is what you are searching for / they are searching for.&lt;/p&gt;

&lt;p&gt;But first and foremost: Don't start asking questions in the beginning like "Ok before we start I got some questions". I did that sometimes if I felt the urge of importance but I still do not recommend it as it can have an impression of being rude if you are not being very diplomatic. So rather don't and wait for the interviewer to give you space for questions. &lt;/p&gt;

&lt;p&gt;If the interviewer does not give you space for questions it feel encouraged to say: "Thanks for this interviewing process so far. [...] May I ask some questions about the company and the job role?".&lt;/p&gt;

&lt;p&gt;No question is a "dumb" question if stated friendly and with honest interest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's talk about Interviewing
&lt;/h2&gt;

&lt;p&gt;Coders be like "Oh shit, what if I can't answer this?". And then they might fall into a deep black hole if there was a question that they felt uncomfortable with and at that point I have seen many interviews failing.&lt;/p&gt;

&lt;p&gt;The Problem is that many don't understand what the point of interviewing is. It is checking your capabilities of solving problems at the base of your current level given the expectations that you set. That means: I can ask the EXACT same questions in an interview to a senior as to a junior but I'd be expecting completely different outcomes and both could be hired respectively.&lt;/p&gt;

&lt;p&gt;What's the trick? Act curious instead of being challenged. Try to imagine all of it less as a "test" and more like a "tell me more discussion". And not only that. Think and explain in pseudocode if you can't provide legit facts.&lt;br&gt;
Literally the worst thing you can say is "I don't know". A few "I don't know"'s and you are out. And not because you didn't know but because you showed that you aren't even trying to solve the problem - not even slightly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenarios
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Scenario 1: Sorting Algorithm Question
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Interviewer&lt;/strong&gt;: "Do you know which is the fastest Sorting Algorithm?" &lt;br&gt;&lt;br&gt;
&lt;strong&gt;You&lt;/strong&gt;: "Sorry, no" - Awkward silence 🙅🏽‍♀️😐&lt;/p&gt;

&lt;p&gt;This is close to ending the meeting soon. Here is a proposal of being curious instead:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;: "I don't have that at hand but I would love to know where the answer to this would help within your products scope if I may. I'd be assuming that JS engines would to their best to have a fast sorting algorithm. If that wouldn't be enough I would make sure to research properly how to improve the performance if there is a need detected." - 🤗&lt;/p&gt;

&lt;h4&gt;
  
  
  Scenario 2: &lt;code&gt;typeof null&lt;/code&gt; Question
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Interviewer&lt;/strong&gt;: "Do you happen to know what &lt;code&gt;typeof null&lt;/code&gt; is?"&lt;/p&gt;

&lt;p&gt;Even if you know the answer to this question (it is 'object') then be rest assured that this is not a key-value test. These questions normally come with a follow up question. There is always "context" around a question.&lt;/p&gt;

&lt;p&gt;So say you didn't know that &lt;code&gt;typeof null&lt;/code&gt; equals &lt;code&gt;object&lt;/code&gt;. Then the worst thing you can do is random guessing. This is not playing lotto and the interviewer doesn't like to be played. They will notice.&lt;br&gt;
If you have a really good guess or you slightly remember something then explain your guess and let the interviewer follow your thoughts: &lt;strong&gt;Think out loud&lt;/strong&gt;! Nothing worse than awkward silence because you think you need to think silently.&lt;/p&gt;

&lt;p&gt;If you have no clue then simply say something like: "I am pretty sure there is a good reason you asked this. Would you mind to tell me the solution and eventually have a follow-up question on this?"&lt;/p&gt;

&lt;p&gt;Even though not knowing you are showing your willingness to go with further questions in this context after being told the solution. A very much follow-up question probably is: "Can you imagine this check being problematic?" - Now, same rules: Start to think loud. Speak up what you think - as if you were googling. Start one by one: "Okay so if &lt;code&gt;typeof null&lt;/code&gt; is &lt;code&gt;object&lt;/code&gt; then that implies that a nullish/falsy value can be seen as object if checked with &lt;code&gt;typeof&lt;/code&gt;. That means that one shouldn't check for something being an object only with &lt;code&gt;typeof&lt;/code&gt; because it could be also &lt;code&gt;null&lt;/code&gt;." - You are literally explaining it to yourself AND to the interviewer and hence showing your skills to solve problems at hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Seniors, Seniors, Seniors
&lt;/h2&gt;

&lt;p&gt;There is some addendum that is important for Senior Frontend Engineers. The huge difference between Juniors and Seniors is that a Senior actually should be able to answer most of the questions asked at the expert level they &lt;em&gt;present themselves with&lt;/em&gt;. And by that I am not saying "They must know every single property / function by heart".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does that mean?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With Juniors I mostly ask the same kind of questions. With Seniors that's different. I know you cannot keep up with every single technology but you must be extremely proficient in a specific technology and the basics (HTML, JS, CSS) so tldr: Your primary skill of the last project + Basics.&lt;/p&gt;

&lt;p&gt;That is why I completely adapt interviews with Seniors &lt;em&gt;on-demand&lt;/em&gt;. I do ask the Seniors beforehand about their proficiencies. If the person is being honest saying "I think I missed out one some CSS in the last 2 years but I am really good at XYZ" then I am happy to be gentle with CSS questions and focus more on XYZ (as stated above, it's hard to keep up with everything). If a senior tells me that the proficiency lies in Angular I will focus on asking Angular-specific questions. Even if it is a position as a React Developer. The reason is simple: If the Senior can deeply elaborate on my questions considering the provided proficiency on expert level then I have no doubt that this person has the capability of understanding the architecture of another framework.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And now comes the pitfall&lt;/strong&gt;: Seniors often don't expect me to ask &lt;em&gt;basic&lt;/em&gt; questions which is honestly shocking for me every single time. And with &lt;em&gt;basic&lt;/em&gt; I don't mean "Which exact CSS property will let boxes to be aligned next to each other" -  it is sufficient to know that &lt;code&gt;display: flex&lt;/code&gt; exists and that you can do a lot of alignments whichever way with it. Details: Google.&lt;/p&gt;

&lt;p&gt;But if a senior starts telling me that &lt;code&gt;float: left&lt;/code&gt; is a good way nowadays to align boxes then it shows that that person must've ignored every single news on the internet in the last past years.&lt;/p&gt;

&lt;p&gt;Also one of my favourite questions for seniors is to explain me the arrow function. And if a senior says "It's a function but with a different syntax" then this is a &lt;strong&gt;definite reason to be rejected&lt;/strong&gt;. For good reason: The arrow function binds context - and it binds it in a way that is unchangeable. So even the functions &lt;code&gt;.bind&lt;/code&gt;, &lt;code&gt;.apply&lt;/code&gt; and &lt;code&gt;.call&lt;/code&gt; cannot change that context. But they also wouldn't throw an error. So if a senior does not know that an arrow function changes context immutably then that Senior would've a hard time debugging if there was a legacy library that would be making use of older functions but now providing arrow functions leads to problems - without throwing errors.&lt;/p&gt;

&lt;p&gt;In my experience Seniors often oversell. So if you are insecure about being Senior then rather sell as Intermediate and surprise with potential Senior knowledge than sell as Senior and surprise with disappointment. When I do ask "How would you rank your JS knowledge on a scale from 1 to 10" they often go to 8 or 9. Because they don't do much of self-reflection anymore. That backfires. And this happens in a &lt;strong&gt;lot&lt;/strong&gt; of interviews. And this is something that really only happens with Seniors, rarely with Intermediates or Juniors. The problem is that seniors are often doing something very specific in a project. And more often than never they are solving the product needs with that specific solution and that might be perfectly fine and in a way that is senior'ish. The problem is that they forget that they are often "living in a technology tunnel" without learning new things and keeping up with how JS evolves. But they &lt;strong&gt;must&lt;/strong&gt; make sure to keep up with the basics. &lt;br&gt;
And not just that. They also must ensure to not forget the basics. Because if they need to dig deeper (not every 3d-party library is perfectly working) they might need to be working outside of the scope of the framework with pure JavaScript. And that shouldn't be a huge challenge for them.&lt;/p&gt;

&lt;p&gt;My suggestion here is simple: Stay humble and at least subscribe to 1 JavaScript Newsletter. That should already be a good start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rejection Handling
&lt;/h2&gt;

&lt;p&gt;Rejections are hard. As always in life. And you must prepare for being rejected. Expect to be rejected. &lt;br&gt;
And if you get rejected then see it as just one step of a &lt;em&gt;potentially large&lt;/em&gt; but definitely &lt;em&gt;finite&lt;/em&gt; ladder. Because every single rejection can be seen as "a practice step for the next interview". This is hard but crucial for your mental wellbeing and for getting better.&lt;/p&gt;

&lt;p&gt;Also don't just be mad. Answer all rejections with the question for feedback: "Thank you for having invited me. Although it wasn't a fit I would be extremely happy if you could provide me more insights and feedback that will allow me to improve". You'd be surprised how much feedback you will get - Sure, there's exceptions but the worst thing that can happen is that you don't get an answer.&lt;/p&gt;

&lt;p&gt;Feedback gives you useful insights what exactly was wrong. &lt;br&gt;
Many don't ask for feedback and simply lower their self-esteem with the implication of "simply not being good enough" instead of acknowledging that it's only a step of becoming better.&lt;/p&gt;

&lt;h2&gt;
  
  
  A last note
&lt;/h2&gt;

&lt;p&gt;Try to be yourself. Yes it can happen to "struggle" oneself into a position but that doesn't come with a bunch of happiness. &lt;/p&gt;

&lt;p&gt;Sometimes it just isn't a fit. Everyone's different, everyone's special. Just like Friends and Relationships: Not all people bond well together. That's fine.&lt;/p&gt;




&lt;p&gt;Phew. That was a bunch of text. I hope it helps.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>interview</category>
    </item>
    <item>
      <title>JavaScript Promises tl;dr</title>
      <dc:creator>David Lorenz</dc:creator>
      <pubDate>Mon, 20 Dec 2021 10:48:23 +0000</pubDate>
      <link>https://dev.to/activenode/javascript-promises-tldr-41e6</link>
      <guid>https://dev.to/activenode/javascript-promises-tldr-41e6</guid>
      <description>&lt;p&gt;A superquick overview of Details about Promises. Stop the talk, let's start getting into it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Promises always chain
&lt;/h2&gt;

&lt;p&gt;If &lt;code&gt;then&lt;/code&gt; or &lt;code&gt;catch&lt;/code&gt; return a value that is NOT a promise then it will be wrapped into a new promise and chained and forwarded to the next one. That means starting from a &lt;code&gt;catch&lt;/code&gt; you can return a value and &lt;code&gt;.then&lt;/code&gt; it.&lt;/p&gt;

&lt;p&gt;All of the samples here will output &lt;code&gt;Hello World1&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;appendWorld&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; World`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;appendOne&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;1`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;appendWorld&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;appendOne&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;appendWorld&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;))).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;appendOne&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;appendWorld&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;appendOne&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Blogging&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;appendWorld&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;appendOne&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  finally
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;finally&lt;/code&gt; cannot return a value that can be chained. Kind of implied by it's name. It is called no matter if another &lt;code&gt;.then&lt;/code&gt; or &lt;code&gt;.catch&lt;/code&gt; was called before. When the Promise was fulfilled in any way then &lt;code&gt;.finally&lt;/code&gt; is called. Good for cleanup work.&lt;/p&gt;

&lt;p&gt;E.g.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Catch is called&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;finally called&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;outputs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Catch is called
finally is called
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Errors inside a promise are forwarded to &lt;code&gt;.catch&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hey&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;i am never called&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Multiple &lt;code&gt;.catch&lt;/code&gt; statements are useful
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;much rejection&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;i can continue doing stuff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;another one&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;catching the second chain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;async&lt;/code&gt; functions are Promise Wrappers
&lt;/h2&gt;

&lt;p&gt;The following code statements have the same effect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// async&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;foobar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// non-async&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;foobar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;await&lt;/code&gt;ing promises must be done carefully
&lt;/h2&gt;

&lt;p&gt;If you &lt;code&gt;await&lt;/code&gt; a promise then you need to be careful when checking for "success" because errors can be hidden.&lt;/p&gt;

&lt;p&gt;See the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;foobar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error thrown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;foobar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// This does not imply success ⚠️👩‍🚀&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="c1"&gt;// This does not imply an error case&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem is that the provided promise is properly caught. Referring back to promise-chaining now the result of the &lt;code&gt;catch&lt;/code&gt; statement can be chained, hence &lt;code&gt;new Error...&lt;/code&gt; is the resulting object if you'd call &lt;code&gt;.then&lt;/code&gt; on it. And that is simply the same as calling &lt;code&gt;await&lt;/code&gt; on it. So here &lt;code&gt;foobar&lt;/code&gt; contains &lt;code&gt;new Error...&lt;/code&gt; which is an object which when checking for &lt;code&gt;if(foobar)&lt;/code&gt; returns true although an error was thrown. So you need to be aware of what your promises return.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;Promise.race&lt;/code&gt; and &lt;code&gt;Promise.any&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Both &lt;code&gt;race&lt;/code&gt; and &lt;code&gt;any&lt;/code&gt; complete with the Promise whichever is first. &lt;strong&gt;But&lt;/strong&gt; there is a big difference: &lt;code&gt;race&lt;/code&gt; finishes  with the first Promise to &lt;strong&gt;EITHER&lt;/strong&gt; resolve &lt;strong&gt;OR&lt;/strong&gt; reject whilst &lt;code&gt;any&lt;/code&gt; finishes only with the first actually resolved Promise.&lt;/p&gt;

&lt;p&gt;In this &lt;code&gt;Promise.race&lt;/code&gt; sample the error Promise wins because it is first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nb"&gt;Promise&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;race&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;promise1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;promise2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;resolved&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this &lt;code&gt;Promise.any&lt;/code&gt; sample the resolved Promise wins because it is the first to actually resolve:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nb"&gt;Promise&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;promise1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;promise2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;resolved&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Promise.all
&lt;/h2&gt;

&lt;p&gt;This one is pretty intuitive: It either resolves when ALL promises are resolved OR it rejects when one of the promises is rejected.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// outputs ['one', 'two']&lt;/span&gt;
&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;one&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;two&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resultArray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resultArray&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// outputs 'error'&lt;/span&gt;
&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;one&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;two&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;()])&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resultArray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resultArray&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Don't be a pr*ck: Frontend Engineers and Accessibility</title>
      <dc:creator>David Lorenz</dc:creator>
      <pubDate>Mon, 20 Dec 2021 08:54:44 +0000</pubDate>
      <link>https://dev.to/activenode/dont-be-a-prick-frontend-engineers-and-accessibility-1m8m</link>
      <guid>https://dev.to/activenode/dont-be-a-prick-frontend-engineers-and-accessibility-1m8m</guid>
      <description>&lt;p&gt;Basic Accessibility isn't hard and it often isn't even a choice. What's hard is your damn stubbornness.&lt;/p&gt;




&lt;h2&gt;
  
  
  The following code will upset you
&lt;/h2&gt;

&lt;p&gt;You are a Frontend Developer. You start in a new company and you find code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;t&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Probably your first thought is: &lt;em&gt;WTF is this 💣&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Let's make it nice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listOfTasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetchTasks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;idAndTitleList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;listOfTasks&lt;/span&gt;
     &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;_id&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Did you feel the anger in the first sample?
&lt;/h3&gt;

&lt;p&gt;You felt it! You felt it because it would've been so damn easy to make it clean and readable. Hence it doesn't matter "why it came to be there". It matters that obviously no one prevented this code to be merged (missing guidelines or what not) and that you suffer in a sense of Developer Experience.&lt;/p&gt;

&lt;p&gt;Developer Experience to you is comparable to accessibility features to people that depend on it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is still a very much harmless example comparing how'd you feel if you were dependent on accessibility features because it wouldn't take much time on an atomic basis to improve the sites accessibility but you decided to not do it. And when the app/site is done it'd be a huge thing to adapt so you never do.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Accessibility is &lt;em&gt;not&lt;/em&gt; hard
&lt;/h2&gt;

&lt;p&gt;And often not a choice because:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you do recommend to NOT implement proper accessibility in your application you are actually consulting for something that has legal impact in a lot of countries now. So that's, first and foremost, a very very good reason to inform yourself and your colleagues about accessibility even more. &lt;br&gt;
 Source: &lt;a href="https://www.w3.org/WAI/policies/"&gt;https://www.w3.org/WAI/policies/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So if you are not developing on / in / for a lonely island then there is a good chance there is legal rules for it.&lt;/p&gt;

&lt;p&gt;I have heard this iffy saying so often. From Frontend Engineers, from Designers but especially from Product Owners and Managers trying to intrigue the engineers to "save time":&lt;/p&gt;

&lt;h3&gt;
  
  
  "We can do it later"
&lt;/h3&gt;

&lt;p&gt;Technically I don't see a problem in "doing it later". But let me take a metaphor for it: A fork lies on your table. You can put it in the shelf right now and your room looks amazingly clean. A rush of endorphines hits your body as it comforts with the tidyness. Easygoing. Now imagine you leave everything laying around in your room for a year. Now start cleaning the room - start even finding anything. You get the point...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/8csqNT29i6JTAGMrFT/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/8csqNT29i6JTAGMrFT/giphy.gif" alt="" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  "People with disabilities are not the target group anyways"
&lt;/h3&gt;

&lt;p&gt;This statement never holds true. Never. Not in any single case for any application that is used by more than 1 person.&lt;/p&gt;

&lt;p&gt;I have heard this in an automotive sector often saying "blind people cannot drive so how would a11y help?". &lt;/p&gt;

&lt;p&gt;Ehm well a blind person can still be controlling the digital sales part of the automotive sector. Just to have a very, very clear example. I could add thousands more if you want.&lt;/p&gt;

&lt;p&gt;Also bad accessibility always impacts pro users because it often comes with bad keyboard usage.&lt;/p&gt;

&lt;h3&gt;
  
  
  "Okay I'll add an &lt;code&gt;aria-label&lt;/code&gt; and some &lt;code&gt;alt&lt;/code&gt; attributes"
&lt;/h3&gt;

&lt;p&gt;Fk no. No no no. Don't just start adding random &lt;code&gt;aria-*&lt;/code&gt; attributes or alt/title tags if you do not know the impact. Start with the basics of understanding. Understanding is the crucial point of effortlessly using it and implementing it whilst coding. I would recommend myself but the problem is that I don't have any public sources on my own so I would need to lend you my brain. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There is an &lt;strong&gt;extremely&lt;/strong&gt; good free udacity course from Google (I really, really can recommend this):  &lt;a href="https://www.udacity.com/course/web-accessibility--ud891"&gt;https://www.udacity.com/course/web-accessibility--ud891&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Read this: &lt;a href="https://developers.google.com/web/fundamentals/accessibility/semantics-builtin/the-accessibility-tree"&gt;https://developers.google.com/web/fundamentals/accessibility/semantics-builtin/the-accessibility-tree&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Also you can start off at  &lt;a href="https://twitter.com/SaraSoueidan"&gt;Sara Soueidan&lt;/a&gt;. She also has published a new course which you will find a link on her Twitter account to.&lt;/li&gt;
&lt;li&gt;A good read is always MDN e.g. &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/heading_role"&gt;https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/heading_role&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Let me prove how easy it can be to improve Accessibility
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Understand that CSS impacts a11y: If you do &lt;code&gt;display: none&lt;/code&gt; on an element it is hidden both visually as well as in the &lt;strong&gt;Accessibility Tree&lt;/strong&gt; so your &lt;code&gt;&amp;lt;div style="display: none" aria-label="additional info only for screen readers"&amp;gt;...&lt;/code&gt; is useless.&lt;/li&gt;
&lt;li&gt;Ensure good ratio on your designs (built-in in the chrome inspector; there is also a lot of Sketch plugins for Designers e.g.) ; &lt;a href="https://webaim.org/resources/contrastchecker/"&gt;https://webaim.org/resources/contrastchecker/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Using a proper HTML structure is a very good start. HTML by definition (without adding CSS etc.) is perfectly accessible if correctly used. &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/HTML"&gt;https://developer.mozilla.org/en-US/docs/Learn/Accessibility/HTML&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;If you have fancy elements on your side that literally have no effect but looking cool (so content-wise not relevant) then simply hide em' semantically with &lt;code&gt;aria-hidden="true"&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;The &lt;code&gt;alt&lt;/code&gt; attribute on a &lt;code&gt;img&lt;/code&gt; tag is nothing that necessarily needs content. It needs content if the image shown is connected to the content. E.g.: You have a news article and you report about "More and more people visit the new shopping center". Now imagine there is an &lt;code&gt;img&lt;/code&gt; tag with a photo showing a lot of people in the shopping center. Then a good alt tag would be &lt;code&gt;alt="A lot of people standing in the new Shopping Center the city"&lt;/code&gt; . If however the image is just a random stock picture then it doesn't provide additional information and you should have &lt;code&gt;alt=""&lt;/code&gt; (in this case the content lives for itself and the image is just a visual addendum).&lt;/li&gt;
&lt;li&gt;If you use modals, make sure to "Lock In". If you cannot click elements below the Modal with your mouse then you shouldn't be able to tab with your keyboard below it. But many modals do that and it's horrible for people working with screen readers because they often cannot get back to the modal once they left it. I also built one React Library to help with that: &lt;a href="https://github.com/activenode/react-use-focus-trap"&gt;https://github.com/activenode/react-use-focus-trap&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Now stop being a prick and at least inform yourself a little bit.
&lt;/h2&gt;

&lt;p&gt;Providing a good semantic HTML structure, knowing how and when to properly set &lt;code&gt;alt&lt;/code&gt; attributes (most FE Developers think they know this but in fact they don't) and the impact of using &lt;code&gt;aria-*&lt;/code&gt; attributes can be a very good start for having basic a11y. That doesn't sound like a huge effort, does it?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/26FPOogenQv5eOZHO/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/26FPOogenQv5eOZHO/giphy.gif" alt="" width="400" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>css</category>
    </item>
    <item>
      <title>⚡️HTML is not a programming language </title>
      <dc:creator>David Lorenz</dc:creator>
      <pubDate>Wed, 24 Nov 2021 09:35:26 +0000</pubDate>
      <link>https://dev.to/activenode/html-is-not-a-programming-language-28p7</link>
      <guid>https://dev.to/activenode/html-is-not-a-programming-language-28p7</guid>
      <description>&lt;p&gt;Btw, CSS also isn't a programming language. I know what you think: &lt;strong&gt;I'm gonna put some roast on this iffy post from this arrogant guy who is trying to talk down the language&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;First and foremost: If you only code in HTML you are a programmer, no discussion needed ♥️. The definition of a language does not change your worthiness or your job title.&lt;/p&gt;

&lt;p&gt;Let me elaborate why writing this blogpost is important and essential and why it is not about "being right". My assumption is that the discussion is purely based on insecurities and fear.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why do you even care?
&lt;/h3&gt;

&lt;p&gt;People on twitter seem to fight for the right that HTML is a programming language. The essential question is why do people argue about it? I don't get it. The definition of what HTML is does not change anything about the fact that HTML is the crucial language to create websites and web apps - fact.&lt;/p&gt;




&lt;h3&gt;
  
  
  People confuse programming language and being a programmer
&lt;/h3&gt;

&lt;p&gt;Maybe that is one of the fears that people have: If neither HTML nor CSS is a programming language then am I even a programmer by just using HTML/CSS? &lt;strong&gt;Sure thing, you are!&lt;/strong&gt; Even though the word has the same origin being a programmer and programming language are still different things.&lt;/p&gt;

&lt;p&gt;Let's take the Wikipedia Definition:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A computer programmer, sometimes called a software developer, a programmer or more recently a coder (especially in more informal contexts), is a person who creates computer software.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So even if you do not code at all e.g. by designing systems architecture you are part of the programmers world.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why it is important to acknowledge that HTML is not a programming language?
&lt;/h3&gt;

&lt;p&gt;In very simple words: Because if we go by the majority of scientifical definitions then it is often described as a Markup Language (HTML= Hypertext Markup Language) as opposed to programming language. We are living in a world that often confuses facts with opinions and hence create problematic discussions that wouldn't even be worth the energy simply because it does not change a single thing about the outcome.&lt;/p&gt;

&lt;p&gt;Let's face Wikipedia again:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Markup languages like XML, HTML, or troff, which define structured data, are not usually considered programming languages.&lt;br&gt;
Source: &lt;a href="https://en.wikipedia.org/wiki/Programming_language"&gt;https://en.wikipedia.org/wiki/Programming_language&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There is a "trivial" and a not-so-trivial explanation. The not-so-trivial one is about language possibilities, turing completeness and so on and so forth which I do not want to elaborate in detail here because.&lt;br&gt;
A more trivial approach is: If you can build a calculator based on users input with it then it most likely can be considered a programming language. Bash can do that, JS can do that, HTML cannot. You can define input fields in HTML but HTML cannot process them and sum/multiply. CSS can partially calculate but then again it is extremely constrained to "hardcoded" values and not arbitrary input.&lt;/p&gt;

&lt;p&gt;And by the way: SQL can also only calculate things to a constrained extent. You cannot write a full program in SQL. SQL is a declarative language. But back to the actual point: Why would you care to make it a "programming language"? You are a programmer nevertheless.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion:
&lt;/h2&gt;

&lt;p&gt;I am not trying to be "right". That is not the whole point of this post. Generically spoken I would really love to see a world where we come together and share what's available in science rather than creating an "opinion" about things that science has a clearer view on. That can be troublesome in any topic e.g. vaccination.&lt;/p&gt;

&lt;p&gt;A good start here is to ask questions: "Can you provide me some more information why HTML wouldn't be considered a programming language?" or vice versa.&lt;/p&gt;

&lt;p&gt;That is the world that I am looking for. A proper, scientifically based discussion (how they are very often found in good responses on StackOverflow).&lt;/p&gt;

&lt;p&gt;I just do not get the point why a simple word triggers so many people. &lt;/p&gt;

&lt;p&gt;Peace &amp;amp; Love&lt;br&gt;
David&lt;/p&gt;

</description>
      <category>html</category>
      <category>programming</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Don't use CSS classes for testing in Unit Tests or E2E</title>
      <dc:creator>David Lorenz</dc:creator>
      <pubDate>Fri, 12 Nov 2021 11:18:08 +0000</pubDate>
      <link>https://dev.to/activenode/dont-use-css-classes-for-testing-in-unit-tests-or-e2e-5dnn</link>
      <guid>https://dev.to/activenode/dont-use-css-classes-for-testing-in-unit-tests-or-e2e-5dnn</guid>
      <description>&lt;p&gt;CSS is meant to style your elements. Sometimes you do that via class and sometimes there is elements that want to be styled the same way all the time e.g. &lt;code&gt;h1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In my past experience I have seen a lot of projects that write their tests depending on css classes. Although this works it is architecturally not the finest of the finest.&lt;/p&gt;

&lt;p&gt;Let's face following problem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;article&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"article"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;strong&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"article__title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Whatever&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Some text&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your task is to test if the &lt;code&gt;"Whatever"&lt;/code&gt; is contained.&lt;/p&gt;

&lt;p&gt;In your tests you might be doing something like on of these options:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Option 1:&lt;/span&gt;
&lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;strong&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Whatever&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Option 2&lt;/span&gt;
&lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.article__title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Whatever&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first option is probably the worst since it means that changing the &lt;code&gt;strong&lt;/code&gt; to e.g. &lt;code&gt;em&lt;/code&gt; or &lt;code&gt;h2&lt;/code&gt; you would need to adapt that in the test as well.&lt;/p&gt;

&lt;p&gt;The second option with querying &lt;code&gt;article__title&lt;/code&gt; class is more stable. But also only if you are using this exact semantical BEM approach. If you use something like Tailwind or bootstrap are you then going to search for &lt;code&gt;whatever-xl-highlight&lt;/code&gt; class? &lt;/p&gt;

&lt;h2&gt;
  
  
  ⚡️ Both options are not stable for changes!
&lt;/h2&gt;

&lt;p&gt;The stable option is to add semantic &lt;code&gt;probe&lt;/code&gt; identifiers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;article&lt;/span&gt; &lt;span class="na"&gt;data-probe-id=&lt;/span&gt;&lt;span class="s"&gt;"blogpost"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;strong&lt;/span&gt; &lt;span class="na"&gt;data-probe-id=&lt;/span&gt;&lt;span class="s"&gt;"blogpost__title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now whatever changes stylewise, removing classes, adding classes, changing class names, the &lt;code&gt;probe-id&lt;/code&gt; will stay and make the life of your Teast team easier as it rarely needs to adapt. &lt;/p&gt;

&lt;p&gt;Also what comes in handy in Test-Driven-Development is that the Test Team can define the &lt;code&gt;probe-id&lt;/code&gt; values upfront before implementation.&lt;/p&gt;

&lt;p&gt;Problem solved 🚀&lt;/p&gt;

</description>
      <category>testing</category>
      <category>javascript</category>
      <category>css</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The Breakpoint CSS-JS "Hack" - do not define breakpoints in JS</title>
      <dc:creator>David Lorenz</dc:creator>
      <pubDate>Thu, 11 Feb 2021 10:21:40 +0000</pubDate>
      <link>https://dev.to/activenode/the-breakpoint-css-js-hack-do-not-define-breakpoints-in-js-1c11</link>
      <guid>https://dev.to/activenode/the-breakpoint-css-js-hack-do-not-define-breakpoints-in-js-1c11</guid>
      <description>&lt;p&gt;This trick is a best practice trick. Knowing that this is a best practice I thought this is a common thing but apparently it is not as widespread as I thought it would be.&lt;/p&gt;

&lt;p&gt;So let me share it with you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do not redefine your breakpoints in JavaScript/TypeScript
&lt;/h2&gt;

&lt;p&gt;I am assuming you are using either native CSS or SASS for your development so let's use SASS for my code snippets now.&lt;/p&gt;

&lt;p&gt;Assume your breakpoints are defined as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mobile =&amp;gt; max-width: 599.99px
tablet =&amp;gt; min-width: 600px
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now what some people do is redefining those values in JS. But you can simply read the current breakpoint directly from CSS. Also you can pass all breakpoints through CSS as Single Source of Truth for UI ♥️&lt;/p&gt;

&lt;p&gt;The trick is to use the &lt;code&gt;:before&lt;/code&gt; in combination with &lt;code&gt;content&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="nf"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max-width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;599&lt;/span&gt;&lt;span class="mi"&gt;.99px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"mobile"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="nf"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;600px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"tablet"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can access this in JS via &lt;code&gt;getComputedStyle(document.body, 'before').content&lt;/code&gt; and it would give you e.g. &lt;code&gt;"mobile"&lt;/code&gt; or &lt;code&gt;"tablet"&lt;/code&gt; here. So the only thing left to do is to remove the quotes like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;breakpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
  &lt;span class="nx"&gt;getComputedStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;before&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/"/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if you want to have all definitions from CSS you could do something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;media-queries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"mobile=(max-width: 599.99px);tablet=(min-width: 600px)"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can read that content and use actually &lt;code&gt;matchMedia&lt;/code&gt; or whatever you want but the important part is to always have the Design in CSS and not duplicated in JS.&lt;/p&gt;

&lt;p&gt;Here is an actual demo you can check out: &lt;br&gt;
&lt;a href="https://codesandbox.io/s/reading-media-queries-bps-from-css-06zjh?file=/index.html"&gt;https://codesandbox.io/s/reading-media-queries-bps-from-css-06zjh?file=/index.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>javascript</category>
      <category>breakpoints</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Angular 10 + Storybook + npm package = NG Design System 💜 - Step-by-Step</title>
      <dc:creator>David Lorenz</dc:creator>
      <pubDate>Thu, 15 Oct 2020 15:54:24 +0000</pubDate>
      <link>https://dev.to/activenode/angular-10-storybook-npm-package-ng-design-system-step-by-step-2dn2</link>
      <guid>https://dev.to/activenode/angular-10-storybook-npm-package-ng-design-system-step-by-step-2dn2</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;! The Angular version used here is &lt;strong&gt;10.x&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  tldr - The Task was:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Create a UI Kit with Angular that lives on its own and scales to multiple product usage.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Or in technical terms:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i @your-company/your-ui-kit&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@your-company/your-ui-kit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  The Final Result:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Angular-based library published as &lt;code&gt;@your-prefix/pattern-lib&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Using Storybook to preview the library elements&lt;/li&gt;
&lt;li&gt;Using and exporting global &lt;code&gt;scss&lt;/code&gt; styles&lt;/li&gt;
&lt;/ul&gt;


&lt;h1&gt;
  
  
  1. Background and Decision-Making 👨🏽‍💻
&lt;/h1&gt;

&lt;p&gt;Our product application is based on &lt;a href="https://angular.io/" rel="noopener noreferrer"&gt;Angular&lt;/a&gt;. We wanted it to scale such that we can quickly re-use components even across other products.&lt;br&gt;
Those components should always go with the Brand visuals.&lt;/p&gt;

&lt;p&gt;To achieve that we wanted to do what the de-facto standard is: &lt;em&gt;Creating a Design System that is implemented as a Pattern Library&lt;/em&gt; (furthermore called Pattern Lib)&lt;/p&gt;
&lt;h2&gt;
  
  
  1.1. A "No" to Web Components and a "Yes" to NG components 👀
&lt;/h2&gt;

&lt;p&gt;If you follow me on different channels you know that I love &lt;strong&gt;Web Components&lt;/strong&gt;. &lt;strong&gt;But&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use the right tool for the right job 🛠&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At &lt;a href="https://www.mercedes-benz.io/" rel="noopener noreferrer"&gt;Mercedes-Benz.io&lt;/a&gt; we were using Web Components together with &lt;a href="https://stenciljs.com/" rel="noopener noreferrer"&gt;Stencil&lt;/a&gt; to create the Pattern Library. This decision was based on the fact that we had React, Vue, Angular and partially even Elm in our product stack and therefore needed to find a Library approach that is framework independent.&lt;/p&gt;

&lt;p&gt;However being framework independent comes with the downside of not getting the best from that very framework since you are mixing up different technologies - that can especially get messy once your requirement says: Enable SSR.&lt;/p&gt;

&lt;p&gt;So at the end of the day: You have the balance the upsides and downsides based on how your business is built.&lt;/p&gt;
&lt;h3&gt;
  
  
  The process that led to an Angular-based PatternLib
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Angular does a lot of preprocessing in its compilation process. So the compiler ensures the best overall output is achieved - when using Angular. Angular cannot optimize the code you put in your Web Component.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintaining a framework-agnostic solution makes only sense if you plan to support multiple frameworks in the long run.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Small team: Focus switch avoidance between e.g. Stencil and Angular. Sticking with Angular delivers overall better output since we can apply the same guidelines.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You do not necessarily benefit of awesome Editor help when mixing up 2 technologies - or you have to put in more of work to achieve that.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you still want to output Web Components from your library you will still be able to tune up your build to do so.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/26xBP13FAQL2mhc1W/giphy-downsized.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/26xBP13FAQL2mhc1W/giphy-downsized.gif"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h1&gt;
  
  
  2. How to implement an Angular UI Kit / NG UI Library
&lt;/h1&gt;
&lt;h2&gt;
  
  
  2.1. The Pre-setup
&lt;/h2&gt;

&lt;p&gt;I guess it is clear that you will have to have &lt;code&gt;@angular/cli&lt;/code&gt; installed and ready.&lt;/p&gt;

&lt;p&gt;Besides that: The first thing you want to do is to be able to test your library to confirm that you did a good job. So before we create the actual library we want to create the application that consumes it.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng new my-app &lt;span class="nt"&gt;--prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ma &lt;span class="nt"&gt;--style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;scss &lt;span class="nt"&gt;--legacyBrowsers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We use the &lt;code&gt;prefix&lt;/code&gt; to be safe and isolated from any used library (that might be unprefixed).&lt;br&gt;
You do not need &lt;code&gt;legacyBrowsers&lt;/code&gt; if you do not plan to support IE.&lt;/p&gt;
&lt;h2&gt;
  
  
  2.2. Creating the library
&lt;/h2&gt;

&lt;p&gt;Run the following command in the directory where your &lt;code&gt;my-app&lt;/code&gt; is located (so basically in its parent directory &lt;code&gt;./my-app/../&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng new design-system &lt;span class="nt"&gt;--create-application&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="nt"&gt;--prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ds &lt;span class="nt"&gt;--style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;scss
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Important Note&lt;/strong&gt;: In Angular 10.1.4 that I used for this project the &lt;code&gt;--style=scss&lt;/code&gt; did not have any effect. This comes from the fact that we created an empty application and Angular has no option yet to predefine it (we will fix it soon in this tutorial).&lt;/p&gt;

&lt;p&gt;We call the parent &lt;code&gt;design-system&lt;/code&gt; to not get confused with its child module below.&lt;br&gt;
Now your directory structure should look like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── my-app
├── design-system
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Inside your &lt;code&gt;design-system&lt;/code&gt; directory we now create the actual library that will contain our components:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng generate library pattern-lib &lt;span class="nt"&gt;--prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;pl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;First thing you want to do is to make the package &lt;em&gt;scoped&lt;/em&gt; to easier identify it is your library. &lt;/p&gt;

&lt;p&gt;So go to &lt;code&gt;design-system/projects/pattern-lib/package.json&lt;/code&gt; and change the &lt;code&gt;name&lt;/code&gt; from &lt;code&gt;pattern-lib&lt;/code&gt; to &lt;code&gt;@your-company/pattern-lib&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;As said above: We also have to fix &lt;code&gt;--style=scss&lt;/code&gt; on our own since this is not yet possible to define for a &lt;code&gt;library&lt;/code&gt; or empty &lt;code&gt;application&lt;/code&gt; upfront. Do the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;code&gt;design-system/angular.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Search for your added library in &lt;code&gt;"projects": { ...}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add the &lt;code&gt;schematics&lt;/code&gt; property to your &lt;code&gt;projects/pattern-lib&lt;/code&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In my project it then looks somewhat like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"projects"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"pattern-lib"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"projectType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"library"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"schematics"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"@schematics/angular:component"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"style"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"scss"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  2.3. Creating a &lt;code&gt;button&lt;/code&gt; component in the library
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng generate component button &lt;span class="nt"&gt;--project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;pattern-lib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This command will create a component named &lt;code&gt;button&lt;/code&gt;. Your directory structure should contain the following directories:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── my-app
├── design-system
   ├── projects
      ├── pattern- lib
         ├── src
            ├── lib
               ├── button
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;You might want to say: &lt;strong&gt;Yo David why so many subfolders? Can't I just put it in the root src?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Answer&lt;/strong&gt;: Angular allows to control multiple libraries / components / modules etc. in one Angular project root and the &lt;code&gt;@angular/cli&lt;/code&gt; is optimized to suppor this exact structure. If we start building a pattern lib in a default &lt;code&gt;ng new my-pattern-lib&lt;/code&gt; application -&amp;gt; that will work for sure but we are leaving the safe track to a slippery path because then we have to bend the tools to do what we want to do (expose and publish library parts).&lt;/p&gt;



&lt;p&gt;Open up &lt;code&gt;button.component.ts&lt;/code&gt; and make sure it has 2 properties defined in the class like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Input&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pl-button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// pl is our prefix&lt;/span&gt;
  &lt;span class="na"&gt;templateUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./button.component.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;styleUrls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./button.component.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ButtonComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pink&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;pink&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;


&lt;p&gt;Quick explainer: By setting the properties explicitly (e.g. &lt;code&gt;@Input('pink') pink: boolean;&lt;/code&gt;) the component exposes its editable fields which will come in handy in Storybook later since Storybook can autodetect the field types.&lt;/p&gt;



&lt;p&gt;Now open &lt;code&gt;button.component.html&lt;/code&gt; and fill it with:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;[attr.is-pink]=&lt;/span&gt;&lt;span class="s"&gt;"pink"&lt;/span&gt; &lt;span class="na"&gt;[ngClass]=&lt;/span&gt;&lt;span class="s"&gt;"{'make-pink': pink}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{label ? "😎 " + label : "No Label provided 🧐"}}&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;[attr.is-pink]="pink"&lt;/code&gt; we use to debug if we run into errors. It is not needed though 😉&lt;/p&gt;

&lt;p&gt;Also open &lt;code&gt;button.component.scss&lt;/code&gt; and fill it with:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt; &lt;span class="m"&gt;2rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;appearance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="na"&gt;-webkit-appearance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="na"&gt;-moz-appearance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="mi"&gt;.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;letter-spacing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="nf"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;55&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="mi"&gt;.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;6px&lt;/span&gt; &lt;span class="m"&gt;35px&lt;/span&gt; &lt;span class="nf"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;55&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="mi"&gt;.7&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;.make-pink&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#ff00a2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="nf"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;55&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="mi"&gt;.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;6px&lt;/span&gt; &lt;span class="m"&gt;35px&lt;/span&gt; &lt;span class="nf"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt; &lt;span class="m"&gt;150&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="m"&gt;70%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Now you want to build and see the button in action - but it is just a library, not an SPA, so HOW?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/kQOxxwjjuTB7O/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/kQOxxwjjuTB7O/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  2.4. Run it: &lt;strong&gt;&lt;a href="https://storybook.js.org/" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt;&lt;/strong&gt; to the rescue.
&lt;/h2&gt;

&lt;p&gt;Adding storybook normally is quite easy as there are ready-to-go recipes. &lt;strong&gt;However&lt;/strong&gt; these do not naturally apply for an Angular library.&lt;/p&gt;
&lt;h3&gt;
  
  
  2.4.1. Installing Storybook and binding it to our Library
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Run &lt;code&gt;npx -p @storybook/cli sb init --type angular&lt;/code&gt; within your &lt;code&gt;design-system&lt;/code&gt; Angular project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open &lt;code&gt;.storybook/tsconfig.json&lt;/code&gt; and change the extends line to &lt;code&gt;"extends": "../projects/pattern-lib/tsconfig.lib.json"&lt;/code&gt; (if not already set)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  2.4.2. Setting up our button story
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;code&gt;design-system/stories&lt;/code&gt; and DELETE EVERYTHING&lt;/li&gt;
&lt;li&gt;Create a file named &lt;code&gt;Intro.stories.mdx&lt;/code&gt; with following content:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Meta } from '@storybook/addon-docs/blocks';

&amp;lt;Meta title="Library Example/Intro" /&amp;gt;

&amp;lt;style&amp;gt;{`
  .box {
    margin: 2rem 0;
    padding: 2rem;
    background: rgba(233,233,233,0.7);
    border-radius: 3px;
  }
`}&amp;lt;/style&amp;gt;

# Hello you!

&amp;lt;div class="box"&amp;gt;
  This is the Pattern Library Intro File to provide a guiding path or whatever else you want to do here. Feel free!
&amp;lt;/div&amp;gt;

![](https://media.giphy.com/media/yJFeycRK2DB4c/giphy.gif)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Create a file named &lt;code&gt;Button.stories.mdx&lt;/code&gt; with following content:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Story&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Meta&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/angular/types-6-0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ButtonComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../projects/pattern-lib/src/lib/button/button.component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Atomics/Buttons&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ButtonComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;argTypes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;control&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; 
    &lt;span class="c1"&gt;// we need to override here since in Angular it could be null as well (see button.component.ts) and therefore it would become an ambigious data type for storybook&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Story&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ButtonComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ButtonComponent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ButtonComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FancyBlueButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;
&lt;span class="nx"&gt;FancyBlueButton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FancyPinkButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;
&lt;span class="nx"&gt;FancyPinkButton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pink version&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;pink&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  2.4.3. Run, run, run!
&lt;/h3&gt;

&lt;p&gt;Trigger &lt;code&gt;npm run storybook&lt;/code&gt; within your &lt;code&gt;design-system&lt;/code&gt; project folder and wait for it to - hopefully successfully - boot up.&lt;/p&gt;

&lt;p&gt;As a result you should see something like this:&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fstmfb0qwclc21nbqejkj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fstmfb0qwclc21nbqejkj.gif" alt="Storybook"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cool Stuff!&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Quick Summary&lt;/strong&gt;: Up to this point we created an Angular library with a button as a component and connected Storybook to it to be able to see and structure it without running an actual Angular SPA.&lt;/p&gt;
&lt;h2&gt;
  
  
  2.5. Global SCSS and Component Composition
&lt;/h2&gt;
&lt;h3&gt;
  
  
  2.5.1. Global SCSS
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;code&gt;design-system/projects/pattern-lib/src/&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Create a directory &lt;code&gt;styles/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create a file named &lt;code&gt;global.scss&lt;/code&gt; with some random content e.g. &lt;code&gt;body { background: red }&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Use it in Storybook
&lt;/h3&gt;

&lt;p&gt;To make sure that Storybook can apply the global scss head over to &lt;code&gt;.storybook/preview.js&lt;/code&gt; and add it as a webpack import like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;!style-loader!css-loader!sass-loader!./../projects/pattern-lib/src/styles/global.scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That's it. Storybook will now always use that file as a global file for every view.&lt;/p&gt;
&lt;h3&gt;
  
  
  Use it in Angular
&lt;/h3&gt;

&lt;p&gt;Using a global SCSS in Angular shouldn't be a problem since you can always &lt;code&gt;@import&lt;/code&gt; it in any of your SCSS files in your project e.g. like&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s1"&gt;'../../styles/global'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;However &amp;gt;&amp;gt; &lt;strong&gt;WARNING&lt;/strong&gt;: Make sure not to import actual CSS definitions such as &lt;code&gt;body { background: red }&lt;/code&gt; into your Angular components as those would get duplicated and would drastically decrease performance.&lt;/p&gt;

&lt;p&gt;If you want a global CSS file for your Angular App you can (and should) surely define it in your library but you should export them with the npm package (see section 2.6.) such that your Angular SPA can then include it.&lt;/p&gt;

&lt;p&gt;In any Angular application (!= Angular library) you can add this to the &lt;code&gt;angular.json&lt;/code&gt; to define a global style for the App:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"styles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"node_modules/@your-company/pattern-lib/styles/style.scss"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  2.5.2. Component Composition
&lt;/h3&gt;

&lt;p&gt;Please refer to &lt;a href="https://www.learnstorybook.com/intro-to-storybook/angular/en/composite-component/" rel="noopener noreferrer"&gt;https://www.learnstorybook.com/intro-to-storybook/angular/en/composite-component/&lt;/a&gt; if you wanted to combine multiple components in Storybook.&lt;/p&gt;
&lt;h2&gt;
  
  
  2.6. Using the &lt;code&gt;pattern-lib&lt;/code&gt; in your Angular application &lt;code&gt;my-app&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Now what we want is to be able to use our patterns in any application that we create - as an npm package.&lt;/p&gt;

&lt;p&gt;The following diagram visualizes that:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fa91u0qq7zrpb99bpi9h4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fa91u0qq7zrpb99bpi9h4.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Hold up! Important!
&lt;/h3&gt;

&lt;p&gt;Before we use our library we need to import the &lt;code&gt;CommonModule&lt;/code&gt; from &lt;code&gt;@angular/common&lt;/code&gt; as otherwise our &lt;code&gt;[ngClass]&lt;/code&gt; binding of our button will not work (more info here: &lt;a href="https://stackoverflow.com/a/45573086" rel="noopener noreferrer"&gt;https://stackoverflow.com/a/45573086&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;So in &lt;code&gt;design-system/pattern-lib&lt;/code&gt; open up &lt;code&gt;pattern-lib.module.ts&lt;/code&gt; and adapt it such that you do:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//... other imports&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CommonModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;CommonModule&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  2.6.1. Export the button for usage
&lt;/h3&gt;

&lt;p&gt;If we want our button to be usable outside of the library we need to export it in our &lt;code&gt;pattern-lib.module.ts&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//.. other imports&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ButtonComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./button/button.component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;PatternLibComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ButtonComponent&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

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

&lt;/div&gt;

&lt;h3&gt;
  
  
  2.6.2. Using the library package through local binding
&lt;/h3&gt;

&lt;p&gt;Go to the directory &lt;code&gt;design-system&lt;/code&gt; and run&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng build &lt;span class="nt"&gt;--project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;pattern-lib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Head over to &lt;code&gt;design-system/dist/pattern-lib&lt;/code&gt; and run &lt;a href="https://docs.npmjs.com/cli/link" rel="noopener noreferrer"&gt;&lt;code&gt;npm link&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now your package should be available on your computer under its package name &lt;code&gt;@your-company/pattern-lib&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;No go over to your Angular SPA &lt;code&gt;my-app&lt;/code&gt; and run &lt;code&gt;npm link @your-company/pattern-lib&lt;/code&gt;. This basically is like a local &lt;code&gt;npm install&lt;/code&gt; - however it will not show up in your package.json. Alternatively you can also do &lt;code&gt;npm install ../design-system/dist/pattern-lib&lt;/code&gt; if you prefer so.&lt;/p&gt;
&lt;h3&gt;
  
  
  Add the linked library to our &lt;code&gt;my-app&lt;/code&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;code&gt;my-app/src/app/app.module.ts&lt;/code&gt; and add the library import
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PatternLibModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@your-company/pattern-lib&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Also add it to the &lt;code&gt;imports&lt;/code&gt; field of &lt;code&gt;app.module.ts&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="nx"&gt;PatternLibModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Go to &lt;code&gt;my-app/src/app/app.component.html&lt;/code&gt; and delete all the contents and put the following instead:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nd"&gt;:host&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;-apple-system&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BlinkMacSystemFont&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;"Segoe UI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Roboto&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Helvetica&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Arial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;"Apple Color Emoji"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;"Segoe UI Emoji"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;"Segoe UI Symbol"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;14px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#333&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;-webkit-font-smoothing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;antialiased&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;-moz-osx-font-smoothing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grayscale&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;


&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Hello I am the Angular SPA and following a button should be shown and it should be blue: &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dvpl-button&lt;/span&gt; &lt;span class="na"&gt;label=&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/dvpl-button&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;And this one should be pink: &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dvpl-button&lt;/span&gt; &lt;span class="na"&gt;label=&lt;/span&gt;&lt;span class="s"&gt;"Hello pink?"&lt;/span&gt; &lt;span class="na"&gt;[pink]=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/dvpl-button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- you only need this if you added a router: --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;router-outlet&amp;gt;&amp;lt;/router-outlet&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now you should be able to run &lt;code&gt;npm start&lt;/code&gt; in your &lt;code&gt;my-app&lt;/code&gt; SPA and you should see that your Angular application properly makes use of our library. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxlfsg25u0xldstdirho7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxlfsg25u0xldstdirho7.png" alt="Running the app"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2.6.3. Using the package with an &lt;code&gt;npm&lt;/code&gt; registry
&lt;/h3&gt;

&lt;p&gt;Now that you have it already running locally this should come with ease.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;First things first. Choose a npm registry (e.g. Github or npmjs).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create an &lt;code&gt;.npmrc&lt;/code&gt; file in your &lt;code&gt;design-system&lt;/code&gt; Angular root that looks similiar to the following:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;registry=https://registry.npmjs.org/
always-auth=true
email=YOUR_EMAIL_GOES_HERE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Login with &lt;code&gt;npm login&lt;/code&gt; - It should ask you for your credentials on the registry provided in the &lt;code&gt;.npmrc&lt;/code&gt; file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once you are logged in you can simply run &lt;code&gt;npm publish&lt;/code&gt; in your &lt;code&gt;design-system/dist/pattern-lib&lt;/code&gt; directory to publish the library that you built! Make sure to NOT run it in your root directory but really in &lt;code&gt;dist&lt;/code&gt; ! Because if you run &lt;code&gt;npm publish&lt;/code&gt; in your root directory it will only publish all the source code and not the compiled library.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now you can use it the same way you installed it locally but from the given repository with &lt;code&gt;npm install @your-company/pattern-lib&lt;/code&gt; 🎉&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/RgfGmnVvt8Pfy/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/RgfGmnVvt8Pfy/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  3. Testing Storybook,  atomic imports and Web Components, etc.
&lt;/h1&gt;

&lt;p&gt;There is way more that we could discuss - but I don't wanna excess this here too much: How to not only test the components but test them with Storybook, how to export more atomically (a single Button import instead of the whole library if needed) and publishing for other Frameworks as a Web Component.&lt;/p&gt;

&lt;p&gt;But this might be worth another Blog Post. Let me know!&lt;/p&gt;
&lt;h1&gt;
  
  
  4. Conclusion
&lt;/h1&gt;

&lt;p&gt;You created a &lt;em&gt;Design System Repo&lt;/em&gt; with Angular and you are able to publish it in different versions.&lt;br&gt;
Also you can use them in whatever Angular app you want 😎.&lt;/p&gt;

&lt;p&gt;Find the source code of the sample here: &lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/activenode" rel="noopener noreferrer"&gt;
        activenode
      &lt;/a&gt; / &lt;a href="https://github.com/activenode/angular-10-storybook-library" rel="noopener noreferrer"&gt;
        angular-10-storybook-library
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      An angular library to implement an isolated Design System
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Angular 10.x Storybook Library&lt;/h1&gt;

&lt;/div&gt;

&lt;p&gt;This is a sample repository that includes 2 Angular root-projects.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;design-system&lt;/code&gt; which is an angular project containing UI elements (pattern library)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;my-app&lt;/code&gt; which consumes those&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the final result of the step-by-step tutorial provided at dev.to: &lt;a href="https://dev.to/activenode/angular-10-storybook-npm-package-ng-design-system-step-by-step-2dn2" rel="nofollow"&gt;https://dev.to/activenode/angular-10-storybook-npm-package-ng-design-system-step-by-step-2dn2&lt;/a&gt;&lt;/p&gt;

&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/activenode/angular-10-storybook-library" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;&lt;a href="https://i.giphy.com/media/WS0OoLybvDIeuBLGxS/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/WS0OoLybvDIeuBLGxS/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Sources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[1] &lt;a href="https://angular.io/cli/generate" rel="noopener noreferrer"&gt;https://angular.io/cli/generate&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[2] &lt;a href="https://www.blexin.com/en-US/Article/Blog/Creating-Angular-components-libraries-68" rel="noopener noreferrer"&gt;https://www.blexin.com/en-US/Article/Blog/Creating-Angular-components-libraries-68&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[3] Exporting global SCSS: &lt;a href="https://medium.com/@Dor3nz/compiling-css-in-new-angular-6-libraries-26f80274d8e5" rel="noopener noreferrer"&gt;https://medium.com/@Dor3nz/compiling-css-in-new-angular-6-libraries-26f80274d8e5&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[4] &lt;a href="https://medium.com/@tomsu/how-to-build-a-library-for-angular-apps-4f9b38b0ed11" rel="noopener noreferrer"&gt;https://medium.com/@tomsu/how-to-build-a-library-for-angular-apps-4f9b38b0ed11&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Design References:&lt;br&gt;
Packaging Design Icon made &lt;a href="https://www.flaticon.com/free-icon/packaging_2467521" rel="noopener noreferrer"&gt;xnimrodx&lt;/a&gt; from flaticon.com&lt;/p&gt;

</description>
      <category>angular</category>
      <category>npm</category>
      <category>storybook</category>
      <category>uikit</category>
    </item>
    <item>
      <title>srcset, sizes, picture, media: What you might not have known.</title>
      <dc:creator>David Lorenz</dc:creator>
      <pubDate>Tue, 29 Sep 2020 12:04:11 +0000</pubDate>
      <link>https://dev.to/activenode/srcset-sizes-picture-media-what-you-might-not-have-known-31nf</link>
      <guid>https://dev.to/activenode/srcset-sizes-picture-media-what-you-might-not-have-known-31nf</guid>
      <description>&lt;p&gt;Gosh. Yet another "How-To Responsive Images" article? Well nope, I hope.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/duLDZKWk8WAaSIkmDv/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/duLDZKWk8WAaSIkmDv/giphy.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The background story: It all started with an &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag
&lt;/h2&gt;

&lt;p&gt;So one of my colleagues was going like &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;WTF Dude, Firefox is loading some bunch of huge images even though I provided a proper srcset and sizes attribute. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In 20 years of programming experience - also in these modern times - me and the team have seen some weird browser bugs here and there so I do not immediately assume the problem is the one in front of the computer.&lt;/p&gt;

&lt;p&gt;However in this case, for something so crucial I and &lt;em&gt;rather&lt;/em&gt; simple I couldn't believe it's a Browser problem. Especially as Safari was behaving the same way.&lt;/p&gt;

&lt;p&gt;It was something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"raw.jpg"&lt;/span&gt;  
&lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"360w.jpg 360w, 800w.jpg 800w, 1080w.jpg 1080w"&lt;/span&gt; 
&lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"
  (max-width: 360px) 360px,
  (max-width: 800px) 800px,
  (max-width: 1080px) 1080px
"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For a Samsung Galaxy S9 with &lt;code&gt;360x740&lt;/code&gt; it would load the &lt;code&gt;1080px&lt;/code&gt; one. And we both were a bit confused.&lt;/p&gt;

&lt;p&gt;I don't want to create cliffhangers so I will immediately jump to the problem: The S9 has a &lt;code&gt;4x&lt;/code&gt; density as its &lt;em&gt;actual&lt;/em&gt; resolution is way more than the above. It is &lt;code&gt;1440x2960 (h x w)&lt;/code&gt;. So yeah, divide that by 4 and you will get &lt;code&gt;360x740&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now what the browser did was quite clever:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Yo Dog, I know you wanted &lt;code&gt;360w&lt;/code&gt; image on &lt;code&gt;360px&lt;/code&gt; screen but this equals 100% width on this mobile phone which is actually &lt;code&gt;1440px&lt;/code&gt; to have a sharp view so I will choose the closest that fits that image size which is &lt;code&gt;1080px&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  It is not directly "intuitive" but it makes sense
&lt;/h3&gt;

&lt;p&gt;It makes sense when you think about it. But for that you have to accept the fact that an &lt;code&gt;img&lt;/code&gt; tag with &lt;code&gt;srcset&lt;/code&gt; is something where you give the browser options (we will have a closer look on this). You are not necessarily the &lt;em&gt;Director&lt;/em&gt; of the scene. If the browser thinks that a certain image out of the provided ones in &lt;code&gt;srcset&lt;/code&gt; is the best fit according to the given information then it will choose that image.&lt;/p&gt;

&lt;h3&gt;
  
  
  So what was the solution now?
&lt;/h3&gt;

&lt;p&gt;We now know what happened and why it happened and I love to tell you the solution - but it really depends on what you want to achieve.&lt;/p&gt;

&lt;p&gt;In this specific case he wanted to deliver a specific image depending on the width of the device. So what he could've done (not saying should've done) to deliver the image that he actually wanted is the following:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"raw.jpg"&lt;/span&gt;  
&lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"360w.jpg 360w, 800w.jpg 800w, 1080w.jpg 1080w"&lt;/span&gt; 
&lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"
  (max-width: 360px) 360px,
  (max-width: 800px) 800px,
  (max-width: 1080px) 1080px
"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"raw.jpg"&lt;/span&gt;  
&lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"360w.jpg 360w, 800w.jpg 800w, 1080w.jpg 1080w"&lt;/span&gt; 
&lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"
  ((max-width: 360px) and (-webkit-min-device-pixel-ratio: 4)) 90px,
  ...
  (max-width: 800px) 800px,
  (max-width: 1080px) 1080px
"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So &lt;code&gt;360/4 = 90px&lt;/code&gt; so when the Browser will search for the best image fit now it will go "Okay I need a 4 times bigger image than &lt;code&gt;90px&lt;/code&gt; which is &lt;code&gt;360px&lt;/code&gt; so I am taking the 360w.jpg"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That does not sound like a clean solution does it?&lt;/strong&gt; Especially when you think about the fact that you would also intentionally deliver an image with non-fitting quality (4 times less the quality to be exact).&lt;br&gt;
However the next time a 5x or 6x DPI device hits the market you need to adapt more and more in your queries of the &lt;code&gt;sizes&lt;/code&gt; attribute.&lt;/p&gt;
&lt;h3&gt;
  
  
  David you talked a lot about the issues but what would you recommend?
&lt;/h3&gt;

&lt;p&gt;I recommend: &lt;em&gt;Start with thinking what you want to see as an end-result&lt;/em&gt;. Maybe even draw it on paper. Then continue to think which solution will help you to achieve that and it might not be an &lt;code&gt;img&lt;/code&gt; tag with &lt;code&gt;srcset&lt;/code&gt; but maybe the &lt;code&gt;picture&lt;/code&gt; tag instead. Please read the explanations below for that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If its the same image on all devices no matter what but with different sizes you should go for using &lt;em&gt;Retina&lt;/em&gt; definitions in your &lt;code&gt;srcset&lt;/code&gt;&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"raw.jpg"&lt;/span&gt;  
&lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"
  image.jpg,
  image@2x.jpx 2x,
  image@3x.jpx 3x,
  image@4x.jpx 4x,
  image@5x.jpx 5x"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;






&lt;h1&gt;
  
  
  It is all about understanding the specs
&lt;/h1&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;img&lt;/code&gt;: The important specification details on &lt;code&gt;srcset&lt;/code&gt; + &lt;code&gt;sizes&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;If you use &lt;code&gt;srcset="foo.jpg 200w ..."&lt;/code&gt; then you &lt;strong&gt;MUST&lt;/strong&gt;  (check the &lt;a href="https://html.spec.whatwg.org/multipage/embedded-content.html#attr-img-srcset"&gt;W3C specs&lt;/a&gt;) provide a &lt;code&gt;sizes&lt;/code&gt; attribute to tell the browser "On this media query the image will have a shown size of WHATEVERpx". &lt;/p&gt;

&lt;p&gt;If you use &lt;code&gt;srcset="foo.jpg 2x ..."&lt;/code&gt; you &lt;strong&gt;MUST NOT&lt;/strong&gt; provide a &lt;code&gt;sizes&lt;/code&gt; attribute. The browser would just ignore it as it implies the chosen image only by the pixel density.&lt;/p&gt;

&lt;p&gt;According to &lt;a href="https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element"&gt;https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element&lt;/a&gt; (09/2020) the &lt;code&gt;img&lt;/code&gt; tag does not support the attributes &lt;code&gt;media&lt;/code&gt;, &lt;code&gt;type&lt;/code&gt;. Which is understandable if you read the following paragraphs about &lt;code&gt;picture&lt;/code&gt; and its &lt;code&gt;source&lt;/code&gt; tags.&lt;/p&gt;

&lt;h2&gt;
  
  
  The powerful &lt;code&gt;picture&lt;/code&gt; tag and its &lt;code&gt;source&lt;/code&gt; children
&lt;/h2&gt;

&lt;p&gt;Semantically, (reading the W3C specs) the &lt;code&gt;picture&lt;/code&gt; element is just a "ghost" container for the &lt;code&gt;img&lt;/code&gt; tag that allows to control what image is served in the &lt;code&gt;img&lt;/code&gt; tag.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://html.spec.whatwg.org/multipage/embedded-content.html#the-picture-element"&gt;W3C states&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The picture element is a container which provides multiple sources to its contained img element to allow authors to declaratively control or give hints to the user agent about which image resource to use, based on the screen pixel density, viewport size, image format, and other factors. It represents its children.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images#Art_direction"&gt;MDN describes&lt;/a&gt; the &lt;code&gt;picture&lt;/code&gt; tag as the tag for the goal of &lt;em&gt;Art Direction&lt;/em&gt;. What they mean is: Total Flexibility. The big difference to &lt;code&gt;img[srcset][sizes]&lt;/code&gt; is that you do not let the browser choose which is the best fit for the device size. You explicitly define what image shall be played under what exact circumstances (media query). This can be based on pixel density, screen ratio, height, whatever you want.&lt;/p&gt;

&lt;p&gt;The picture element must at least contain an &lt;code&gt;img&lt;/code&gt; tag and for it to be actually useful it should contain 1 or more &lt;code&gt;source&lt;/code&gt; tags.&lt;/p&gt;

&lt;p&gt;Let us go by examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Retina Image with &lt;code&gt;picture&lt;/code&gt; tag
&lt;/h3&gt;

&lt;p&gt;We simply want to scale up the images depending on device pixel density.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"logo.png 1x, logo_x2.png 2x, logo_x3.png 3x"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"logo.png"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Cool Logo 👌"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This sample could be seen as over-engineered since removing the &lt;code&gt;picture&lt;/code&gt; and &lt;code&gt;source&lt;/code&gt; tag but keeping the &lt;code&gt;img&lt;/code&gt; tag would do the same thing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"logo.png"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Cool Logo 👌"&lt;/span&gt; 
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"logo.png 1x, logo_x2.png 2x, logo_x3.png 3x"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Choosing a different image depending on ratio
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; 
  &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-aspect-ratio: 21/9)"&lt;/span&gt;
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"2100x900px-img.jpg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; 
  &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-aspect-ratio: 16/9)"&lt;/span&gt; 
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"1600x900px-img.jpg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; 
  &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-aspect-ratio: 1)"&lt;/span&gt; 
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"300x300px-img.jpg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"fallback_whatever.png"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"💞"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The above will solely take the aspect ratio of the screen into account. So for a &lt;code&gt;600x600&lt;/code&gt; screen with actual resolution of &lt;code&gt;3000x3000&lt;/code&gt; which would be &lt;code&gt;5x&lt;/code&gt; retina it would still use the &lt;code&gt;300x300px-img.jpg&lt;/code&gt; because that is the first media query that matches.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is important to note: &lt;code&gt;source&lt;/code&gt; tags are matched from top to bottom. If one hits, the following are ignored.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2. Choosing a different image depending on ratio whilst still providing proper retina images
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; 
  &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-aspect-ratio: 21/9)"&lt;/span&gt;
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"
   2100x900px-img.jpg 1x, 
   4200x1800px-img.jpg 2x,
   6300x2700px-img.jpg 3x"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; 
  &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-aspect-ratio: 16/9)"&lt;/span&gt; 
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"
   1600x900px-img.jpg 1x,
   3200x1800px-img.jpg 2x,
   4800x2700px-img.jpg 3x,"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; 
  &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-aspect-ratio: 1)"&lt;/span&gt; 
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"
   300x300px-img.jpg 1x,
   600x600px-img.jpg 2x,
   900x900px-img.jpg 3x"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"fallback_whatever.png"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"💞"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The only difference to our previous sample now is that we tell the browser exactly which &lt;code&gt;source&lt;/code&gt; tag to take but then the browser is able to choose the best image &lt;strong&gt;within&lt;/strong&gt; this source tag. So if its &lt;code&gt;8x&lt;/code&gt; retina but a squared screen it would hit the last &lt;code&gt;source&lt;/code&gt; tag and choose the next best fit which is &lt;code&gt;3x&lt;/code&gt; which is &lt;code&gt;900x900px-img.jpg&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Improving performance with &lt;code&gt;source&lt;/code&gt; tag and &lt;code&gt;type&lt;/code&gt; attribute
&lt;/h3&gt;

&lt;p&gt;Let us take a simple sample and tune it only for the sake of performance with the &lt;code&gt;type&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;Before tuning:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; 
  &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 1024px)"&lt;/span&gt;
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"
   big.jpg 1x, 
   big-2x.jpg 2x"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; 
  &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 768px)"&lt;/span&gt;
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"
   medium.jpg 1x, 
   medium-2x.jpg 2x"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"fallback.jpg"&lt;/span&gt; 
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"
   fallback.jpg 1x, 
   fallback-2x.jpg 2x"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"💞"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see we have 3 potential sources. It is totally okay to also use &lt;code&gt;srcset&lt;/code&gt; on the &lt;code&gt;img&lt;/code&gt; within a &lt;code&gt;picture&lt;/code&gt; tag as it will only be considered when the other 2 &lt;code&gt;source&lt;/code&gt; tags are not matched.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://html.spec.whatwg.org/multipage/embedded-content.html#attr-img-srcset"&gt;W3C says&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The srcset attribute and the src attribute (if width descriptors are not used) contribute the image sources to the source set (if no source element was selected).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's tune:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; 
  &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 1024px)"&lt;/span&gt;
  &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/webp"&lt;/span&gt;
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"
   big-optimized.webp 1x, 
   big-optimized-2x.webp 2x"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; 
  &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 1024px)"&lt;/span&gt;
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"
   big.jpg 1x, 
   big-2x.jpg 2x"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; 
  &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 768px)"&lt;/span&gt;
  &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/webp"&lt;/span&gt;
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"
   medium-optimized.webp 1x, 
   medium-optimized-2x.webp 2x"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; 
  &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 768px)"&lt;/span&gt;
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"
   medium.jpg 1x, 
   medium-2x.jpg 2x"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; 
  &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/webp"&lt;/span&gt;
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"
   fallback-optimized.webp 1x, 
   fallback-optimized-2x.webp 2x"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"fallback.jpg"&lt;/span&gt; 
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"
   fallback.jpg 1x, 
   fallback-2x.jpg 2x"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"💞"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now we not only provided different images for different resolutions but we also provided the browser the possibility to then take the retina image and of that even the optimized version in the &lt;code&gt;webp&lt;/code&gt; format instead of &lt;code&gt;jpg&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/cL4pqu8GGRIihabgSM/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/cL4pqu8GGRIihabgSM/giphy.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;picture&lt;/code&gt; tag Conclusion
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;picture&lt;/code&gt; tag allows you to play a different image in different situations. E.g. if you were going to play a moving &lt;code&gt;.gif&lt;/code&gt; file but you want to improve A11y you could do something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; 
  &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(prefers-reduced-motion: reduce)"&lt;/span&gt;
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"
   no-motion.jpg 1x, 
   no-motion2x.jpg 2x,
   no-motion3x.jpg 1x 3x"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"funny_moving_gif.gif"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Funny Animals"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;






&lt;h1&gt;
  
  
  Conclusion: So when to use what?
&lt;/h1&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;picture&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;If you have a complex setup do yourself a favor, use &lt;code&gt;picture&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;&amp;lt;img srcset sizes ...&amp;gt;&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;If you have an image that stays the same ratio but shall be played in different quality versions e.g. actual Photographs such as those uploaded on Instagram or Facebook then you might would want to simplify your life by using &lt;code&gt;&amp;lt;img srcset&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;img srcset sizes&amp;gt;&lt;/code&gt; depending on what you want to achieve.&lt;/p&gt;

&lt;p&gt;Use the comments below for any questions.&lt;/p&gt;

</description>
      <category>responsive</category>
      <category>frontend</category>
      <category>html</category>
      <category>design</category>
    </item>
  </channel>
</rss>
