<?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: Klaus Kazlauskas</title>
    <description>The latest articles on DEV Community by Klaus Kazlauskas (@klauskpm).</description>
    <link>https://dev.to/klauskpm</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%2F69896%2Fda0eae39-d95a-4f2b-ae6a-49d4de872988.jpg</url>
      <title>DEV Community: Klaus Kazlauskas</title>
      <link>https://dev.to/klauskpm</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/klauskpm"/>
    <language>en</language>
    <item>
      <title>The saltiest and wrongest article about Big O ever</title>
      <dc:creator>Klaus Kazlauskas</dc:creator>
      <pubDate>Mon, 24 Nov 2025 16:55:00 +0000</pubDate>
      <link>https://dev.to/klauskpm/the-saltiest-and-wrongest-article-about-big-o-ever-1blm</link>
      <guid>https://dev.to/klauskpm/the-saltiest-and-wrongest-article-about-big-o-ever-1blm</guid>
      <description>&lt;p&gt;Sigh... So you want to learn about Big O Notation huh? Welp, you came to the wrong place, but stay for the ride AS YOU WALK INTO MY RANT ABOUT THIS THING FOR 20 PARAGRAPHS! &lt;strong&gt;YES, I'M SCREAMING&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nobody talks like that
&lt;/h2&gt;

&lt;p&gt;Ok. Maybe some people do, but it is VERY specific and rare. What am I talking about? Look at this function:&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;function&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&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;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&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;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bar&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bar&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;foo&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;If you just thought "Oh, that is an O(n^2)" then you are a Big O pervert. Sorry. I don't make the rules.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fw4fq96pu10o21x9zzi5h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fw4fq96pu10o21x9zzi5h.png" alt=" " width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In 15 years of web development, nobody ever reached out to me and talked in Big O terms. People would reach out to me and say "Yeah, that function is doing a nested loop. Maybe we can figure out a way of not doing it", like decent people.&lt;/p&gt;

&lt;p&gt;But hey, Big O is not that bad, and there might be scenarios where you need to talk like that. Like, when doing interviews. So when an interviewer asks you "What is the complexity of the function?" you know how to answer, and then proceed to never use it ever again. Or when you need to prove to the C-suite that an optimization needs to happen, so you present some calculations, which they don't understand but nod either way, and they might approve it if there is some lingering "let's make devs happy" budget.&lt;/p&gt;

&lt;p&gt;With all that said... That is not a problem with Big O itself. That is just how it is used in the industry. I think that understanding Big O is actually helpful. You can think more about how a function can become a bottleneck pretty easily by thinking how bad does it scale to infinity. Talking about that...&lt;/p&gt;

&lt;h2&gt;
  
  
  Infinites can be bigger than others, but why care?
&lt;/h2&gt;

&lt;p&gt;THEY CAN, OK?! Some of them are almost the same, but others? They are entirely different beasts. Let's look at these two functions:&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;function&lt;/span&gt; &lt;span class="nf"&gt;badFoo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&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;bar&lt;/span&gt; &lt;span class="o"&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;bibar&lt;/span&gt; &lt;span class="o"&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;tribar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&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="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;bibar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&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="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tribar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&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="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;bibar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tribar&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;goodFoo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&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;bar&lt;/span&gt; &lt;span class="o"&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;bibar&lt;/span&gt; &lt;span class="o"&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;tribar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&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;bibar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&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;tribar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&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="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;bibar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tribar&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;Both functions are O(n). One of them is obviously way worse than the other. It should be an O(3n). It actually is that, but if you present that as is someone will pop up saying "Um... Actually. While that is technically correct, you need to drop that constant as it is not a factor that depends on the n. We are only interested in how the function scales to infinity."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F6lilz47ty13prdqc9nkt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F6lilz47ty13prdqc9nkt.png" alt=" " width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You know what? This is what we are doing. It is a WAY bigger growth rate than just O(n). Which leads to a bigger infinite. I would understand if we were talking about sums, but multiplications?&lt;/p&gt;

&lt;p&gt;Look at the chart below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fwruh7o96q6x0xm6nnfay.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fwruh7o96q6x0xm6nnfay.png" alt="Big O notation chart comparing O(3n), O(n+200), and O(n). Where O(n+200) is worse than O(n) but it scales similarly, while O(3n) keeps getting worse" width="800" height="581"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see that the Green line is worse than the Red, but it is basically  following the same growth path. But take a look at the Black line there. That thing is getting farther and farther as the number of items grow. And how are all of them described? O(n).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ff264k9zaeuitxhfcrsf6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ff264k9zaeuitxhfcrsf6.png" alt=" " width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  I'm tired
&lt;/h2&gt;

&lt;p&gt;Look, this all probably makes sense to a lot of people and it is correct and all. It comes from math and it has been used for many generations. The objective is to look for the part of the function that actually grows the fastest to infinity. Big O notation is just trying to simplify and highlight the issue.&lt;/p&gt;

&lt;p&gt;That said, fuck you Big O, Theta, Omega, and the rest of your family as well. Nobody will come to your funeral.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fhx9lu0a2hatyyp2ns94k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fhx9lu0a2hatyyp2ns94k.png" alt=" " width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  Resources
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Big O chart: &lt;a href="https://www.desmos.com/calculator/kgwiv5zizm" rel="noopener noreferrer"&gt;https://www.desmos.com/calculator/kgwiv5zizm&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Header image: dev.to AI image generator&lt;/li&gt;
&lt;li&gt;Article images: Gemini Nano Banana&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>computerscience</category>
      <category>webdev</category>
      <category>rant</category>
      <category>funny</category>
    </item>
    <item>
      <title>Make your life easier with Set Compositions</title>
      <dc:creator>Klaus Kazlauskas</dc:creator>
      <pubDate>Tue, 20 Aug 2024 12:05:00 +0000</pubDate>
      <link>https://dev.to/klauskpm/make-your-life-easier-with-set-compositions-45j</link>
      <guid>https://dev.to/klauskpm/make-your-life-easier-with-set-compositions-45j</guid>
      <description>&lt;p&gt;Finally! When &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set" rel="noopener noreferrer"&gt;&lt;code&gt;Set&lt;/code&gt;&lt;/a&gt; was introduced in the past it already made our lives better. We were able to easily generate unique lists, but also have better performance on finding and setting items on those lists.&lt;/p&gt;

&lt;p&gt;That was great, but we were still missing several things that other languages had. And this is true, because we were. With the new composition methods added to &lt;code&gt;Set&lt;/code&gt; in 2024, we will finally be able to do union, intersection, difference, and more with simple calls.&lt;/p&gt;

&lt;p&gt;Without any further ado, lets jump on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Difference
&lt;/h2&gt;

&lt;p&gt;Returns a new &lt;code&gt;Set&lt;/code&gt; containing elements that exist in the first &lt;code&gt;Set&lt;/code&gt; but not in the second.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fas9vt5augmtq8up9f9sl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fas9vt5augmtq8up9f9sl.png" alt="A Venn diagram with circles A and B, and they are overlapping. The difference is the part of the A circle that is not overlapping the B circle." width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example: You want to see which users visited the site in this week that didn't visit last month.&lt;/p&gt;

&lt;p&gt;How to use it?&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;thisWeekUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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;lastMonthUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&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;newUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;thisWeekUsers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;difference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lastMonthUsers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newUsers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Set(2) { 1, 2 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How we would do that in the past?&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;thisWeekUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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;lastMonthUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;newUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;thisWeekUsers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;lastMonthUsers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newUsers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// (2) [1,2]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Learn more at: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/difference" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/difference&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Intersection
&lt;/h2&gt;

&lt;p&gt;Returns a new &lt;code&gt;Set&lt;/code&gt; with only the values that are present in both &lt;code&gt;Set&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk2kd4g24ig79or1iun1m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk2kd4g24ig79or1iun1m.png" alt="A Venn diagram with circles A and B, and they are overlapping. The intersection is the part overlapping part of circles A and B." width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example: You are adding an e-books bundle to the cart, but you already had some of those books there.&lt;/p&gt;

&lt;p&gt;How to use it?&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;booksBundle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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;cart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&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;booksToAdd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;booksBundle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;intersection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;booksToAdd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Set(2) { 3, 4 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How we would do that in the past?&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;booksBundle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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;cart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&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;booksToAdd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;booksBundle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;book&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;booksToAdd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// (2) [3, 4]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Learn more at: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/intersection" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/intersection&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Symmetric Difference
&lt;/h2&gt;

&lt;p&gt;Returns a new &lt;code&gt;Set&lt;/code&gt; with the values that do not repeat in neither groups.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ful30mklh9ecnrj3mf1e0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ful30mklh9ecnrj3mf1e0.png" alt="A Venn diagram with circles A and B, and they are overlapping. The symmetric difference is the part where circles A and B are not overlapping." width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example: Checking overstocked items between stores to check which items can be exchanged.&lt;/p&gt;

&lt;p&gt;How to use it?&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;firstStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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;secondStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&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;overstockedItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;firstStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;symmetricDifference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;secondStore&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;overstockedItems&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Set(4) { 1, 2, 5, 6 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How we would do that in the past?&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;firstStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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;secondStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&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;allItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;firstStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;secondStore&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;flat&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;overstockedItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;allItems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&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;return&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;firstStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&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="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;secondStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&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="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;overstockedItems&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// (4) [1, 2, 5, 6]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Learn more at: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/symmetricDifference" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/symmetricDifference&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Union
&lt;/h2&gt;

&lt;p&gt;Returns a new &lt;code&gt;Set&lt;/code&gt; with the values from both groups but without repeating any values.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0thktezpopbux29mfhu0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0thktezpopbux29mfhu0.png" alt="A Venn diagram with circles A and B, and they are overlapping. The union is all the content from circles A and B. This means the parts that are and aren't overlapping." width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example: You and your friend want to merge playlists, but some music are the same.&lt;/p&gt;

&lt;p&gt;How to use it?&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;yourPlaylist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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;friendPlaylist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&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;mergedPlaylist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;yourPlaylist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;union&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;friendPlaylist&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mergedPlaylist&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Set(6) { 1, 2, 3, 4, 5, 6 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How we would do that in the past?&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;yourPlaylist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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;friendPlaylist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&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;mergedPlaylist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;yourPlaylist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;friendPlaylist&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;flat&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mergedPlaylist&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// (6) [1, 2, 3, 4, 5, 6]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Learn more at: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/union" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/union&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Is Disjoint From?
&lt;/h2&gt;

&lt;p&gt;It returns a &lt;code&gt;Boolean&lt;/code&gt;. It is true if both &lt;code&gt;Set&lt;/code&gt; have no values in common, and false if they have at least one value in common.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ih58xz69trumgpmb0co.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ih58xz69trumgpmb0co.png" alt="A Venn diagram with circles A and B, and they are not overlapping. This means they are disjointed." width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example: See there are products that are part of other groups.&lt;/p&gt;

&lt;p&gt;How to use it?&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;electronics&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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;furniture&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&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;groceries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;apple&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;electronics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isDisjointFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;furniture&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;electronics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isDisjointFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;groceries&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How we would do that in the past?&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;electronics&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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;furniture&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&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;groceries&lt;/span&gt; &lt;span class="o"&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;apple&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;isDisjoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;array2&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;array1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;every&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;array2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&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="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isDisjoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;electronics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;furniture&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isDisjoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;electronics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;groceries&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Learn more at: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/isDisjointFrom" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/isDisjointFrom&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Is Superset/Subset Of?
&lt;/h2&gt;

&lt;p&gt;These two functions are very similar. They both return a &lt;code&gt;Boolean&lt;/code&gt; value, and are direct opposites. Superset will return true if the &lt;code&gt;Set&lt;/code&gt; is a superset of another, and Subset will return true if the &lt;code&gt;Set&lt;/code&gt; is a subset of another.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I'm putting those functions together because knowing the answer to one of them is enough to know the other. A &lt;code&gt;Set&lt;/code&gt; can only be a superset of a subset &lt;code&gt;Set&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1oh8p6a26qooq5iu79s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1oh8p6a26qooq5iu79s.png" alt="A Venn diagram with circles A and B, where B is smaller than A and it is inside of it. The picturing is representing that B is a subset of A, and A is a superset of B." width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example: Understand if users are part of a company group.&lt;/p&gt;

&lt;p&gt;How to use it?&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;itDepartment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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;genZFromToronto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;itDepartment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isSupersetOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;genZFromToronto&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;genZFromToronto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isSubsetOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;itDepartment&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How we would do that in the past?&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;itDepartment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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;genZFromToronto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;genZFromToronto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;every&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;itDepartment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&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="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Learn more at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/isSupersetOf" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/isSupersetOf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/isSubsetOf" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/isSubsetOf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Now you are all &lt;code&gt;Set&lt;/code&gt; &lt;del&gt;I'm not sorry&lt;/del&gt; to use it in your project!&lt;/p&gt;

&lt;p&gt;Let me know if you are also excited about it, another feature, or want to see something else covered. Until next time o/&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>TIL: Gemini can analyze errors directly on the browser</title>
      <dc:creator>Klaus Kazlauskas</dc:creator>
      <pubDate>Sun, 18 Aug 2024 16:00:00 +0000</pubDate>
      <link>https://dev.to/klauskpm/til-gemini-can-analyze-errors-directly-on-the-browser-g45</link>
      <guid>https://dev.to/klauskpm/til-gemini-can-analyze-errors-directly-on-the-browser-g45</guid>
      <description>&lt;p&gt;So, I was using Chrome's console to debug something today when I noticed a bulb icon on the right side of it saying "Understand this error". I clicked it, accepted the warning message saying the data will be sent to Google, and voila! The error was explained to me.&lt;/p&gt;

&lt;p&gt;Here is on app they provide to test: &lt;a href="https://bubble-jingle.web.app/search" rel="noopener noreferrer"&gt;https://bubble-jingle.web.app/search&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxjm6ktjsj78iffu2cdks.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxjm6ktjsj78iffu2cdks.png" alt="A screenshot showing a CORS error, which will be explained right after this." width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The example app forces a CORS error, and when you click to understand it, it explains what is a CORS error, what is the problem, and some possible solutions.&lt;/p&gt;

&lt;p&gt;This feature is called &lt;strong&gt;Console Insights&lt;/strong&gt;, uses Gemini, and it should be on by default if you have Chrome v125 and meets their other requirements. If it is not turned on for you, check their requirements: &lt;a href="https://developer.chrome.com/docs/devtools/console/understand-messages" rel="noopener noreferrer"&gt;https://developer.chrome.com/docs/devtools/console/understand-messages&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep In Mind
&lt;/h3&gt;

&lt;p&gt;On their own article they describe some issues to be aware, like &lt;a href="https://developer.chrome.com/docs/devtools/console/understand-messages#prompt-injection" rel="noopener noreferrer"&gt;prompt injection&lt;/a&gt; and &lt;a href="https://developer.chrome.com/docs/devtools/console/understand-messages#wrong-explanation" rel="noopener noreferrer"&gt;wrong explanations&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Another point is how the data is used. Be sure to only submit data or have the feature on if you agree and trust how they are dealing with it: &lt;a href="https://developer.chrome.com/docs/devtools/console/understand-messages#data-use" rel="noopener noreferrer"&gt;https://developer.chrome.com/docs/devtools/console/understand-messages#data-use&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;AI is for sure not perfect and there are many issues around it, but I would love to have something like that when I was beginning. That said, it will for sure make my day-to-day easier (when it doesn't hallucinate).&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>learning</category>
    </item>
    <item>
      <title>Hora de substituir o Redux</title>
      <dc:creator>Klaus Kazlauskas</dc:creator>
      <pubDate>Sat, 27 Apr 2024 13:09:35 +0000</pubDate>
      <link>https://dev.to/klauskpm/hora-de-substituir-o-redux-331d</link>
      <guid>https://dev.to/klauskpm/hora-de-substituir-o-redux-331d</guid>
      <description>&lt;p&gt;Olá pessoas! Vamos deixar claro desde o início que Redux não é ruim. Ruim é a forma como usam ele. Eu uso o ele desde 2016, e muitas vezes vejo as pessoas cometendo os mesmos erros. O principal? Querem usar Redux para tudo.&lt;/p&gt;

&lt;p&gt;Muitas vezes as pessoas começam usando Redux para resolver problemas que fazem sentido, mas logo começam a cair na armadilha de adicionar o resto da aplicação para fazer sentido o investimento em usar o Redux. "Fica mais fácil e tudo centralizado" eles dizem, mas na maioria das vezes não fica.&lt;/p&gt;

&lt;p&gt;Mas, o que é esse tudo o que eu to falando?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ea4hirly8ixbn3vi95w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ea4hirly8ixbn3vi95w.png" alt="Texto escrito Tudão.png" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é tudo?
&lt;/h2&gt;

&lt;p&gt;Estados locais como coisas visuais e formulários, estados de uma única página como query strings de URL, estados simples e não compartilhados, e requisições simples que não precisam ser cacheadas.&lt;/p&gt;

&lt;p&gt;Você consegue resolver todos os problemas de cima com soluções simples, porque todos esses problemas são simples. Redux é complexo porque é feito para resolver problemas complexos. Mas como falei, muitas pessoas insistem em usar isso como uma bala de prata que funciona para tudo.&lt;/p&gt;

&lt;p&gt;Não só você está tornando seu código mais complexo, como também está introduzindo mais responsabilidades pra você. Em vez de ter um estado que some quando o componente ou Context são destruídos, agora você tem um estado global cacheado que só será limpo se você tomar uma ação. Gerenciar cache é complicado, e o Redux puro não é a ferramenta aconselhada pra isso.&lt;/p&gt;

&lt;p&gt;Os melhores casos pro Redux são estados complexos e com muitas interações. Isso não sou nem só eu que digo. Desde 2016 essa é uma opinião popular compartilhada por várias pessoas, incluindo um dos &lt;a href="https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367"&gt;criadores do Redux&lt;/a&gt; e também está no próprio &lt;a href="https://redux.js.org/faq/general#when-should-i-use-redux"&gt;site do Redux&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Dito tudo isso... Até nesses casos eu ainda aconselharia outras opções além do Redux.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mas qual é o problema do Redux?
&lt;/h2&gt;

&lt;p&gt;Na real, são problemas. Não existe nenhuma opção na vida que seja perfeita. Tudo tem pontos positivos e negativos, e o Redux não é excessão. Além disso, na minha opinião, já surgiram muitas outras bibliotecas que resolvem os problemas que o Redux tenta resolver e de forma melhor.&lt;/p&gt;

&lt;p&gt;Os principais problemas pra mim são a quantidade de código, e a gerenciamento de cache.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quantidade de código
&lt;/h3&gt;

&lt;p&gt;Recentemente eu troquei várias páginas de um projeto que estava usando Redux por &lt;code&gt;@tanstack/react-query&lt;/code&gt; e a redução foi de mais ou menos 50% do código. Mesmo contando com &lt;code&gt;yarn.lock&lt;/code&gt;, configuração pra testes e do projeto, ainda assim eram 200 linhas adicionadas pra 360 removidas.&lt;/p&gt;

&lt;p&gt;Por que isso? Porque Redux não era a solução ideal pra isso, mais especificamente, Redux Toolkit. Bem provavel que o RTK Query (Redux Toolkit Query) também reduzisse bastante as linhas de código, mas no final as soluções apresentadas pelo &lt;code&gt;@tanstack/react-query&lt;/code&gt; eram melhores pro nosso projeto.&lt;/p&gt;

&lt;p&gt;Outro exemplo são estados compartilhados e globais. Se eles ainda são simples ou não mudam muito, como permissões, tema, ou lingua, você pode muito bem manter eles em um &lt;code&gt;Context&lt;/code&gt;. O código pra manter isso é muito menor, e mais fácil de entender.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gerenciamento de cache
&lt;/h3&gt;

&lt;p&gt;Redux e RTK (Redux Toolkit) em si não foram feitos para gerenciar cache. RTK Query foi. Não só ele, como várias outras ferramentas. Mas o que eu quero dizer com isso? Que quando você tenta usar apenas Redux ou RTK, você terá que desenvolver todas essas técnicas. Você vai ter que pensar nos items a seguir e muito mais:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quando que devemos eliminar/invalidar o cache?&lt;/li&gt;
&lt;li&gt;Quando que o cache vai estar "vencido"?&lt;/li&gt;
&lt;li&gt;Vamos usar parte dos dados primeiro e fazer um request por trás?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;São várias pequenas decisões, onde cada uma traz seus problemas, e que a responsabilidade de planejar todas elas passou a ser nossa. Não precisa ser assim. Como falei antes, tem ferramentas que já fazem isso pra gente. RTK Query, TanStack Query, Apollo Client, etc. Todos eles tem várias ferramentas para poder lidar com o cache. Nós ainda temos a responsabilidade de saber como e onde usar, mas não precisamos desenvolver toda a lógica por trás disso e seus bugs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Pare de usar Redux para tudo. Problema simples, solução simples. Como o pessoal fala use o KISS (Keep it simple stupid) ou a versão brasileira, o MSO:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fprixaivrbic6yhe9h26g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fprixaivrbic6yhe9h26g.png" alt='Rogerinho do Ingá falando "Mantenha simples otário"' width="495" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Espero ter ajudado, e até a próxima \o/&lt;/p&gt;

</description>
      <category>braziliandevs</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Simplificando Feature Flags com DevCycle</title>
      <dc:creator>Klaus Kazlauskas</dc:creator>
      <pubDate>Mon, 10 Jul 2023 15:26:45 +0000</pubDate>
      <link>https://dev.to/klauskpm/simplificando-feature-flags-com-devcycle-2mgo</link>
      <guid>https://dev.to/klauskpm/simplificando-feature-flags-com-devcycle-2mgo</guid>
      <description>&lt;p&gt;Se você já tentou criar Feature Flags na mão, você sabe o inferno que é. Você tem que pensar em ...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Alterar feature flags sem precisar de deploys;&lt;/li&gt;
&lt;li&gt;Ter configuração pra diferentes ambientes;&lt;/li&gt;
&lt;li&gt;Dar acesso a quem precisa criar/configurar feature flags;&lt;/li&gt;
&lt;li&gt;Saber se uma feature flag é usada e pode ser deletada;&lt;/li&gt;
&lt;li&gt;Teste A/B, widget de feature flags, grupo de usuários, gereciamento por API, criar e dar manutenção pra solução ...&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Então, pra que inventar a roda e não simplesmente usar uma coisa pronta? Ai que entra o DevCycle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mas... por que o DevCycle? 😐
&lt;/h2&gt;

&lt;p&gt;Além de eles terem &lt;a href="https://devcycle.com/features/sdk"&gt;SDKs para a maioria das grandes linguagens e plataformas&lt;/a&gt;, e também terem uma &lt;a href="https://devcycle.com/features/management-api"&gt;API para gerenciar feature flags&lt;/a&gt;, eles tem integrações com outros serviços e uma &lt;a href="https://docs.devcycle.com/tools-and-integrations/cli/"&gt;CLI própria&lt;/a&gt;. Com esses dois últimos, tu vai poder saber onde suas feature flags estão implementadas e &lt;strong&gt;&lt;a href="https://docs.devcycle.com/tools-and-integrations/cli/docs/cleanup"&gt;REMOVER AS FEATURE FLAGS COM UM COMANDO&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q6RgfbiC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d8m3djckq1bvakupblya.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q6RgfbiC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d8m3djckq1bvakupblya.gif" alt="Pessoa positivamente surpresa e batendo palmas" width="400" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Essa plataforma tem váááárias outras coisas fodas, mas essas duas últimas foram as que mais me pegaram no coração. Lógico, existem outras paltaformas como &lt;a href="https://launchdarkly.com/"&gt;LaunchDarkly&lt;/a&gt; e &lt;a href="https://www.harness.io/"&gt;Harness&lt;/a&gt; que oferecem serviços parecidos ou até melhores que o DevCycle, mas ...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z4E6H-V---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t6eruqepaopnvybvnhpw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z4E6H-V---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t6eruqepaopnvybvnhpw.gif" alt='Meme do "eu quero é ó... preço"' width="498" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Preço! 💰
&lt;/h3&gt;

&lt;p&gt;DevCycle começa gratuito e escala de acordo com seu negócio. Outras alternativas normalmente não começam gratuitas, e escalam por quantidade de projetos, ou pessoas usando, o que sempre foi muito ruim pra mim. Isso força a gente a entulhar tudo em um projeto, e ter aquela famosa conta compartilhada na empresa. Quem nunca? Risco de segurança? Nada. De boas. Só olha pro lado.&lt;/p&gt;




&lt;h2&gt;
  
  
  Vamos começar 🏁
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1) Crie um projeto React e instale o DevCycle:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Cria o projeto react-ff&lt;/span&gt;
npm create vite@latest react-ff &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--template&lt;/span&gt; react

&lt;span class="c"&gt;# Entra no projeto&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;react-ff

&lt;span class="c"&gt;# Instala o SDK de React do DevCycle&lt;/span&gt;
npm i @devcycle/devcycle-react-sdk

&lt;span class="c"&gt;# Verifica que o projeto está funcionando&lt;/span&gt;
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2) Crie um arquivo .env
&lt;/h3&gt;

&lt;p&gt;Na raiz do seu projeto, crie um arquivo &lt;code&gt;.env&lt;/code&gt; com um valor temporário. Mais tarde vamos colocar o valor definitivo aqui.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VITE_DVC_SDK_KEY=valor_temporario
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3) Adicione uma feature flag ao projeto
&lt;/h3&gt;

&lt;p&gt;No arquivo &lt;code&gt;App.jsx&lt;/code&gt; faça as seguintes alterações:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;useVariableValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;withDVCProvider&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="s2"&gt;@devcycle/devcycle-react-sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Busca a variável ainda não criada, usando false como o valor padrão.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myFeatureFlag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useVariableValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-feature-flag&lt;/span&gt;&lt;span class="dl"&gt;'&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* vai rederizar o falso por enquanto */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;myFeatureFlag&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;My feature flag is on!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;myFeatureFlag&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;My feature flag is off!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;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="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;withDVCProvider&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;sdkKey&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;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_DVC_SDK_KEY&lt;/span&gt;
&lt;span class="p"&gt;})(&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4) Configurando o DevCycle e sua feature flag
&lt;/h3&gt;

&lt;p&gt;Registre uma conta no &lt;a href="https://auth.devcycle.com/u/login"&gt;DevCycle&lt;/a&gt;. Depois disso, crie uma organização e projeto qualquer (depois você vai poder deletar e recriar a vontade), e uma feature flag do tipo Release com o mesmo nome que usamos antes (&lt;code&gt;my-feature-flag&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Dentro do DevCycle, no menu superior no canto direito, clique no ícone de chave. Você vai ser redirecionado para a página de Keys dos SDK por ambiente. Copie o Client do Development, e substitua &lt;code&gt;valor_temporario&lt;/code&gt; no &lt;code&gt;.env&lt;/code&gt; por essa sua chave. Se tudo deu certo, você deve ver que a sua feature flag está ativa. Agora você pode voltar pro DevCycle e brincar com ela a vontade.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nota: Não se esqueça de que você vai precisar fazer essa configuração para os demais ambientes que tiver.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Recapitulando 🔛
&lt;/h2&gt;

&lt;p&gt;Em poucos passos conseguimos ter um projeto com uma feature flag funcionando. Foi menos tempo do que levaríamos pra pensar em como fazer uma solução simples, e ainda é gratuito até seu negócio crescer o suficiente.&lt;/p&gt;

&lt;p&gt;Além disso, você vai saber as métricas de uso, poderá saber onde no código está sendo implementado pela plataforma ou pelo CLI, e até fazer uma migração progressiva do sistema que está usando atualmente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finalizando 🎉
&lt;/h2&gt;

&lt;p&gt;Espero que esse artigo tenha te ajudado de  alguma forma, e nos vemos na próxima \o/&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>featureflags</category>
      <category>devcycle</category>
    </item>
    <item>
      <title>Data Driven Design System com Omlet</title>
      <dc:creator>Klaus Kazlauskas</dc:creator>
      <pubDate>Wed, 24 May 2023 12:29:52 +0000</pubDate>
      <link>https://dev.to/klauskpm/revolucione-seus-componentes-com-a-analise-de-dados-do-omlet-1ggp</link>
      <guid>https://dev.to/klauskpm/revolucione-seus-componentes-com-a-analise-de-dados-do-omlet-1ggp</guid>
      <description>&lt;p&gt;Oie! Eu me chamo Klaus Kazlauskas, sou desenvolvedor a mais de 10 anos, e eu estou esperando por algo como o Omlet esse tempo todo.&lt;/p&gt;

&lt;p&gt;Você já esteve em um projeto e quis saber quantas vezes seus componentes são usados, ou onde ele é usado? Já quis saber quantos Buttons diferentes foram criados no seu projeto? Ou até mesmo sentiu uma falta de confiança na hora de atualizar componentes? Então, Omlet resolveu tudo isso pra mim.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é o Omlet?
&lt;/h2&gt;

&lt;p&gt;É uma ferramenta, em beta, que está sendo desenvolvida pela equipe do Zeplin, para coletar dados de uso dos componentes de múltiplos projetos. Rodando apenas 3 comandos, você vai saber:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quantas vezes seu componente foi usado;&lt;/li&gt;
&lt;li&gt;Quais dependem dele, e quais são dependências dele;&lt;/li&gt;
&lt;li&gt;Quais projetos estão usando os componentes;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br&gt;
&lt;em&gt;Fonte: &lt;a href="https://omlet.dev/" rel="noopener noreferrer"&gt;Site do Omlet&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;No momento que esse artigo foi criado, a ferramenta ainda está em beta, e só suporta componentes escritos em React.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Primeiros passos com o Omlet
&lt;/h2&gt;

&lt;p&gt;Antes de rodar os comandos, precisamos criar uma conta no &lt;a href="https://omlet.dev/" rel="noopener noreferrer"&gt;https://omlet.dev/&lt;/a&gt; e dar um nome pro nosso ÚNICO workspace. Como a ferramenta está em beta, no momento você só pode ter 1 workspace por conta/e-mail, então de um bom nome ou use um e-mail para testes.&lt;/p&gt;

&lt;p&gt;Com o workspace criado, escolha o repositório React que você quer coletar dados dos componentes, e rode os seguintes comandos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;npm i --save-dev @omlet/cli&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npx omlet login&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npx omlet init&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Nas próximas vezes, ou após instalar em outros repositórios, você só vai precisar rodar &lt;code&gt;npx omlet analyze&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pronto. Após alguns segundos você receberá uma URL para o seu workspace com o scan finalizado, e você terá que escolher a pasta ou projeto que tem os seus componentes principais. Agora você tem acesso instantâneo aos dados de uso dos seus componentes. Depois você poderá automatizar isso com uma configuração de CI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aba de análise (Analytics)
&lt;/h3&gt;

&lt;p&gt;Nessa aba você tem acesso instantâneo a uma visão geral dos seus componentes e projetos. São apresentados gráficos como: &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Componentes principais vs secundários&lt;/strong&gt;&lt;br&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%2Fn6ogmltuwb3eztxh79t1.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%2Fn6ogmltuwb3eztxh79t1.png" alt="Gráfico de área mostrando a progressão do uso de componentes principais vs secundários durante o tempo"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Fonte: &lt;a href="https://omlet.dev/" rel="noopener noreferrer"&gt;Site do Omlet&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Componentes mais utilizados&lt;/strong&gt;&lt;br&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%2Fm8jtjeehiuxr94a2vs4y.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%2Fm8jtjeehiuxr94a2vs4y.png" alt="Dois gráficos em barra horizontal, onde cada um mostra os 7 componentes mais utilizados, e com uma nota de rodapé dando informações extras. O gráfico a esquerda é sobre componentes principais/core, e o da direita é sobre componentes secundários/custom."&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Fonte: &lt;a href="https://omlet.dev/" rel="noopener noreferrer"&gt;Site do Omlet&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Aba de componentes
&lt;/h3&gt;

&lt;p&gt;Nessa aba você terá acesso a lista de todos os seus componentes de todos os seus projetos, além de poder olhar onde e como seu componente é usado ao clicar nele.&lt;br&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%2Fy67y6d771wjq21ey0exu.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%2Fy67y6d771wjq21ey0exu.png" alt="O lado esquerdo da página contém dados do componente, como quantidade de utilizações e caminho. No lado direito tem um gráfico mostrando quais componentes usam e são usados pelo componente."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Página de tags
&lt;/h3&gt;

&lt;p&gt;Aqui você pode criar quantas tags você quiser, e adicionar para os projetos ou pastas que quiser. Por exemplo, você pode ter a tag &lt;code&gt;core&lt;/code&gt; no projeto da sua biblioteca de componentes, e uma tag de &lt;code&gt;deprecated&lt;/code&gt; algumas pastas dessa biblioteca. Assim você consegue trackear a adoção dos novos componentes.&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%2Fxiqepbztml0q4ij5yh2r.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%2Fxiqepbztml0q4ij5yh2r.png" alt="No lado esquerdo tem a caixa de tags, onde você pode deletar ou criar novas tags. No lado direito tem a lista de projetos e pastas, em formato de árvore de pastas, com as tags associadas as pastas."&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Casos de uso
&lt;/h2&gt;

&lt;p&gt;Agora que você sabe sobre o Omlet, instalou ele, e sabe das páginas, que tal saber mais problemas que ele pode resolver pra você?&lt;/p&gt;

&lt;p&gt;Aqui vai uma lista de problemas que o Omlet vai ou já resolveu pra mim:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Usando a página de componentes:

&lt;ul&gt;
&lt;li&gt;Achar onde os componentes são utilizados (em segundos)&lt;/li&gt;
&lt;li&gt;Saber quais componentes são inúteis e onde eles são usados&lt;/li&gt;
&lt;li&gt;Descobrir componentes com nome parecidos&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Usando tags:

&lt;ul&gt;
&lt;li&gt;Saber quais componentes queremos refatorar&lt;/li&gt;
&lt;li&gt;Resolver conflitos de organização ou agrupamento de pastas&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Usando dashboards + tags:

&lt;ul&gt;
&lt;li&gt;Saber como está a adoção dos componentes&lt;/li&gt;
&lt;li&gt;Saber o progresso da refatoração dos projetos&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Esses e mais outros problemas podem ser resolvidos hoje com ele, e o melhor, você não precisa gastar HORAS criando e MANTENDO documentos, listas, gráficos e apresentações. Está tudo disponível para você e sua equipe.&lt;/p&gt;




&lt;h2&gt;
  
  
  Concluindo
&lt;/h2&gt;

&lt;p&gt;Botando um pouco os pés no chão, vamos relembrar que é uma ferramenta em beta, então espere erros e faltar algumas funções; não é open source, então um dia vão cobrar pra usar; hoje só suporta React, mas tem planos para suportar outras tecnologias.&lt;/p&gt;

&lt;p&gt;Dito isso, o Omlet é foda! Ainda acho que o Omlet vai se tornar essencial para quem lida com projetos médios a grandes, ou até mesmo múltiplos pequenos projetos e um design system. Então o futuro preço a ser cobrado deve valer MUITO a pena, principalmente quando comparado com as horas ou dias gastos refatorando coisas que não tem valor, ou pesquisando e trazendo resultados insatisfatórios.&lt;/p&gt;




&lt;p&gt;Espero que esse artigo tenha te ajudado. Se gostou, não esqueça de reagir ou compartilhar com seus amigos e colegas, ou seguir se quiser mais artigos como esse.&lt;/p&gt;

&lt;p&gt;Não deixe de comentar melhorias ou abrir discussões abaixo!&lt;/p&gt;

&lt;p&gt;Um forte abraço e te vejo na próxima \o/&lt;/p&gt;

</description>
      <category>braziliandevs</category>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>Iniciando um Design System com Storybook 5.3 e Angular</title>
      <dc:creator>Klaus Kazlauskas</dc:creator>
      <pubDate>Fri, 31 Jan 2020 11:02:11 +0000</pubDate>
      <link>https://dev.to/klauskpm/iniciando-um-design-system-com-storybook-5-3-e-angular-47i3</link>
      <guid>https://dev.to/klauskpm/iniciando-um-design-system-com-storybook-5-3-e-angular-47i3</guid>
      <description>&lt;p&gt;O &lt;a href="https://twitter.com/mshilman/status/1217081058849517568" rel="noopener noreferrer"&gt;Storybook 5.3 foi lançado oficialmente&lt;/a&gt; há duas semanas e ele trouxe &lt;a href="https://medium.com/storybookjs/storybook-5-3-83e114e8797c" rel="noopener noreferrer"&gt;ótimas melhorias&lt;/a&gt;. Além de ficar mais fácil de usar e configurar, ele não é mais "só" um explorador de componentes UI. Ele se tornou uma ferramenta incrível para desenvolver um &lt;a href="https://brasil.uxdesign.cc/entendendo-design-system-f375bbb6f704" rel="noopener noreferrer"&gt;Design System&lt;/a&gt;, e eu vou explorar isso com vocês!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Esse artigo é baseado principalmente nos 4 artigos, criados pela equipe do Storybook, sobre esse lançamento. Se quiser ver essas histórias, que são mais curtas e estão separadas, você pode pular direto para Fontes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Se você não sabe o que é o Storybook, recomendo ler meu artigo anterior, pois também vou usar o projeto dele como base para esse artigo.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/klauskpm" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F69896%2Fda0eae39-d95a-4f2b-ae6a-49d4de872988.jpg" alt="klauskpm"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/klauskpm/como-criar-uma-biblioteca-de-componentes-com-angular-e-storybook-420p" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Como criar uma biblioteca de componentes com Angular e Storybook&lt;/h2&gt;
      &lt;h3&gt;Klaus Kazlauskas ・ Jan 3 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#angular&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#storybook&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;Índice dos tópicos principais:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Atualizando os pacotes&lt;/li&gt;
&lt;li&gt;Configuração declarativa&lt;/li&gt;
&lt;li&gt;Geração automática de documentação&lt;/li&gt;
&lt;li&gt;Iniciando um Design System com MDX&lt;/li&gt;
&lt;li&gt;Storybook focado em Design&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Preparação
&lt;/h1&gt;

&lt;p&gt;Na época que esse guia foi preparado, foram usadas as seguintes tecnologias:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;tecnologia&lt;/th&gt;
&lt;th&gt;versão&lt;/th&gt;
&lt;th&gt;instalação&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;td&gt;11.6.0&lt;/td&gt;
&lt;td&gt;&lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;como instalar&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NPM&lt;/td&gt;
&lt;td&gt;6.13.4&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Já vem com o Node.js&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Angular CLI&lt;/td&gt;
&lt;td&gt;8.3.21&lt;/td&gt;
&lt;td&gt;&lt;a href="https://angular.io/guide/setup-local#step-1-install-the-angular-cli" rel="noopener noreferrer"&gt;como instalar&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storybook&lt;/td&gt;
&lt;td&gt;5.3.8&lt;/td&gt;
&lt;td&gt;como instalar&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Todo o código desse projeto está no GitHub. Então, caso você se perca em qualquer parte, pode fazer uma comparação direta:&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/klauskpm" rel="noopener noreferrer"&gt;
        klauskpm
      &lt;/a&gt; / &lt;a href="https://github.com/klauskpm/angular-storybook" rel="noopener noreferrer"&gt;
        angular-storybook
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Repositório para ensinar a usar Storybook com Angular.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;





&lt;h1&gt;
  
  
  Atualizando os pacotes
&lt;/h1&gt;

&lt;p&gt;Se você &lt;a href="https://dev.to/klauskpm/como-criar-uma-biblioteca-de-componentes-com-angular-e-storybook-420p#instalando-o-storybook"&gt;instalou os pacotes do Storybook&lt;/a&gt; e agora precisa atualizar eles, não se preocupe. Você só precisa rodar o seguinte comando no seu terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# dentro do seu projeto&lt;/span&gt;
npx npm-check-updates &lt;span class="s1"&gt;'/storybook/'&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;O &lt;a href="https://www.npmjs.com/package/npm-check-updates" rel="noopener noreferrer"&gt;&lt;code&gt;npm-check-updates&lt;/code&gt;&lt;/a&gt; é um pacote que verifica se um pacote precisa atualizar. Nós passamos uma expressão regular para ele achar todos os pacotes que tenham storybook no nome, e a opção &lt;code&gt;-u&lt;/code&gt; para atualizar o nosso &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;npx&lt;/code&gt; é um comando do Node/npm para executar pacotes sem precisar instalar eles. Ótimo para casos em que não queremos instalar um pacote globalmente porque só vamos usar ele apenas uma vez.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pode comparar o seu progresso com a &lt;a href="https://github.com/klauskpm/angular-storybook/tree/v2.0" rel="noopener noreferrer"&gt;tag v2.0 do repositório&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h1&gt;
  
  
  Configuração declarativa
&lt;/h1&gt;

&lt;p&gt;O Storybook já tinha uma configuração bem simples, mas tinham alguns pontos que poderiam melhorar, como alguns nomes que não eram claros de acordo com as responsabilidades e a utilização da API do Webpack. Agora que resolveram esses problemas, vamos ver como a ela ficou.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;main.js&lt;/code&gt;
&lt;/h2&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%2Fmiro.medium.com%2Fmax%2F2794%2F1%2Aq_AI89haHMbERQslHrXyAA.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%2Fmiro.medium.com%2Fmax%2F2794%2F1%2Aq_AI89haHMbERQslHrXyAA.png" alt="Resumindo o config.js, addons.js e presets.js no novo arquivo main.js"&gt;&lt;/a&gt;&lt;a href="https://medium.com/storybookjs/declarative-storybook-configuration-49912f77b78" rel="noopener noreferrer"&gt;&lt;em&gt;Fonte&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;main.js&lt;/code&gt; é o arquivo principal de configuração do Storybook e é responsável por tudo que lida com a renderização das nossas histórias. Nesse arquivo vamos declarar, onde devemos buscar as histórias e como identificar elas, quais são os addons da aplicação e as configurações de presets.&lt;/p&gt;

&lt;p&gt;Vamos ver como escrevíamos antes e como é hoje.&lt;/p&gt;
&lt;h3&gt;
  
  
  Antes
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;.storybook/config.js&lt;/strong&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;configure&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&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../src&lt;/span&gt;&lt;span class="dl"&gt;'&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="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;stories&lt;/span&gt;&lt;span class="se"&gt;\.[&lt;/span&gt;&lt;span class="sr"&gt;tj&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;s$/&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../projects&lt;/span&gt;&lt;span class="dl"&gt;'&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="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;stories&lt;/span&gt;&lt;span class="se"&gt;\.[&lt;/span&gt;&lt;span class="sr"&gt;tj&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;s$/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;module&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;.storybook/addons.js&lt;/strong&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="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/addon-knobs/register&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/addon-actions/register&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;h3&gt;
  
  
  Depois
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;.storybook/main.js&lt;/strong&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="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;stories&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;../src/**/*.stories.(ts|js)&lt;/span&gt;&lt;span class="dl"&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;../projects/**/*.stories.(ts|js)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;addons&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;@storybook/addon-knobs&lt;/span&gt;&lt;span class="dl"&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;@storybook/addon-actions&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;p&gt;Com isso nós conseguimos matar o &lt;code&gt;config.js&lt;/code&gt; e o &lt;code&gt;addons.js&lt;/code&gt; do nosso projeto e temos uma configuração bem mais simples de entender. Apesar de nesse exemplo nós termos matado o &lt;code&gt;config.js&lt;/code&gt;, nós poderíamos ter outras configurações nele. Essas configurações foram absorvidas pelo &lt;code&gt;preview.js&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;preview.js&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;O &lt;code&gt;preview.js&lt;/code&gt; cuida do iframe que exibe (preview) a sua história e das configurações globais. É nele que vamos fazer a importação de CSS e polyfill, e configurações de parâmetros e decorators, que era a segunda responsabilidade do &lt;code&gt;config.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;No nosso caso só vamos configurar o addon &lt;code&gt;knobs&lt;/code&gt;, que estava sendo configurado dentro do &lt;code&gt;simple-button/index.stories.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;.storybook/preview.js&lt;/strong&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;addDecorator&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="s2"&gt;@storybook/angular&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;withKnobs&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="s2"&gt;@storybook/addon-knobs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;addDecorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;withKnobs&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;manager.js&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;O &lt;code&gt;manager.js&lt;/code&gt; cuida da parte gráfica que está em volta dos "previews" das histórias e também a parte dos addons. É nele que vamos adicionar configurações como temas, logo e nome da empresa, e configurações de exibição dos addons.&lt;/p&gt;

&lt;p&gt;Vamos criar um tema com a base clara e definir que o nome do nosso Storybook é "Angular Storybook":&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;.storybook/manager.js&lt;/strong&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;create&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/theming/create&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;addons&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="s2"&gt;@storybook/addons&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;addons&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;brandTitle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Angular Storybook&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;p&gt;E vamos ter o seguinte resultado:&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fxvfvwtdswltuta93kqzc.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fxvfvwtdswltuta93kqzc.png" alt="Storybook com título definido no manager.js"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O layout continua o mesmo, mas, em vez da logo do Storybook, está aparecendo o nome do nosso projeto definido no tema.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Se quiser saber mais sobre a parte de tema, você pode ver a &lt;a href="https://storybook.js.org/docs/configurations/theming/" rel="noopener noreferrer"&gt;documentação oficial sobre criação de temas&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Separadores de hierarquia
&lt;/h2&gt;

&lt;p&gt;Antes do 5.3, o Storybook aceitava vários tipos de separadores de hierarquia, como &lt;code&gt;|&lt;/code&gt;, &lt;code&gt;\&lt;/code&gt; e &lt;code&gt;.&lt;/code&gt;. mas agora ele força a hierarquia a ser definida sempre com &lt;code&gt;/&lt;/code&gt;. Então, uma história que tinha esse título &lt;code&gt;UI|Buttons &amp;amp; Indicators/Button&lt;/code&gt; ficaria assim &lt;code&gt;UI/Buttons &amp;amp; Indicators/Button&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Vamos revisitar o nosso &lt;code&gt;simple-button/index.stories.ts&lt;/code&gt; e substituir o título da história respeitando a nova hierarquia:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;projects/storybook-ui/src/lib/simple-button/index.stories.ts&lt;/strong&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;SimpleButtonComponent&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;./simple-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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;text&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/addon-knobs&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;moduleMetadata&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&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;action&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/addon-actions&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;UI / Button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;decorators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;moduleMetadata&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;declarations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;SimpleButtonComponent&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;withDefaultValues&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="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SimpleButtonComponent&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;withText&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
        &amp;lt;ui-simple-button
          [text]="text"
          (click)="click($event)"
        &amp;gt;&amp;lt;/ui-simple-button&amp;gt;
    `&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="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ola&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&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;Clicou&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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  Fazendo a atualização em massa
&lt;/h4&gt;

&lt;p&gt;Fazer essa alteração na mão para apenas uma história é simples, mas quando começam a ser várias e com vários níveis, isso se torna trabalhoso. Felizmente, a equipe do Storybook fez um script para atualizar isso de forma automática. Você só precisa rodar o seguinte comando:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# dentro do seu projeto&lt;/span&gt;
npx &lt;span class="nt"&gt;-p&lt;/span&gt; @storybook/cli sb migrate upgrade-hierarchy-separators &lt;span class="nt"&gt;--glob&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.stories.(ts|js)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  Perdemos o root!
&lt;/h4&gt;

&lt;p&gt;Com essa atualização nós perdemos o root/raiz das nossas histórias. O root aparecia como um texto em cima das nossas histórias. No nosso caso, era o &lt;code&gt;UI&lt;/code&gt;, e tinhamos como pasta o &lt;code&gt;Button&lt;/code&gt;. Sem o root, o &lt;code&gt;UI&lt;/code&gt; se torna uma pasta como o &lt;code&gt;Button&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Para recuperar essa aparência de root, nós precisamos adicionar o seguinte código no &lt;code&gt;.storybook/preview.js&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;.storybook/preview.js&lt;/strong&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="nf"&gt;addParameters&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; 
  &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;showRoots&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;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Migração
&lt;/h2&gt;

&lt;p&gt;Tanto a parte do antigo &lt;code&gt;config.js&lt;/code&gt; quanto os antigos separadores vão ser suportados até a versão 6.0.0 do Storybook. Felizmente, esse artigo já é suficiente para te preparar para essa versão, mas, caso queira consultar uma fonte oficial, a equipe do Storybook também preparou um &lt;a href="https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#from-version-52x-to-53x" rel="noopener noreferrer"&gt;guia de migração do 5.2 para o 5.3&lt;/a&gt; para facilitar todo esse processo.&lt;/p&gt;
&lt;h2&gt;
  
  
  Saber mais sobre
&lt;/h2&gt;

&lt;p&gt;Se quiser saber mais detalhes sobre a parte da configuração declarativa, você pode ver o artigo oficial do Storybook:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="https://medium.com/storybookjs/declarative-storybook-configuration-49912f77b78" class="ltag__link__link" rel="noopener noreferrer"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afill%3A88%3A88%2F1%2Ad5rwflocxCeaz7KOvEm3ug.jpeg" alt="Norbert de Langen"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://medium.com/storybookjs/declarative-storybook-configuration-49912f77b78" class="ltag__link__link" rel="noopener noreferrer"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Declarative Storybook configuration | by Norbert de Langen | Storybook | Medium&lt;/h2&gt;
      &lt;h3&gt;Norbert de Langen ・ &lt;time&gt;Jan 27, 2020&lt;/time&gt; ・ 
      &lt;div class="ltag__link__servicename"&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%2Fmedium-f709f79cf29704f9f4c2a83f950b2964e95007a3e311b77f686915c71574fef2.svg" alt="Medium Logo"&gt;
        Medium
      &lt;/div&gt;
    &lt;/h3&gt;
&lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Pode comparar o seu progresso com a &lt;a href="https://github.com/klauskpm/angular-storybook/tree/v2.1" rel="noopener noreferrer"&gt;tag 2.1 do repositório&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  Geração automática de documentação
&lt;/h1&gt;

&lt;p&gt;O Storybook agora da suporte ao &lt;a href="https://github.com/storybookjs/storybook/blob/next/addons/docs/docs/docspage.md" rel="noopener noreferrer"&gt;DocsPage&lt;/a&gt; para geração automática de documentação, e ao &lt;a href="https://github.com/storybookjs/storybook/blob/next/addons/docs/docs/mdx.md" rel="noopener noreferrer"&gt;MDX&lt;/a&gt; para documentações mais longas e customizadas - vamos falar dele mais tarde.&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%2Fraw.githubusercontent.com%2Fstorybookjs%2Fstorybook%2Fnext%2Faddons%2Fdocs%2Fdocs%2Fmedia%2Fangular-hero.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%2Fraw.githubusercontent.com%2Fstorybookjs%2Fstorybook%2Fnext%2Faddons%2Fdocs%2Fdocs%2Fmedia%2Fangular-hero.png" alt="Página de exemplo da documentação gerada do Storybook com Angular"&gt;&lt;/a&gt;&lt;a href="https://github.com/storybookjs/storybook/tree/next/addons/docs/angular" rel="noopener noreferrer"&gt;&lt;em&gt;Fonte&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configurando o DocsPage
&lt;/h2&gt;

&lt;p&gt;Para usar o DocsPage só preciamos instalar umas dependências, adicionar poucas configurações, e a documentação está pronta. Parece mágica, mas é melhor!&lt;/p&gt;

&lt;h3&gt;
  
  
  Instale as dependências
&lt;/h3&gt;

&lt;p&gt;Primeiro nós vamos instalar o &lt;a href="https://www.npmjs.com/package/@storybook/addon-docs" rel="noopener noreferrer"&gt;&lt;code&gt;@storybook/addon-docs&lt;/code&gt;&lt;/a&gt; (responsável pela geração das páginas) e o &lt;a href="https://www.npmjs.com/package/@compodoc/compodoc" rel="noopener noreferrer"&gt;&lt;code&gt;@compodoc/compodoc&lt;/code&gt;&lt;/a&gt; (gerador de documentação do de projetos do Angular).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# dentro do seu projeto&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @storybook/addon-docs @compodoc/compodoc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Mais tarde vou detalhar a importância do &lt;code&gt;compodoc&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Adicione os scripts de geração
&lt;/h3&gt;

&lt;p&gt;Vamos criar o script &lt;code&gt;docs:storybook&lt;/code&gt; que vai ser responsável por gerar a documentação do nosso projeto, e vamos adicionar esse script antes da execução do &lt;code&gt;storybook&lt;/code&gt; e do &lt;code&gt;build-storybook&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;package.json&lt;/strong&gt;&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&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;"scripts"&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;"docs:storybook"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"compodoc -p .storybook/tsconfig.json -e json -d ."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"storybook"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm run docs:storybook &amp;amp;&amp;amp; start-storybook -p 6006"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build-storybook"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm run docs:storybook &amp;amp;&amp;amp; build-storybook"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;O comando que configuramos vai gerar um arquivo JSON chamado &lt;code&gt;documentation.json&lt;/code&gt; e vamos passar essas informações para o &lt;code&gt;@storybook/addon-docs&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Na documentação é recomendado usar o &lt;code&gt;tsconfig.json&lt;/code&gt; do projeto principal em vez do &lt;code&gt;.storybook/tsconfig.json&lt;/code&gt;, mas como estamos usando o &lt;code&gt;compodoc&lt;/code&gt; para o &lt;code&gt;Storybook&lt;/code&gt;, na &lt;strong&gt;MINHA OPINIÃO&lt;/strong&gt; faz mais sentido usar o do &lt;code&gt;Storybook&lt;/code&gt;. Sinta-se livre para discordar e opinar!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Infelizmente, a documentação não atualiza automaticamente ao mudar o componente. Precisamos regerar o &lt;code&gt;documentation.json&lt;/code&gt; sempre que quisermos as informações mais novas. Felizmente já tem uma &lt;a href="https://github.com/storybookjs/storybook/issues/8672" rel="noopener noreferrer"&gt;issue aberta sobre isso&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  Explicando o &lt;code&gt;compodoc&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Explicando um pouco o comando que acabamos de configurar, nós passamos as seguintes opções:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-p&lt;/code&gt; ou &lt;code&gt;--tsconfig&lt;/code&gt; para definir qual tsconfig vai ser usado&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-e&lt;/code&gt; ou &lt;code&gt;--exportFormat&lt;/code&gt; para definir o formato que vai ser exportado&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-d&lt;/code&gt; ou &lt;code&gt;--output&lt;/code&gt; para definir a pasta em que vai ser exportada a documentação&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se usássemos as opções padrões do &lt;code&gt;compodoc&lt;/code&gt; e gerássemos a documentação com &lt;code&gt;compodoc -p .storybook/tsconfig.json&lt;/code&gt;, seria gerada a pasta &lt;code&gt;documentation&lt;/code&gt; com páginas HTML com uma documentação completa do projeto.&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%2Fraw.githubusercontent.com%2Fcompodoc%2Fcompodoc%2Fmaster%2Fscreenshots%2Fmain-view.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%2Fraw.githubusercontent.com%2Fcompodoc%2Fcompodoc%2Fmaster%2Fscreenshots%2Fmain-view.gif" alt="Exemplo de uma documentação gerada pelo compodoc"&gt;&lt;/a&gt;&lt;a href="https://www.npmjs.com/package/@compodoc/compodoc" rel="noopener noreferrer"&gt;&lt;em&gt;Fonte&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Configure o &lt;code&gt;@storybook/addon-docs&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Como todos os outros addons nós precisamos adicionar ele no &lt;code&gt;.storybook/main.js&lt;/code&gt; para ele ser carregado:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;.storybook/main.js&lt;/strong&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="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;addons&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/addon-docs&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Além disso, precisamos alimentar ele com o &lt;code&gt;documentation.json&lt;/code&gt; gerado pelo &lt;code&gt;compodoc&lt;/code&gt;. Vamos adicionar o seguinte no &lt;code&gt;.storybook/preview.js&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;.storybook/preview.js&lt;/strong&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;setCompodocJson&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="s2"&gt;@storybook/addon-docs/dist/frameworks/angular&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="nx"&gt;docJson&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;../documentation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;setCompodocJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;docJson&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;E por último, não podemos esquecer de adicionar a propriedade &lt;code&gt;component&lt;/code&gt; na história do nosso componente. É com ela que será identificado o componente e vinculado a tabela de propriedades geradas pelo &lt;code&gt;compodoc&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;projects/storybook-ui/src/lib/simple-button/index.stories.ts&lt;/strong&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;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;UI / Button&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;SimpleButtonComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Adicionado aqui&lt;/span&gt;
  &lt;span class="na"&gt;decorators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;moduleMetadata&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;declarations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;SimpleButtonComponent&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;
  
  
  Adicione uns enfeites (opcional)
&lt;/h3&gt;

&lt;p&gt;Apenas para ver como a tabela de propriedades é gerada pelo &lt;code&gt;compodoc&lt;/code&gt;, vamos adicionar o seguinte no &lt;code&gt;simple-button/index.stories.ts&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;projects/storybook-ui/src/lib/simple-button/simple-button.component.ts&lt;/strong&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="cm"&gt;/**
 * ViewChild que está vinculada a nada
 */&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;ViewChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;empty&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="na"&gt;static&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="nx"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TemplateRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Output fake
 */&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;clicked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EventEmitter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Input que define o texto apresentado no botão
 */&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="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;clique aqui&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Método simples e público
 * @return void
 */&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;simpleMethod&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="cm"&gt;/**
 * Método complexo e privado
 * @return string
 */&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;complexMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;num2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&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="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;E também podemos controlar o tamanho do preview das histórias da documentação adicionando uma configuração no &lt;code&gt;.storybook/preview.js&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;.storybook/preview.js&lt;/strong&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="nf"&gt;addParameters&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="p"&gt;...,&lt;/span&gt;
  &lt;span class="na"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;iframeHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&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;
  
  
  Resultado
&lt;/h3&gt;

&lt;p&gt;Agora, quando rodarmos o comando &lt;code&gt;npm run storybook&lt;/code&gt;, devemos ver o seguinte:&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fiyjtcl9so89mwvmtbeps.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fiyjtcl9so89mwvmtbeps.png" alt="Página de documentação no Storybook, exibindo a tabela de propriedades gerada pelo compodoc pro componente SimpleButton"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🎉 Storybook com documentação gerada 🎉&lt;/p&gt;
&lt;h2&gt;
  
  
  Saber mais sobre
&lt;/h2&gt;

&lt;p&gt;Se quiser saber mais detalhes sobre geração de documentação, você pode ler o &lt;a href="https://github.com/storybookjs/storybook/tree/next/addons/docs/angular" rel="noopener noreferrer"&gt;guia oficial para o Angular&lt;/a&gt;, ou o artigo oficial do Storybook:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="https://medium.com/storybookjs/storybook-docs-for-new-frameworks-b1f6090ee0ea" class="ltag__link__link" rel="noopener noreferrer"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afill%3A88%3A88%2F1%2AOLm0t9xiaKkJZC3a-fETTg.jpeg" alt="Michael Shilman"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://medium.com/storybookjs/storybook-docs-for-new-frameworks-b1f6090ee0ea" class="ltag__link__link" rel="noopener noreferrer"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Storybook Docs for new frameworks | by Michael Shilman | Storybook | Medium&lt;/h2&gt;
      &lt;h3&gt;Michael Shilman ・ &lt;time&gt;Jan 14, 2020&lt;/time&gt; ・ 
      &lt;div class="ltag__link__servicename"&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%2Fmedium-f709f79cf29704f9f4c2a83f950b2964e95007a3e311b77f686915c71574fef2.svg" alt="Medium Logo"&gt;
        Medium
      &lt;/div&gt;
    &lt;/h3&gt;
&lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Pode comparar o seu progresso com a &lt;a href="https://github.com/klauskpm/angular-storybook/tree/v2.2" rel="noopener noreferrer"&gt;tag v2.2 do repositório&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  Iniciando um Design System com MDX
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://mdxjs.com/" rel="noopener noreferrer"&gt;MDX&lt;/a&gt; é a mistura de &lt;a href="https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet" rel="noopener noreferrer"&gt;Markdown&lt;/a&gt; (MD) e &lt;a href="https://reactjs.org/docs/introducing-jsx.html" rel="noopener noreferrer"&gt;JSX&lt;/a&gt; (sintaxe do React para escrita de templates). Com o MDX, o Storybook nos da a liberdade de melhorar ou substituir as documentações geradas automaticamente, e muito mais!&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%2Fmiro.medium.com%2Fmax%2F800%2F1%2A2QMmoHLXMg_AoVcI6o_NSg.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%2Fmiro.medium.com%2Fmax%2F800%2F1%2A2QMmoHLXMg_AoVcI6o_NSg.gif" alt="Gif de introdução ao MDX, onde é mostrado uma imagem de exemplo de MDX, depois o que seria o resultado disso, e por último o logo do Storybook e do MDX lado a lado"&gt;&lt;/a&gt;&lt;a href="https://medium.com/storybookjs/rich-docs-with-storybook-mdx-61bc145ae7bc" rel="noopener noreferrer"&gt;&lt;em&gt;Fonte&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Com o MDX podemos escrever histórias apenas com MDX ou misturar as histórias em CSF (Component Story Format) com MDX. Também podemos escrever um MDX de documentação sem histórias, como design tokens e introdução ao design system. Segue abaixo o exemplo de um projeto:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://reaviz.io/?path=/story/docs-intro--page" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F3958%2F1%2AXGUPJaHY7riY2qNKtEl_3Q.png" alt="Colagem de imagens mostrando um repositório com Landing Page, Markdown, MDX, Props e DocsPage"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://reaviz.io/?path=/story/docs-intro--page" rel="noopener noreferrer"&gt;Site&lt;/a&gt; | &lt;a href="https://github.com/jask-oss/reaviz" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Como escrevemos em MDX
&lt;/h2&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%2Fmiro.medium.com%2Fmax%2F990%2F1%2ADNSAb7P_4auXdb6TjERPxw.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%2Fmiro.medium.com%2Fmax%2F990%2F1%2ADNSAb7P_4auXdb6TjERPxw.png" alt="Exemplo de sintaxe de MDX"&gt;&lt;/a&gt;&lt;a href="https://medium.com/storybookjs/rich-docs-with-storybook-mdx-61bc145ae7bc" rel="noopener noreferrer"&gt;&lt;em&gt;Fonte&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Olhando a imagem acima, podemos ver o &lt;code&gt;#Badge&lt;/code&gt; e o &lt;code&gt;Lets define...&lt;/code&gt; e isso faz parte da sintaxe do Markdown. Enquanto isso o &lt;code&gt;&amp;lt;Badge&amp;gt;&lt;/code&gt; que é um componente feito em React, e o &lt;code&gt;&amp;lt;Meta&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;Story&amp;gt;&lt;/code&gt; e &lt;code&gt;&amp;lt;Preview&amp;gt;&lt;/code&gt; que fazem parte do &lt;code&gt;addon-docs&lt;/code&gt;, usam a sintaxe do JSX. Isso quer dizer que, quando quisermos adicionar textos e formatações nós vamos usar o MD (Markdown), e quando quisermos adicionar algum layout ou funcionalidade diferente, vamos usar componentes em React com JSX. Segue abaixo o que seria o resultado do MDX apresentado anteriormente:&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%2Fmiro.medium.com%2Fmax%2F2754%2F1%2AorUEtAhfGFroSSLLzCVO6A.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%2Fmiro.medium.com%2Fmax%2F2754%2F1%2AorUEtAhfGFroSSLLzCVO6A.png"&gt;&lt;/a&gt;&lt;a href="https://medium.com/storybookjs/rich-docs-with-storybook-mdx-61bc145ae7bc" rel="noopener noreferrer"&gt;&lt;em&gt;Fonte&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O resultado dessa combinação é uma sintaxe muito mais simples. Ela é tão simples, e mais afastada da programação, que se torna fácil para que pessoas sem conhecimento da nossa linguagem de programação possam contribuir com a documentação do nosso Design System.&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%2Fmiro.medium.com%2Fmax%2F600%2F1%2ASWf7TSUuDHX9CnIXmOaNhg.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%2Fmiro.medium.com%2Fmax%2F600%2F1%2ASWf7TSUuDHX9CnIXmOaNhg.gif" alt="Gif rodando 5 imagens que demonstram o preview de um componente, a tabela de propriedades de um componente, a tipografia, a palheta de cores, e os ícones de um sistema"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://medium.com/storybookjs/rich-docs-with-storybook-mdx-61bc145ae7bc" rel="noopener noreferrer"&gt;&lt;em&gt;Fonte&lt;/em&gt;&lt;/a&gt; | &lt;a href="https://storybook-design-system.netlify.com/?path=/docs/design-system-intro--page" rel="noopener noreferrer"&gt;Site&lt;/a&gt; | &lt;a href="https://github.com/storybookjs/design-system" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | &lt;a href="https://github.com/storybookjs/storybook/tree/next/lib/components/src/blocks" rel="noopener noreferrer"&gt;Componentes de Auxílio&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Configurando o MDX
&lt;/h2&gt;

&lt;p&gt;Para fazer o MDX rodar é bem simples. Nós precisamos instalar algumas dependências e fazer nosso sistema encontrar os arquivos MDX.&lt;/p&gt;
&lt;h3&gt;
  
  
  Instale as dependências
&lt;/h3&gt;

&lt;p&gt;O MDX precisa do DocsPage e do React (JSX). Como já fizemos as instalações pro DocsPage anteiormente, vamos só fazer as instalações necessárias do React.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# dentro do seu projeto&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; react react-is babel-loader
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Altere o &lt;code&gt;main.js&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;O nosso &lt;code&gt;.storybook/main.js&lt;/code&gt; já está configurado para procurar por histórias que tenham as extensões &lt;code&gt;ts&lt;/code&gt; ou &lt;code&gt;js&lt;/code&gt;. Então só precisamos adicionar a extensão &lt;code&gt;mdx&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="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;stories&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;../src/**/*.stories.(ts|js|mdx)&lt;/span&gt;&lt;span class="dl"&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;../projects/**/*.stories.(ts|js|mdx)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;addons&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;@storybook/addon-docs&lt;/span&gt;&lt;span class="dl"&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;@storybook/addon-knobs&lt;/span&gt;&lt;span class="dl"&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;@storybook/addon-actions&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;h3&gt;
  
  
  Criando um arquivo &lt;code&gt;MDX&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Por enquanto vamos criar só um arquivo de ilustração. Só precisa copiar e colar que mais tarde vou explicar a sintaxe. Dentro de &lt;code&gt;projects/storybook-ui/src/lib/&lt;/code&gt; vamos criar o arquivo &lt;code&gt;design-system/getting-started.stories.mdx&lt;/code&gt; para introduzir as pessoas ao nosso design system:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;projects/storybook-ui/src/lib/design-system/getting-started.stories.mdx&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;import { Meta } from '@storybook/addon-docs/blocks';

&lt;span class="nt"&gt;&amp;lt;Meta&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;'Design System / Introdução'&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="gh"&gt;# Introdução&lt;/span&gt;

Olá pessoa! Seja bem vinda ao meu Design System
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Veja o resultado
&lt;/h3&gt;

&lt;p&gt;Agora, quando você rodar o comando &lt;code&gt;npm run storybook&lt;/code&gt;, você deve ver algo como o que está abaixo:&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fcbr1ke1cuaxtxqnfxuft.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fcbr1ke1cuaxtxqnfxuft.png" alt="Página gerada pelo Storybook com o texto formatado do arquivo acima"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Criando histórias com MDX
&lt;/h2&gt;

&lt;p&gt;Nós configuramos o DocsPage e o MDX, e vimos ambos em ação. Agora, nós precisamos dar o próximo passo e entender como criar histórias em MDX. Para isso, devemos saber quais ferramentas temos.&lt;/p&gt;
&lt;h3&gt;
  
  
  Blocos do &lt;code&gt;@storybook/addon-docs&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;O Storybook nos dá &lt;a href="https://github.com/storybookjs/storybook/tree/next/addons/docs/src/blocks" rel="noopener noreferrer"&gt;vários blocos&lt;/a&gt; para montarmos nossas histórias, e os 4 blocos principais são:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Meta&lt;/code&gt; para definir título, decorators e parameters (assim como o que definimos no &lt;code&gt;export default&lt;/code&gt; no CSF)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Props&lt;/code&gt; para exibir a tabela de propriedades do componente&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Story&lt;/code&gt; para criar a história do componente e exibir ela na documentação&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Preview&lt;/code&gt; para exibir a história do componente em volta de um bloco de exibição&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/storybookjs/storybook/tree/next/lib/components/src/blocks" rel="noopener noreferrer"&gt;Existem outros blocos&lt;/a&gt; além desses, como o &lt;a href="https://github.com/storybookjs/storybook/blob/next/lib/components/src/blocks/ColorPalette.stories.tsx" rel="noopener noreferrer"&gt;&lt;code&gt;ColorPalette&lt;/code&gt; para design tokens&lt;/a&gt;, mas esses 4 são os principais e devem aparecer em todas as histórias que fizermos com MDX. Além disso, também podemos criar os nossos próprios blocos usando o React.&lt;/p&gt;
&lt;h3&gt;
  
  
  Estilos de escrita com MDX
&lt;/h3&gt;

&lt;p&gt;Diferente do React e do Vue, no Storybook o Angular não tem a habilidade de escrever histórias inline. Felizmente, temos outras abordagens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/storybookjs/storybook/tree/next/addons/docs/angular#mdx" rel="noopener noreferrer"&gt;histórias puras em MDX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/storybookjs/storybook/blob/next/addons/docs/docs/recipes.md#csf-stories-with-mdx-docs" rel="noopener noreferrer"&gt;histórias em CSF com documentação em MDX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/storybookjs/storybook/blob/next/addons/docs/docs/recipes.md#csf-stories-with-arbitrary-mdx" rel="noopener noreferrer"&gt;histórias em CSF definindo o MDX arbitrariamente&lt;/a&gt; (MDX não podendo definir histórias, só referênciando).&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Não irei abordar o último estilo de escrita com MDX (histórias em CSF definindo o MDX arbitrariamente), pois eu não consegui fazer ele funcionar. Continuarei buscando soluções e atualizarei esse artigo caso consiga.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;
  
  
  Histórias puras em MDX
&lt;/h4&gt;

&lt;p&gt;Essa abordagem é ótima para documentações, como o &lt;code&gt;getting-started.stories.mdx&lt;/code&gt;, e também para componentes simples. Como eles não precisam de muita configuração, e no máximo tem alguns inputs e outputs simples, não precisamos de um arquivo de lógica. Segue abaixo um exemplo:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;index.stories.mdx&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;import { Meta, Story, Props, Preview } from '@storybook/addon-docs/blocks';
import { moduleMetadata, addDecorator } from '@storybook/angular';
import { SimpleButtonComponent } from '../simple-button.component';

&amp;lt;Meta
  title='UI / Button'
  component={SimpleButtonComponent}
  decorators={[moduleMetadata({ declarations: [SimpleButtonComponent] })]}
/&amp;gt;

&lt;span class="gh"&gt;# SimpleButton Component&lt;/span&gt;

Uma descrição simples em &lt;span class="gs"&gt;**markdown**&lt;/span&gt;.
Exibindo o &lt;span class="sb"&gt;`SimpleButtonComponent`&lt;/span&gt; usando o &lt;span class="sb"&gt;`Story`&lt;/span&gt;.

&lt;span class="nt"&gt;&amp;lt;Story&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;'basic'&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;'60px'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{
  component: SimpleButtonComponent,
  props: {},
}}&lt;span class="nt"&gt;&amp;lt;/Story&amp;gt;&lt;/span&gt;

&lt;span class="gu"&gt;## Props&lt;/span&gt;

A tabela de propriedades é exibida com usando o &lt;span class="sb"&gt;`Props`&lt;/span&gt;.

&lt;span class="nt"&gt;&amp;lt;Props&lt;/span&gt; &lt;span class="na"&gt;of=&lt;/span&gt;&lt;span class="s"&gt;{SimpleButtonComponent}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="sb"&gt;


&lt;/span&gt;&lt;span class="gu"&gt;## Stories&lt;/span&gt;

Fazendo preview da história com &lt;span class="sb"&gt;`&amp;lt;Preview&amp;gt;`&lt;/span&gt;.

&lt;span class="nt"&gt;&amp;lt;Preview&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Story&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Basic Preview"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{
    component: SimpleButtonComponent,
    props: {},
  }}&lt;span class="nt"&gt;&amp;lt;/Story&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Preview&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  Histórias em CSF com documentação em MDX
&lt;/h4&gt;

&lt;p&gt;As vezes nós temos componentes mais complexos, ou com dados mais longos, e queremos deixar a parte da documentação mais simples possível. Para esses casos nós vamos ter dois arquivos, um CSF (&lt;code&gt;.ts&lt;/code&gt; ou &lt;code&gt;.js&lt;/code&gt;) e um MDX (&lt;code&gt;.mdx&lt;/code&gt;). No CSF vamos deixar as histórias e lógicas, e no MDX vamos deixar a documentação e aplicaremos as histórias nos devidos lugares. Segue abaixo um exemplo:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;stories.ts&lt;/strong&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;action&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/addon-actions&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;text&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/addon-knobs&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;SimpleButtonComponent&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;../simple-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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;withDefaultValues&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="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SimpleButtonComponent&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;withText&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
        &amp;lt;ui-simple-button
          [text]="text"
          (click)="click($event)"
        &amp;gt;&amp;lt;/ui-simple-button&amp;gt;
    `&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="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ola&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&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;Clicou&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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;index.stories.mdx&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;import { Meta, Story, Props, Preview } from '@storybook/addon-docs/blocks';
import { moduleMetadata, addDecorator } from '@storybook/angular';
import { SimpleButtonComponent } from '../simple-button.component';
import &lt;span class="err"&gt;*&lt;/span&gt; as stories from './stories.ts';

&amp;lt;Meta
  title='UI / Button'
  component={SimpleButtonComponent}
  decorators={[moduleMetadata({ declarations: [SimpleButtonComponent] })]}
/&amp;gt;

&lt;span class="gh"&gt;# SimpleButton Component&lt;/span&gt;

Uma descrição simples em &lt;span class="gs"&gt;**markdown**&lt;/span&gt;.
Exibindo o &lt;span class="sb"&gt;`SimpleButtonComponent`&lt;/span&gt; usando o &lt;span class="sb"&gt;`CSF`&lt;/span&gt; + &lt;span class="sb"&gt;`MDX`&lt;/span&gt;.

&lt;span class="nt"&gt;&amp;lt;Story&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;'basic'&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;'60px'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{stories.withDefaultValues()}&lt;span class="nt"&gt;&amp;lt;/Story&amp;gt;&lt;/span&gt;

&lt;span class="gu"&gt;## Props&lt;/span&gt;

A tabela de propriedades é exibida com usando o &lt;span class="sb"&gt;`Props`&lt;/span&gt;.

&lt;span class="nt"&gt;&amp;lt;Props&lt;/span&gt; &lt;span class="na"&gt;of=&lt;/span&gt;&lt;span class="s"&gt;{SimpleButtonComponent}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="sb"&gt;


&lt;/span&gt;&lt;span class="gu"&gt;## Stories&lt;/span&gt;

Usando histórias criadas em CSF no MDX

&lt;span class="nt"&gt;&amp;lt;Preview&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Story&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"With Text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{stories.withText()}&lt;span class="nt"&gt;&amp;lt;/Story&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Preview&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Vamos atualizar nossa história
&lt;/h3&gt;

&lt;p&gt;Vendo as estratégias acima, podemos afirmar que nosso componente só precisa de um arquivo MDX porque ele é bem simples, mas, apenas por questão de demonstração, vamos usar os dois estilos ao mesmo tempo. Vamos pegar o nosso &lt;code&gt;simple-button/index.stories.ts&lt;/code&gt; e começar a criar nossa nova documentação dele. Vamos seguir os seguintes passos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Crie a pasta &lt;code&gt;stories&lt;/code&gt; dentro de &lt;code&gt;projects/storybook-ui/src/lib/simple-button&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Renomei o &lt;code&gt;index.stories.ts&lt;/code&gt; para &lt;code&gt;stories.ts&lt;/code&gt; e mova ele para dentro de &lt;code&gt;stories&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Crie o arquivo &lt;code&gt;index.stories.mdx&lt;/code&gt; dentro &lt;code&gt;stories&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nós renomeamos o arquivo para não haver um possível problema de carregamento das histórias, e movemos os dois arquivos para uma outra pasta apenas por questão de organização.&lt;/p&gt;

&lt;p&gt;Agora, vamos aplicar as mudanças no conteúdo dos arquivos:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;stories.ts&lt;/strong&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;action&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/addon-actions&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;text&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/addon-knobs&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;SimpleButtonComponent&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;../simple-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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;withDefaultValues&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="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SimpleButtonComponent&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;withText&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
        &amp;lt;ui-simple-button
          [text]="text"
          (click)="click($event)"
        &amp;gt;&amp;lt;/ui-simple-button&amp;gt;
    `&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="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ola&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&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;Clicou&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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;index.stories.mdx&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;import { Meta, Story, Props, Preview } from '@storybook/addon-docs/blocks';
import { moduleMetadata, addDecorator } from '@storybook/angular';
import { SimpleButtonComponent } from '../simple-button.component';
import &lt;span class="err"&gt;*&lt;/span&gt; as stories from './stories.ts';

&amp;lt;Meta
  title='UI / SimpleButton'
  component={SimpleButtonComponent}
  decorators={[moduleMetadata({ declarations: [SimpleButtonComponent] })]}
/&amp;gt;

&lt;span class="gh"&gt;# SimpleButton Component&lt;/span&gt;

Uma descrição simples em &lt;span class="gs"&gt;**markdown**&lt;/span&gt;.
Exibindo o &lt;span class="sb"&gt;`SimpleButtonComponent`&lt;/span&gt; usando o &lt;span class="sb"&gt;`Story`&lt;/span&gt;.

&lt;span class="nt"&gt;&amp;lt;Story&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;'simples'&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;'60px'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{
  component: SimpleButtonComponent,
  props: {},
}}&lt;span class="nt"&gt;&amp;lt;/Story&amp;gt;&lt;/span&gt;

&lt;span class="gu"&gt;## Props&lt;/span&gt;

A tabela de propriedades é exibida com usando o &lt;span class="sb"&gt;`Props`&lt;/span&gt;.

&lt;span class="nt"&gt;&amp;lt;Props&lt;/span&gt; &lt;span class="na"&gt;of=&lt;/span&gt;&lt;span class="s"&gt;{SimpleButtonComponent}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="sb"&gt;


&lt;/span&gt;&lt;span class="gu"&gt;## Stories&lt;/span&gt;

Usando histórias criadas em CSF no MDX

&lt;span class="nt"&gt;&amp;lt;Preview&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Story&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"com valores default"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{stories.withDefaultValues()}&lt;span class="nt"&gt;&amp;lt;/Story&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Preview&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;Preview&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Story&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"com texto diferente"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{stories.withText()}&lt;span class="nt"&gt;&amp;lt;/Story&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Preview&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;O resultado resultado é esse:&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fnvvunbj2x0qob57a61db.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fnvvunbj2x0qob57a61db.png" alt="Imagem da documentação gerada a partir do index.stories.mdx. Exibindo o título, a história simples e a tabela de propriedades na parte principal, e na parte lateral os links das histórias: simples, com valores default e com texto diferente"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Saber mais sobre
&lt;/h2&gt;

&lt;p&gt;Se quiser saber mais detalhes sobre documentação rica com MDX, você pode ler o artigo oficial do Storybook:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="https://medium.com/storybookjs/rich-docs-with-storybook-mdx-61bc145ae7bc" class="ltag__link__link" rel="noopener noreferrer"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afill%3A88%3A88%2F1%2AOLm0t9xiaKkJZC3a-fETTg.jpeg" alt="Michael Shilman"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://medium.com/storybookjs/rich-docs-with-storybook-mdx-61bc145ae7bc" class="ltag__link__link" rel="noopener noreferrer"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Rich docs with Storybook MDX. Components &amp;amp; documentation in harmony… | by Michael Shilman | Storybook | Medium&lt;/h2&gt;
      &lt;h3&gt;Michael Shilman ・ &lt;time&gt;Jan 14, 2020&lt;/time&gt; ・ 
      &lt;div class="ltag__link__servicename"&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%2Fmedium-f709f79cf29704f9f4c2a83f950b2964e95007a3e311b77f686915c71574fef2.svg" alt="Medium Logo"&gt;
        Medium
      &lt;/div&gt;
    &lt;/h3&gt;
&lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;p&gt;Além disso, também tem esses links super importantes com documentações e exemplos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/storybookjs/storybook/tree/next/addons/docs/angular#mdx" rel="noopener noreferrer"&gt;Documentação do MDX com Angular&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/storybookjs/storybook/blob/next/addons/docs/docs/mdx.md" rel="noopener noreferrer"&gt;Documentação geral do MDX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/storybookjs/storybook/blob/next/addons/docs/docs/recipes.md" rel="noopener noreferrer"&gt;Receitas para criações de histórias&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/storybookjs/storybook/tree/next/addons/docs/src/blocks" rel="noopener noreferrer"&gt;Lista de blocos em JSX disponíveis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/storybookjs/storybook/tree/next/lib/components/src/blocks" rel="noopener noreferrer"&gt;Lista complementar de blocos em JSX&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Antes de ir para a próxima sessão, se você já tem várias histórias criadas no Storybook no estilo do &lt;code&gt;storiesOf&lt;/code&gt; ou &lt;code&gt;CSF&lt;/code&gt; e quer mudar todas, ou algumas, para outro estilo, você pode dar uma olhada no &lt;a href="https://github.com/storybookjs/storybook/blob/next/lib/codemod/README.md" rel="noopener noreferrer"&gt;&lt;code&gt;codemod&lt;/code&gt;&lt;/a&gt;. Ele tem scripts para mudar, em massa, as histórias de estilo e isso pode te poupar muito tempo.&lt;/p&gt;

&lt;p&gt;Pode comparar o seu progresso com a &lt;a href="https://github.com/klauskpm/angular-storybook/tree/v2.3" rel="noopener noreferrer"&gt;tag v2.3 do repositório&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  Storybook focado em Design
&lt;/h1&gt;

&lt;p&gt;Quando lidamos com qualquer organização de um projeto, a parte mais difícil é a comunicação. Seja a falta ou o mau uso dela. Para resolver esse problema, em relação aos aspectos de Design de um sistema, existe o &lt;a href="https://brasil.uxdesign.cc/entendendo-design-system-f375bbb6f704" rel="noopener noreferrer"&gt;Design System&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Apesar de o Design System ser uma ótima solução, cada equipe tem um conjunto de ferramentas e elas vivem em seus universos isolados. Isso torna o trabalho de manter um Design System algo, um tanto que, trabalhoso.&lt;/p&gt;

&lt;p&gt;Por esse motivo, eu fico muito feliz quando vejo o time do Storybook exibindo tantas integrações com essas essas ferramentas.&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%2Fmiro.medium.com%2Fmax%2F1944%2F1%2AzIZPDT1f9tL0hrLi5mTm6g.jpeg" 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%2Fmiro.medium.com%2Fmax%2F1944%2F1%2AzIZPDT1f9tL0hrLi5mTm6g.jpeg" alt="Imagem mostrando, no lado esquerdo as integrações com ferramentas de Design: Sketch, Figma, Zeplin, Abstract, Invision e Adobe XD, com o Storybook, no lado direito, e o React, Vue e Angular"&gt;&lt;/a&gt;&lt;a href="https://medium.com/storybookjs/storybook-for-design-3ff761c579bf" rel="noopener noreferrer"&gt;&lt;em&gt;Fonte&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.figma.com/resources/extensions-and-apis/storybook-figma-addon/" rel="noopener noreferrer"&gt;Figma addon&lt;/a&gt;&lt;br&gt;
As mudanças de Design vão aparecer automaticamente no Storybook&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/amccloud/storybook-addons-abstract" rel="noopener noreferrer"&gt;Abstract addon&lt;/a&gt; (para Sketch e Adobe XD)&lt;br&gt;
Abre um painel nas histórias do Storybook, onde você vê os layers e containers do Abstract&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.invisionapp.com/design-system-manager/learn/setting-up-storybook-in-dsm/" rel="noopener noreferrer"&gt;InVision Design System Manager&lt;/a&gt;&lt;br&gt;
O DSM permite ver os componentes do Storybook, no app do DSM, junto dos designs extraídos do Sketch&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://blog.zeplin.io/introducing-connected-components-components-in-design-and-code-in-harmony-aa894ed5bd95" rel="noopener noreferrer"&gt;Zeplin&lt;/a&gt;&lt;br&gt;
Linka e mostra uma minidocumentação dos componentes do Storybook direto com o app do Zeplin&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://zeroheight.com/landing" rel="noopener noreferrer"&gt;Zeroheight&lt;/a&gt;&lt;br&gt;
O addon leva os componentes do Storybook para serem exibidos junto com os designs de outras ferramentas, como Sketch, Figma, ou Adobe XD&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/chrisvxd/story2sketch/" rel="noopener noreferrer"&gt;Story2sketch for Sketch&lt;/a&gt;&lt;br&gt;
Converte histórias do Storybook em símbolos do Sketch&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/UX-and-I/storybook-design-token" rel="noopener noreferrer"&gt;Design Token&lt;/a&gt;&lt;br&gt;
Transforma e exibe design tokens identificados em um painel no Storybook&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2Fmiro.medium.com%2Fmax%2F1042%2F1%2ARnyPVhVKrNGT6sfXq2-mCg.jpeg" 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%2Fmiro.medium.com%2Fmax%2F1042%2F1%2ARnyPVhVKrNGT6sfXq2-mCg.jpeg"&gt;&lt;/a&gt;&lt;a href="https://medium.com/storybookjs/storybook-for-design-3ff761c579bf" rel="noopener noreferrer"&gt;&lt;em&gt;Fonte&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;São integrações para a equipe de Design ver os nossos componentes e usar eles nos próximos designs, ou para nós vermos os designs deles e compararmos cores, tamanhos e fontes. O objetivo é todos terem uma única fonte de verdade sobre os elementos de design e facilitar a manutenção e evolução do Design System&lt;/p&gt;

&lt;h2&gt;
  
  
  Saber mais sobre
&lt;/h2&gt;

&lt;p&gt;Se quiser saber mais detalhes sobre Storybook para Design, você pode ler o artigo oficial do Storybook:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="https://medium.com/storybookjs/storybook-for-design-3ff761c579bf" class="ltag__link__link" rel="noopener noreferrer"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afill%3A88%3A88%2F1%2AvqFNU0cFQkAeVqSJd56Xvw.jpeg" alt="Dominic Nguyen"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://medium.com/storybookjs/storybook-for-design-3ff761c579bf" class="ltag__link__link" rel="noopener noreferrer"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Storybook for design. How to integrate your favorite design… | by Dominic Nguyen | Storybook | Medium&lt;/h2&gt;
      &lt;h3&gt;Dominic Nguyen ・ &lt;time&gt;Sep 24, 2020&lt;/time&gt; ・ 
      &lt;div class="ltag__link__servicename"&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%2Fmedium-f709f79cf29704f9f4c2a83f950b2964e95007a3e311b77f686915c71574fef2.svg" alt="Medium Logo"&gt;
        Medium
      &lt;/div&gt;
    &lt;/h3&gt;
&lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;





&lt;h1&gt;
  
  
  Conclusão
&lt;/h1&gt;

&lt;p&gt;Além de facilitar a utilização e configuração, também adicionaram vários modos de criação de documentação (DocsPage e MDX) e várias integrações com as ferramentas de Design. O Storybook tem evoluído muito, e &lt;a href="https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md#600-alpha0-january-21-2020" rel="noopener noreferrer"&gt;vai continuar evoluindo&lt;/a&gt;, para se tornar a ferramenta para criações de Design System.&lt;/p&gt;

&lt;p&gt;Eu aprendi muito enquanto fazia esse artigo e espero que ele ajude você também.&lt;/p&gt;

&lt;p&gt;Um forte abraço e até a próxima! 😬&lt;/p&gt;




&lt;h1&gt;
  
  
  Fontes
&lt;/h1&gt;

&lt;p&gt;A base desse artigo foram os 4 artigos sobre o lançamento da nova versão do Storybook. Segue abaixo os links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/storybookjs/declarative-storybook-configuration-49912f77b78" rel="noopener noreferrer"&gt;Declarative Storybook configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/storybookjs/storybook-docs-for-new-frameworks-b1f6090ee0ea" rel="noopener noreferrer"&gt;Storybook Docs for new frameworks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/storybookjs/rich-docs-with-storybook-mdx-61bc145ae7bc" rel="noopener noreferrer"&gt;Rich docs with Storybook MDX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/storybookjs/storybook-for-design-3ff761c579bf" rel="noopener noreferrer"&gt;Storybook for Design&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Além desse artigos, também tiveram esses outros links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md#530-january-11-2020" rel="noopener noreferrer"&gt;CHANGELOG da versão 5.3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/storybookjs/storybook/tree/next/addons/docs/angular" rel="noopener noreferrer"&gt;Documentação sobre como usar o Storybook Docs/DocsPage no Angular&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/storybookjs/storybook/tree/next/examples/angular-cli/src/stories" rel="noopener noreferrer"&gt;Exemplos de histórias com Angular&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>angular</category>
      <category>storybook</category>
      <category>design</category>
    </item>
    <item>
      <title>Como gerar CHANGELOG automaticamente</title>
      <dc:creator>Klaus Kazlauskas</dc:creator>
      <pubDate>Fri, 17 Jan 2020 12:10:40 +0000</pubDate>
      <link>https://dev.to/klauskpm/como-gerar-changelog-automaticamente-56ie</link>
      <guid>https://dev.to/klauskpm/como-gerar-changelog-automaticamente-56ie</guid>
      <description>&lt;p&gt;Oie! Se você já usou bibliotecas, ou viu repositórios open-source, você já deve ter visto um arquivo chamado &lt;code&gt;CHANGELOG.md&lt;/code&gt;. Até dá pra fazer ele manualmente, mas...&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%2Fi.imgflip.com%2F3lukls.jpg" 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%2Fi.imgflip.com%2F3lukls.jpg" alt="Meme do fantoche Pedro falando "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Você luta contra muitos fatores e perde muito tempo. Além disso, é muito simples fazer de forma automática. Só precisamos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Definir um padrão para os nossos commits&lt;/li&gt;
&lt;li&gt;Usar pacotes para auxiliar nesses padrões&lt;/li&gt;
&lt;li&gt;Usar um pacote para gerar o CHANGELOG&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Então, vamos começar a gerar nosso CHANGELOG.&lt;/p&gt;




&lt;h1&gt;
  
  
  Preparação
&lt;/h1&gt;

&lt;p&gt;Na época que esse guia foi preparado, foram usadas as seguintes tecnologias:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;tecnologia&lt;/th&gt;
&lt;th&gt;versão&lt;/th&gt;
&lt;th&gt;instalação&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;td&gt;11.6.0&lt;/td&gt;
&lt;td&gt;&lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;como instalar&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NPM&lt;/td&gt;
&lt;td&gt;6.13.4&lt;/td&gt;
&lt;td&gt;Já vem com o Node.js&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Todo o código desse projeto está no GitHub, então, caso você se perca em qualquer parte, pode fazer uma comparação direta. Além disso, todos os passos desse artigo estão lá de forma resumida:&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/klauskpm" rel="noopener noreferrer"&gt;
        klauskpm
      &lt;/a&gt; / &lt;a href="https://github.com/klauskpm/changelog-cicd" rel="noopener noreferrer"&gt;
        changelog-cicd
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Repositório para ensinar a criar CHANGELOG automaticamente
    &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;changelog-cicd&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/klauskpm/changelog-cicd/workflows/Gerador%20de%20CHANGELOG/badge.svg"&gt;&lt;img src="https://github.com/klauskpm/changelog-cicd/workflows/Gerador%20de%20CHANGELOG/badge.svg" alt="Status Badge do Gerador de CHANGELOG"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Repositório com passo-a-passo de como gerar um CHANGELOG automaticamente.&lt;/p&gt;
&lt;p&gt;Esse passo-a-passo é a versão muito resumida do artigo: &lt;a href="https://github.com/klauskpm/changelog-cicd" rel="noopener noreferrer"&gt;Como gerar CHANGELOG automaticamente&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Gerando um CHANGELOG automaticamente&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;1) Instale as dependências&lt;/h3&gt;
&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm install --global commitizen

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; dentro do seu projeto&lt;/span&gt;
npm install --save-dev husky @commitlint/cli @commitlint/config-conventional standard-version&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;2) Configure o commitizen&lt;/h3&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; dentro do seu projeto&lt;/span&gt;
commitizen init cz-conventional-changelog --save-dev --save-exact&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;3) Crie o arquivo &lt;code&gt;commitlint.config.js&lt;/code&gt;
&lt;/h3&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-js notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-smi"&gt;module&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;exports&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;extends&lt;/span&gt;: &lt;span class="pl-kos"&gt;[&lt;/span&gt;&lt;span class="pl-s"&gt;'@commitlint/config-conventional'&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;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;4) Altere o seu &lt;code&gt;package.json&lt;/code&gt;
&lt;/h3&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-json notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;{
  &lt;span class="pl-ii"&gt;...,&lt;/span&gt;
  &lt;span class="pl-ii"&gt;// opcional&lt;/span&gt;
  &lt;span class="pl-ent"&gt;"repository"&lt;/span&gt;: {
    &lt;span class="pl-ent"&gt;"url"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;git@gitlab.com:meu-usuario/meu-repo.git&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
  },
  &lt;span class="pl-ii"&gt;...,&lt;/span&gt;
  &lt;span class="pl-ent"&gt;"husky"&lt;/span&gt;: {
    &lt;span class="pl-ent"&gt;"hooks"&lt;/span&gt;: {
      &lt;span class="pl-ent"&gt;"commit-msg"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;commitlint -E HUSKY_GIT_PARAMS&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
    }
  },
  &lt;span class="pl-ent"&gt;"scripts"&lt;/span&gt;: {
    &lt;span class="pl-ent"&gt;"release"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;standard-version&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
  }
}&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;5) Crie o arquivo &lt;code&gt;.versionrc&lt;/code&gt;
&lt;/h3&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-json notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;{
  &lt;span class="pl-ent"&gt;"types"&lt;/span&gt;: [
    {&lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;feat&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"section"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Funcionalidades&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;}
    {&lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;fix&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/klauskpm/changelog-cicd" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;





&lt;h1&gt;
  
  
  Padronizando as mensagens de commit
&lt;/h1&gt;

&lt;p&gt;O padrão que vamos seguir para as mensagens é o &lt;a href="https://www.conventionalcommits.org/en/v1.0.0-beta.2/" rel="noopener noreferrer"&gt;conventional commit specification&lt;/a&gt;(especificação convencional de commit). Esse padrão é escrito da seguinte forma:&lt;/p&gt;

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

&amp;lt;tipo&amp;gt;[(escopo opcional)]: &amp;lt;descrição&amp;gt;

[corpo opcional]

[rodapé opcional]


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

&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;campo&lt;/th&gt;
&lt;th&gt;obrigatório&lt;/th&gt;
&lt;th&gt;descrição&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;tipo&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Tipo do commit que vai ser feito. Verificar lista de tipos permitidos.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;escopo&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Arquivo, domínio, ou módulo que aquele commit se refere&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;descrição&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Uma descrição curta sobre o commit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;corpo&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Uma descrição maior, caso não consiga explicar com clareza tudo o que tem no commit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rodapé&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Fechamento de tarefas e/ou informação sobre breaking changes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Lista de tipos permitidos
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;feat:&lt;/strong&gt; Uma funcionalidade&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;fix:&lt;/strong&gt; Um ajuste de erro/bug&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;docs:&lt;/strong&gt; Modificação na documentação&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;style:&lt;/strong&gt; Mudança de estilo (ponto, vírgula, indentação)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;refactor:&lt;/strong&gt; Mudança de código que não adiciona funcionalidade ou arruma um erro&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;perf:&lt;/strong&gt; Mudança que altera performance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;test:&lt;/strong&gt; Novos testes ou correção de antigos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;build:&lt;/strong&gt; Mudanças que afetam o build ou dependências exeternas (gulp, npm)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ci:&lt;/strong&gt; Mudanças na configuração da Integração Contínua (Travis, Circle)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;chore:&lt;/strong&gt; Outras mudanças que não são nos arquivos de src ou test&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;revert:&lt;/strong&gt; Reversão de um commit&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Exemplos de commit
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

feat(cadastro): adiciona integração com Gugou Sign-in


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

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

fix(pagamento): muda a chave do RecebaSeguro

A chave que estava sendo usada era de desenvolvimento,
mas acabou sendo enviada para produção

Fecha a tarefa #457


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

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

refactor(produto): remove o método #adicionarAoCarrinho

O método já tinha sido depreciado e agora foi removido

BREAKING CHANGE: o método públic #adicionarAoCarrinho foi removido


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

&lt;/div&gt;

&lt;h1&gt;
  
  
  Facilitando a padronização
&lt;/h1&gt;

&lt;p&gt;Apesar da padronização facilitar a automatização, ela pode ser muita coisa pra gravar de primeira. Então, para facilitar a aplicação desse padrão, nós vamos usar o Commitizen e o Commitlint.&lt;/p&gt;
&lt;h2&gt;
  
  
  Commitlint
&lt;/h2&gt;

&lt;p&gt;O &lt;code&gt;commitlint&lt;/code&gt; vai verificar se nossos commits estão seguindo o Conventional Commit Specification. Ele vai fazer isso com a ajuda do &lt;code&gt;husky&lt;/code&gt;, que irá disparar o &lt;code&gt;commitlint&lt;/code&gt; toda vez que for feito um commit.&lt;/p&gt;
&lt;h3&gt;
  
  
  1) Instale as dependências
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="c"&gt;# dentro do seu projeto&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; husky @commitlint/cli @commitlint/config-conventional


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  2) Crie o commitlint.config.js
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extends&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;@commitlint/config-conventional&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;h3&gt;
  
  
  3) Configure o &lt;code&gt;husky&lt;/code&gt; no package.json
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"husky"&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;"hooks"&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;"commit-msg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"commitlint -E HUSKY_GIT_PARAMS"&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="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  4) Teste para ver se está funcionando (opcional)
&lt;/h3&gt;

&lt;p&gt;A configuração está pronta e já deve estar funcionando. Se quiser, pode fazer uma adição no seu projeto e commitar como &lt;code&gt;teste para quebrar&lt;/code&gt;. Você deve receber um erro explicando o que está faltando no commit.&lt;/p&gt;
&lt;h2&gt;
  
  
  Commitizen
&lt;/h2&gt;

&lt;p&gt;Agora que temos algo para verificar nossos commits, precisamos fazer eles de uma maneira mais fácil. Com o &lt;code&gt;commitizen&lt;/code&gt;, nós vamos commitar usando o comando &lt;code&gt;git cz&lt;/code&gt;, que vai fazer perguntas passo-a-passo até ter o commit final.&lt;/p&gt;
&lt;h3&gt;
  
  
  1) Instale e configure o &lt;code&gt;commitizen&lt;/code&gt;
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--global&lt;/span&gt; commitizen

&lt;span class="c"&gt;# dentro do seu projeto&lt;/span&gt;
commitizen init cz-conventional-changelog &lt;span class="nt"&gt;--save-dev&lt;/span&gt; &lt;span class="nt"&gt;--save-exact&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  2) Teste para ver se está funcionando
&lt;/h3&gt;

&lt;p&gt;Faça uma pequena alteração, adicione ela com &lt;code&gt;git add .&lt;/code&gt; e faça um &lt;code&gt;git cz&lt;/code&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%2Fgithub.com%2Fcommitizen%2Fcz-cli%2Fraw%2Fmaster%2Fmeta%2Fscreenshots%2Fadd-commit.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%2Fgithub.com%2Fcommitizen%2Fcz-cli%2Fraw%2Fmaster%2Fmeta%2Fscreenshots%2Fadd-commit.png" alt="Terminal listando os tipos de commit que podem ser escolhidos, após ter executado o commitizen"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h1&gt;
  
  
  Automatizando o CHANGELOG
&lt;/h1&gt;

&lt;p&gt;Agora que nós temos os commits seguindo um padrão, podemos gerar o nosso arquivo CHANGELOG. Os dois pacotes mais utilizados para fazer essa tarefa hoje, são o &lt;a href="https://www.npmjs.com/package/semantic-release" rel="noopener noreferrer"&gt;&lt;code&gt;semantic-release&lt;/code&gt;&lt;/a&gt; e o &lt;a href="https://www.npmjs.com/package/standard-version" rel="noopener noreferrer"&gt;&lt;code&gt;standard-version&lt;/code&gt;&lt;/a&gt;. Vamos seguir com o &lt;code&gt;standard-version&lt;/code&gt; pela facilidade do uso.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;standard-version&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Esse pacote vai ser responsável por analisar nossos commits, gerar uma nova versão pro projeto e gerar o CHANGELOG.&lt;/p&gt;
&lt;h3&gt;
  
  
  1) Instale o &lt;code&gt;standard-version&lt;/code&gt;
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; standard-version


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  2) Altere seu &lt;code&gt;package.json&lt;/code&gt;
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&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;"scripts"&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;"release"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"standard-version"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  3) Faça seu primeiro release
&lt;/h3&gt;

&lt;p&gt;Agora que tudo está configurado, commite essas alterações e execute o seguinte comando:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npm run release &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--first-release&lt;/span&gt;


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

&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;O &lt;code&gt;npm run release&lt;/code&gt; executa as seguintes etapas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Modifica a versão do seu &lt;code&gt;package.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Usa o &lt;a href="https://github.com/conventional-changelog/conventional-changelog" rel="noopener noreferrer"&gt;&lt;code&gt;conventional-changelog&lt;/code&gt;&lt;/a&gt; para criar/atualizar o &lt;code&gt;CHANGELOG.md&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Commita o &lt;code&gt;package.json&lt;/code&gt; e o &lt;code&gt;CHANGELOG.md&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Gera uma nova tag&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A diferença dele para o &lt;code&gt;--first-release&lt;/code&gt;, é que o &lt;code&gt;--first-release&lt;/code&gt; ignora o passo &lt;strong&gt;1&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;
  
  
  🎉 CHANGELOG gerado 🎉
&lt;/h4&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F9n1esq47jyuzuo7zfxsp.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F9n1esq47jyuzuo7zfxsp.png" alt="CHANGELOG.md da versão v1.0.0 do projeto, gerado pelo comando npm run release -- --first-release"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pode comparar o seu progresso com a &lt;a href="https://github.com/klauskpm/changelog-cicd/tree/v1.0.0" rel="noopener noreferrer"&gt;tag v1.0.0 do repositório&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Explorando o CHANGELOG
&lt;/h2&gt;

&lt;p&gt;Agora que temos tudo, vamos entender como o CHANGELOG é gerado e o que podemos fazer com ele.&lt;/p&gt;

&lt;p&gt;Se você for no &lt;a href="https://github.com/klauskpm/changelog-cicd/blob/v2.1.0/CHANGELOG.md" rel="noopener noreferrer"&gt;repositório na v2.1.0&lt;/a&gt;, você verá que foram criados vários commits e versões. Olhando essas versões criadas, podemos observar que:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uma feat representa um minor (X.1.X) do &lt;a href="https://semver.org/" rel="noopener noreferrer"&gt;SemVer&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;Um fix representa um patch (X.X.1) do &lt;a href="https://semver.org/" rel="noopener noreferrer"&gt;SemVer&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;Uma BREAKING CHANGE representa um major (1.X.X) do &lt;a href="https://semver.org/" rel="noopener noreferrer"&gt;SemVer&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;Só aumenta um número por vez. 3 feats aumentam o mesmo que 1;&lt;/li&gt;
&lt;li&gt;O maior número é que manda. Se tem feat, não importa o fix;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Só aparecem os commits com feat e fix&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;Todos os links estão apontando para o repositório do &lt;strong&gt;GitHub&lt;/strong&gt;;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Tirando os dois últimos pontos, o resto são regras do próprio &lt;a href="https://semver.org/" rel="noopener noreferrer"&gt;SemVer&lt;/a&gt; (Semantic Versioning), que é quem dita as regras do versionamento (major.minor.patch).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Esses dois últimos pontos ganharam destaque porque eles são muito interessantes. Fazendo uma reflexão, parece que você teria que fazer uma solução própria caso quisesse exibir commits de outros tipos ou se quisesse usar o GitLab. Felizmente, o &lt;code&gt;standard-version&lt;/code&gt; tem uma solução bem prática pra isso. Você só precisa passar um arquivo de configuração.&lt;/p&gt;
&lt;h3&gt;
  
  
  Configurando a geração do CHANGELOG
&lt;/h3&gt;

&lt;p&gt;Podemos passar a configuração pro &lt;code&gt;standard-version&lt;/code&gt; de &lt;a href="https://www.npmjs.com/package/standard-version#configuration" rel="noopener noreferrer"&gt;diversas formas&lt;/a&gt;, mas vamos focar no &lt;code&gt;.versionrc&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Esse arquivo segue a &lt;a href="https://github.com/conventional-changelog/conventional-changelog-config-spec/blob/master/versions/2.1.0/README.md" rel="noopener noreferrer"&gt;especificação de configuração do conventional changelog&lt;/a&gt;. Então, se quiser exibir um outro tipo de commit, botar em português, e usar o GitLab:&lt;/p&gt;
&lt;h4&gt;
  
  
  1) Crie o arquivo &lt;code&gt;.versionrc&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Aqui nós estamos adicionando o tipo perf ao &lt;code&gt;CHANGELOG.md&lt;/code&gt;, ao mesmo tempo que estamos também definindo os nomes das sessões em português. Por último, estamos adicionando o &lt;code&gt;[skip ci]&lt;/code&gt; na mensagem de commit que é gerada pelo &lt;code&gt;standard-version&lt;/code&gt;. Isso vai ser útil no futuro.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&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;"types"&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="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"feat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"section"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Funcionalidades"&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="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fix"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"section"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Errors Corrigidos"&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="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chore"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"hidden"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"docs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"hidden"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"style"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"hidden"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"refactor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"hidden"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"perf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"section"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Melhorias de Performance"&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="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"hidden"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"releaseCommitMessageFormat"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chore(release): {{currentTag}} [skip ci]"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


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

&lt;/div&gt;
&lt;h4&gt;
  
  
  2) Altere o &lt;code&gt;package.json&lt;/code&gt; (Opcional: GitLab)
&lt;/h4&gt;

&lt;p&gt;Se quiser mesmo usar outro repositório, é bem provável que você só precise adicionar o &lt;code&gt;repository.url&lt;/code&gt; no seu &lt;code&gt;package.json&lt;/code&gt;. O &lt;code&gt;standard-version&lt;/code&gt; usa essa URL para definir as URLs do CHANGELOG:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"repository"&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;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"git@gitlab.com:meu-usuario/meu-repo.git"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


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

&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;Se tiver problema nas URLs que foram geradas no seu &lt;code&gt;CHANGELOG.md&lt;/code&gt;, você pode adicionar uma configuração customizada para o seguintes campos no seu &lt;code&gt;.versionrc&lt;/code&gt;: &lt;code&gt;commitUrlFormat&lt;/code&gt;, &lt;code&gt;compareUrlFormat&lt;/code&gt; e &lt;code&gt;issueUrlFormat&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Frbxy02lbfsjyma8imp00.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Frbxy02lbfsjyma8imp00.png" alt="CHANGELOG novo na v2.1.1 com Melhorias de Performance sendo exibida"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pode comparar o seu progresso com a &lt;a href="https://github.com/klauskpm/changelog-cicd/tree/v2.1.1" rel="noopener noreferrer"&gt;tag v2.1.1 do repositório&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h1&gt;
  
  
  Automatizando a automatização com integração contínua
&lt;/h1&gt;

&lt;p&gt;O nosso CHANGELOG já é gerado graças ao &lt;code&gt;standard-version&lt;/code&gt;, mas ainda precisamos rodar o script de forma manual. O ideal é que isso aconteça sempre que o código atinja a versão final / produção. Para isso, vamos usar o &lt;a href="https://help.github.com/en/actions" rel="noopener noreferrer"&gt;GitHub Actions&lt;/a&gt; como nossa ferramenta de integração contínua (CI - Continuous Integration).&lt;/p&gt;

&lt;p&gt;No repositório do GitHub, na aba Ações/Actions, vamos criar um &lt;a href="https://help.github.com/en/actions/automating-your-workflow-with-github-actions/starting-with-preconfigured-workflow-templates" rel="noopener noreferrer"&gt;workflow de Node.js&lt;/a&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fb6ie7rmjcte8ns7c1b8z.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fb6ie7rmjcte8ns7c1b8z.png" alt="Página de Actions do GitHub com o workflows de Node.js e Node.js package"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E esse é o arquivo que é gerado por padrão nesse workflow, mas não vamos usa-lo:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# nome do processo&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Node CI&lt;/span&gt;

&lt;span class="c1"&gt;# o processo roda quando tiver um push&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="c1"&gt;# roda o build no ubuntu&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# o processo vai executar uma vez para cada configuração do node&lt;/span&gt;
      &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;8.x&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;10.x&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;12.x&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# esse passo pega uma cópia dos seu repositório&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v1&lt;/span&gt;

    &lt;span class="c1"&gt;# esse passo instala a versão do node&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Use Node.js ${{ matrix.node-version }}&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v1&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ matrix.node-version }}&lt;/span&gt;

    &lt;span class="c1"&gt;# esse passo faz a instalação das dependências, roda o build e o teste&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm install, build, and test&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;npm ci&lt;/span&gt;
        &lt;span class="s"&gt;npm run build --if-present&lt;/span&gt;
        &lt;span class="s"&gt;npm test&lt;/span&gt;
      &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;CI&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;



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

&lt;/div&gt;
&lt;p&gt;Nós vamos usar esse arquivo como base para construir o nosso próprio. Se olhar bem, nós não precisamos realizar um teste, criar uma build ou muito menos rodar em várias versões do node, mas precisamos gerar o CHANGELOG e ele precisa de  permissões para commitar e pushar no GitHub.&lt;/p&gt;

&lt;p&gt;Além disso, tem um ponto que precisamos prestar muita atenção. Como o nosso processo de automatização gera um commit e roda a cada push, &lt;strong&gt;nós vamos criar um loop infinito&lt;/strong&gt;. Felizmente, eu já passei 1 dia resolvendo isso, e depois de 50 commits disparados automaticamente, achei a solução.&lt;/p&gt;

&lt;p&gt;Nos outros sistemas de integração contínua (CI) se fizermos um commit com &lt;code&gt;skip ci&lt;/code&gt; - se lembra do &lt;code&gt;.versionrc&lt;/code&gt;? - esse commit é automaticamente ignorado. Pena que não funciona assim no GitHub. Felizmente, a internet é um lugar maravilhoso e as pessoas &lt;a href="https://github.com/marketplace/actions/skip-based-on-commit-message" rel="noopener noreferrer"&gt;conseguiram desenvolver uma solução&lt;/a&gt; para isso.&lt;/p&gt;

&lt;p&gt;Juntando os fatores que precisávamos para gerar o &lt;code&gt;CHANGELOG.md&lt;/code&gt; e aplicando essa solução que previne o loop, temos o seguinte arquivo: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;.github/workflows/gerador-de-changelog.yml&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Gerador de CHANGELOG&lt;/span&gt;

&lt;span class="c1"&gt;# só executa no push de commit da branch master&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# só deixa executar se o último commit não conter 'skip ci' na mensagem&lt;/span&gt;
    &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;!contains(github.event.head_commit.message,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'skip&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ci')"&lt;/span&gt;

    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v1&lt;/span&gt;

    &lt;span class="c1"&gt;# configura o GITHUB_TOKEN&lt;/span&gt;
    &lt;span class="c1"&gt;# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/authenticating-with-the-github_token&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Configura o GitHub token&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fregante/setup-git-token@v1&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Gerador&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;de&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;changelog"&lt;/span&gt;
        &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;changelog@users.noreply.github.com"&lt;/span&gt;

    &lt;span class="c1"&gt;# instala a versão 11.x do Node.js&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Instala o Node.js 11.x&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v1&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;11.x&lt;/span&gt;

    &lt;span class="c1"&gt;# instala as dependências, vai para a master&lt;/span&gt;
    &lt;span class="c1"&gt;# executa o standard-version, e envia o commit e tag&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Gera o CHANGELOG&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;npm ci&lt;/span&gt;
        &lt;span class="s"&gt;git checkout master&lt;/span&gt;
        &lt;span class="s"&gt;npm run release&lt;/span&gt;
        &lt;span class="s"&gt;git push origin master --follow-tags&lt;/span&gt;


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

&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;Se quiser saber mais sobre como &lt;a href="https://help.github.com/en/actions/automating-your-workflow-with-github-actions/configuring-a-workflow" rel="noopener noreferrer"&gt;configurar um workflow&lt;/a&gt;, como funciona a &lt;a href="https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions" rel="noopener noreferrer"&gt;sintaxe do workflow do GitHub Actions&lt;/a&gt; e &lt;a href="https://help.github.com/en/actions/automating-your-workflow-with-github-actions/authenticating-with-the-github_token" rel="noopener noreferrer"&gt;o que é o GITHUB_TOKEN&lt;/a&gt;, sugiro seguir esses links.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pronto! Agora nossa automatização está completa!&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fesqa7kc50dcxujat4r0u.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fesqa7kc50dcxujat4r0u.png" alt="Painel de Workflows do GitHub com o Gerador de CHANGELOG aberto após ter rodado com sucesso"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pode comparar o seu progresso com a &lt;a href="https://github.com/klauskpm/changelog-cicd/tree/v2.1.2" rel="noopener noreferrer"&gt;tag v2.1.2 do repositório&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Última graça
&lt;/h2&gt;

&lt;p&gt;Por último, só para fazer uma graça, podemos adicionar um &lt;a href="https://help.github.com/en/actions/automating-your-workflow-with-github-actions/configuring-a-workflow#adding-a-workflow-status-badge-to-your-repository" rel="noopener noreferrer"&gt;status badge (distintivo/indicador de status) para o nosso build&lt;/a&gt;. Isso é uma imagem que indica se o build passou ou não. Podemos adicionar isso no nosso &lt;code&gt;README.md&lt;/code&gt; seguindo esse padrão de URL:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;

URL 
&lt;span class="p"&gt;![](&lt;/span&gt;&lt;span class="sx"&gt;https://github.com/&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;CONTA&amp;gt;&lt;/span&gt;/&lt;span class="nt"&gt;&amp;lt;REPOSITORIO&amp;gt;&lt;/span&gt;/workflows/&lt;span class="nt"&gt;&amp;lt;NOME_WORKFLOW&amp;gt;&lt;/span&gt;/badge.svg)

Exemplo do meu repositório:
&lt;span class="p"&gt;![](&lt;/span&gt;&lt;span class="sx"&gt;https://github.com/klauskpm/changelog-cicd/workflows/Gerador%20de%20CHANGELOG/badge.svg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="sb"&gt;


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

&lt;/div&gt;
&lt;p&gt;Sendo &lt;code&gt;klauskpm&lt;/code&gt; meu usuário, &lt;code&gt;changelog-cicd&lt;/code&gt; o repositório que estou usando, e &lt;code&gt;Gerador de CHANGELOG&lt;/code&gt; o nome do workflow, &lt;strong&gt;não o do arquivo&lt;/strong&gt;, com &lt;code&gt;%20&lt;/code&gt; em vez de espaços.&lt;/p&gt;

&lt;p&gt;Assim que sua badge será exibida no seu &lt;code&gt;README.md&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/klauskpm/changelog-cicd/workflows/Gerador%20de%20CHANGELOG/badge.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://github.com/klauskpm/changelog-cicd/workflows/Gerador%20de%20CHANGELOG/badge.svg" alt="Status Badge do Gerador de CHANGELOG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pode comparar o seu progresso com a &lt;a href="https://github.com/klauskpm/changelog-cicd/tree/v2.1.3" rel="noopener noreferrer"&gt;tag v2.1.3 do repositório&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h1&gt;
  
  
  Conclusão
&lt;/h1&gt;

&lt;p&gt;Com esse artigo nós:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Melhoramos a qualidade dos commits&lt;/li&gt;
&lt;li&gt;Automatizamos a geração de CHANGELOG e subida de versão&lt;/li&gt;
&lt;li&gt;Fizemos integração contínua com GitHub Actions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Caso algo tenha dado errado, pode sempre consultar o repositório com a versão final e um passo-a-passo super resumido desse artigo.&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/klauskpm" rel="noopener noreferrer"&gt;
        klauskpm
      &lt;/a&gt; / &lt;a href="https://github.com/klauskpm/changelog-cicd" rel="noopener noreferrer"&gt;
        changelog-cicd
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Repositório para ensinar a criar CHANGELOG automaticamente
    &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;changelog-cicd&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/klauskpm/changelog-cicd/workflows/Gerador%20de%20CHANGELOG/badge.svg"&gt;&lt;img src="https://github.com/klauskpm/changelog-cicd/workflows/Gerador%20de%20CHANGELOG/badge.svg" alt="Status Badge do Gerador de CHANGELOG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repositório com passo-a-passo de como gerar um CHANGELOG automaticamente.&lt;/p&gt;

&lt;p&gt;Esse passo-a-passo é a versão muito resumida do artigo: &lt;a href="https://github.com/klauskpm/changelog-cicd" rel="noopener noreferrer"&gt;Como gerar CHANGELOG automaticamente&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Gerando um CHANGELOG automaticamente&lt;/h2&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;1) Instale as dependências&lt;/h3&gt;
&lt;/div&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm install --global commitizen

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; dentro do seu projeto&lt;/span&gt;
npm install --save-dev husky @commitlint/cli @commitlint/config-conventional standard-version&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;2) Configure o commitizen&lt;/h3&gt;

&lt;/div&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; dentro do seu projeto&lt;/span&gt;
commitizen init cz-conventional-changelog --save-dev --save-exact&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;3) Crie o arquivo &lt;code&gt;commitlint.config.js&lt;/code&gt;
&lt;/h3&gt;

&lt;/div&gt;

&lt;div class="highlight highlight-source-js notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-smi"&gt;module&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;exports&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;extends&lt;/span&gt;: &lt;span class="pl-kos"&gt;[&lt;/span&gt;&lt;span class="pl-s"&gt;'@commitlint/config-conventional'&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;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;4) Altere o seu &lt;code&gt;package.json&lt;/code&gt;
&lt;/h3&gt;

&lt;/div&gt;

&lt;div class="highlight highlight-source-json notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;{
  &lt;span class="pl-ii"&gt;...,&lt;/span&gt;
  &lt;span class="pl-ii"&gt;// opcional&lt;/span&gt;
  &lt;span class="pl-ent"&gt;"repository"&lt;/span&gt;: {
    &lt;span class="pl-ent"&gt;"url"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;git@gitlab.com:meu-usuario/meu-repo.git&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
  },
  &lt;span class="pl-ii"&gt;...,&lt;/span&gt;
  &lt;span class="pl-ent"&gt;"husky"&lt;/span&gt;: {
    &lt;span class="pl-ent"&gt;"hooks"&lt;/span&gt;: {
      &lt;span class="pl-ent"&gt;"commit-msg"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;commitlint -E HUSKY_GIT_PARAMS&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
    }
  },
  &lt;span class="pl-ent"&gt;"scripts"&lt;/span&gt;: {
    &lt;span class="pl-ent"&gt;"release"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;standard-version&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
  }
}&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;5) Crie o arquivo &lt;code&gt;.versionrc&lt;/code&gt;
&lt;/h3&gt;

&lt;/div&gt;

&lt;div class="highlight highlight-source-json notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;{
  &lt;span class="pl-ent"&gt;"types"&lt;/span&gt;: [
    {&lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;feat&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-ent"&gt;"section"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Funcionalidades&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;}
    {&lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;fix&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/klauskpm/changelog-cicd" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;






&lt;p&gt;Não deixe de me seguir caso queira receber mais artigos como esse, e compartilhar com seus colegas caso tenha ❤️. Não deixe de comentar se tiver algo que acha que eu deva mudar no artigo.&lt;/p&gt;

&lt;p&gt;Um forte abraço e te vejo na próxima 😬&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>devops</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Como criar uma biblioteca de componentes com Angular e Storybook</title>
      <dc:creator>Klaus Kazlauskas</dc:creator>
      <pubDate>Fri, 03 Jan 2020 12:10:42 +0000</pubDate>
      <link>https://dev.to/klauskpm/como-criar-uma-biblioteca-de-componentes-com-angular-e-storybook-420p</link>
      <guid>https://dev.to/klauskpm/como-criar-uma-biblioteca-de-componentes-com-angular-e-storybook-420p</guid>
      <description>&lt;p&gt;Se você já tentou &lt;a href="https://angular.io/guide/creating-libraries" rel="noopener noreferrer"&gt;criar uma biblioteca&lt;/a&gt; de componentes pro seu sistema, você com toda certeza já alterou um componente que quebrou várias páginas e quando te perguntaram quem foi...&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%2Fi.kym-cdn.com%2Fphotos%2Fimages%2Foriginal%2F001%2F471%2F227%2Fdd0.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%2Fi.kym-cdn.com%2Fphotos%2Fimages%2Foriginal%2F001%2F471%2F227%2Fdd0.png" alt="Um fantoche de macaco olha de canto de olho pra tela, e depois olha pra frente como se não tivesse visto nada"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pra eliminar esse e outros problemas, como não saber se um componente existe, como funciona ou em que página você pode ver um exemplo dele funcionando; existe o Storybook.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://storybook.js.org/" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F321738%2F63501763-88dbf600-c4cc-11e9-96cd-94adadc2fd72.png" alt="Logo do Storybook"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O Storybook se denomina como "&lt;em&gt;Um explorador de componentes UI para desenvolvedores front-end&lt;/em&gt;". Isso quer dizer que ele serve para gerar várias histórias dos nossos componentes, assim como a documentação deles, para facilitar a exploração visual dos nossos componentes.&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%2Fmiro.medium.com%2Fproxy%2F1%2A593C9tIr2pYJRbjmhA2GJA.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%2Fmiro.medium.com%2Fproxy%2F1%2A593C9tIr2pYJRbjmhA2GJA.gif" alt="Vídeo de exemplo do Storybook"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Então, vamos criar passo-a-passo essa biblioteca de componentes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Preparação
&lt;/h2&gt;

&lt;p&gt;Na época que esse guia foi preparado, foram usadas as seguintes tecnologias:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;tecnologia&lt;/th&gt;
&lt;th&gt;versão&lt;/th&gt;
&lt;th&gt;instalação&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;td&gt;11.6.0&lt;/td&gt;
&lt;td&gt;&lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;como instalar&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NPM&lt;/td&gt;
&lt;td&gt;6.13.4&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Já vem com o Node.js&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Angular CLI&lt;/td&gt;
&lt;td&gt;8.3.21&lt;/td&gt;
&lt;td&gt;&lt;a href="https://angular.io/guide/setup-local#step-1-install-the-angular-cli" rel="noopener noreferrer"&gt;como instalar&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Todo o código desse projeto está no GitHub, então, caso você se perca em qualquer parte, pode fazer uma comparação direta:&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/klauskpm" rel="noopener noreferrer"&gt;
        klauskpm
      &lt;/a&gt; / &lt;a href="https://github.com/klauskpm/angular-storybook" rel="noopener noreferrer"&gt;
        angular-storybook
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Repositório para ensinar a usar Storybook com Angular.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h4&gt;
  
  
  ⚠️ Caso você já saiba gerar uma biblioteca, você pode pular para a sessão Instalando o Storybook ⚠️
&lt;/h4&gt;

&lt;h2&gt;
  
  
  Gerando o projeto
&lt;/h2&gt;

&lt;p&gt;Usando o Angular CLI, vamos criar um projeto chamado &lt;code&gt;angular-storybook&lt;/code&gt; e uma biblioteca chamada &lt;code&gt;storybook-ui&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 angular-storybook

&lt;span class="c"&gt;# dentro do projeto angular-storybook&lt;/span&gt;
ng g lib storybook-ui &lt;span class="nt"&gt;--prefix&lt;/span&gt; ui &lt;span class="c"&gt;# versão curta de ng generate library&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Já temos o projeto para usar nossos componentes, e temos a biblioteca onde vamos desenvolver eles. A biblioteca já vem com um componente pronto, mas não vamos usar ele. Então, vamos até a pasta &lt;code&gt;/projects/storybook-ui/src/lib/&lt;/code&gt; e deletamos tudo de lá. Nessa mesma pasta vamos criar o módulo e componente &lt;code&gt;simple-button&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;&lt;span class="c"&gt;# dentro da pasta /projects/storybook/src/lib&lt;/span&gt;

ng g m simple-button &lt;span class="c"&gt;# versão curta de ng generate module&lt;/span&gt;

ng g c simple-button &lt;span class="nt"&gt;--export&lt;/span&gt; &lt;span class="c"&gt;# versão curta de ng generate componente&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E vamos dar uma cara de botão para o nosso componente:&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;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;ui-simple-button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;button&amp;gt;{{text}}&amp;lt;/button&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&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;SimpleButtonComponent&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="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;clique aqui&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;p&gt;Agora, vamos no arquivo &lt;code&gt;/projects/storybook/src/public_api.ts&lt;/code&gt; e substituir todo o conteúdo desse arquivo por:&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;export&lt;/span&gt; &lt;span class="o"&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;./lib/simple-button/simple-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="o"&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;./lib/simple-button/simple-button.module&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;Para usar esse componente precisamos gerar o arquivo final da biblioteca:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng b storybook-ui &lt;span class="c"&gt;# versão curta de ng build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reescrever o &lt;code&gt;/src/app/app.component.html&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;Ola Mundo!
&lt;span class="nt"&gt;&amp;lt;ui-simple-button&amp;gt;&amp;lt;/ui-simple-button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E adicionar o &lt;code&gt;SimpleButtonModule&lt;/code&gt; ao &lt;code&gt;/src/app/app.module.ts&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;BrowserModule&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/platform-browser&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;NgModule&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SimpleButtonModule&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-ui&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;AppComponent&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;./app.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="na"&gt;declarations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;AppComponent&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;BrowserModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;SimpleButtonModule&lt;/span&gt; &lt;span class="c1"&gt;// modificado&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AppComponent&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;AppModule&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;Por último, vamos servir nossa aplicação e ver como ela está no &lt;a href="http://localhost:4200" rel="noopener noreferrer"&gt;http://localhost:4200&lt;/a&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 s &lt;span class="c"&gt;# versão curta de ng serve angular-storybook&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F01j0cq7vjg2klkbx9qf9.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F01j0cq7vjg2klkbx9qf9.png" alt="Projeto de Angular rodando na porta 4200, com o texto "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pode comparar o seu progresso com a &lt;a href="https://github.com/klauskpm/angular-storybook/tree/v1.2" rel="noopener noreferrer"&gt;tag v1.2 do repositório&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Instalando o Storybook
&lt;/h2&gt;

&lt;p&gt;O Storybook tem um &lt;a href="https://storybook.js.org/docs/guides/guide-angular/" rel="noopener noreferrer"&gt;guia de como fazer a instalação em um projeto Angular&lt;/a&gt; e o jeito mais fácil é só usando uma única linha:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;-p&lt;/span&gt; @storybook/cli sb init &lt;span class="nt"&gt;--type&lt;/span&gt; angular
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Executando essa linha no seu projeto, ele:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;instala todas as dependências necessárias&lt;/li&gt;
&lt;li&gt;adiciona os scripts &lt;code&gt;storybook&lt;/code&gt; e &lt;code&gt;build-storybook&lt;/code&gt; no seu package.json&lt;/li&gt;
&lt;li&gt;cria os arquivos de configuração pro Storybook&lt;/li&gt;
&lt;li&gt;cria as histórias de exemplo no seu projeto principal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para ver o Storybook em ação, é só rodar o comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run storybook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ftup293mgc2eu5ksz10qc.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ftup293mgc2eu5ksz10qc.png" alt="Página do Storybook rodando em localhost:6006, exibindo a história ˜with some emoji and action"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tudo bonito, tudo rodando. Mas, a configuração do Storybook está apenas pro seu projeto principal, e não para a sua biblioteca. Além disso, você sabe o que foi adicionado e para que? Então vamos voltar no tempo e seguir de forma manual.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fazendo a instalação manualmente
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1) Instale as dependências
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @storybook/angular babel-loader @babel/core &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2) Adicione os scripts de npm
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&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;"storybook"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"start-storybook -p 6006"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build-storybook"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"build-storybook"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O script &lt;code&gt;storybook&lt;/code&gt; vai executar o &lt;a href="https://storybook.js.org/docs/configurations/cli-options/#for-start-storybook" rel="noopener noreferrer"&gt;start-storybook&lt;/a&gt; para exibir nossas histórias no &lt;a href="http://localhost:6006" rel="noopener noreferrer"&gt;http://localhost:6006&lt;/a&gt;. O &lt;code&gt;build-storybook&lt;/code&gt; vai executar o &lt;a href="https://storybook.js.org/docs/configurations/cli-options/#for-build-storybook" rel="noopener noreferrer"&gt;build-storybook&lt;/a&gt; que vai gerar os arquivos estáticos do Storybook na pasta &lt;code&gt;storybook-static&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Você pode definir o diretório final mudando o comando &lt;code&gt;build-storybook&lt;/code&gt; por &lt;code&gt;build-storybook -o /dist/storybook&lt;/code&gt;, colocando os arquivos estáticos no mesmo diretório que os builds gerados pelo seu projeto.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  3) Crie o arquivo de configuração
&lt;/h4&gt;

&lt;p&gt;É esse o arquivo que o Storybook vai usar para saber onde ele pode procurar as nossas histórias e como identificar os arquivos. No caso, vamos procurar arquivos com &lt;code&gt;.stories.ts&lt;/code&gt; neles, dentro das pastas &lt;code&gt;src&lt;/code&gt; e &lt;code&gt;projects&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Crie o arquivo &lt;code&gt;.storybook/config.js&lt;/code&gt; com o seguinte conteúdo:&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;configure&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&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../src&lt;/span&gt;&lt;span class="dl"&gt;'&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="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;stories&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;ts$/&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../projects&lt;/span&gt;&lt;span class="dl"&gt;'&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="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;stories&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;ts$/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4) Configure o Storybook para funcionar com TypeScript
&lt;/h4&gt;

&lt;p&gt;Como o &lt;code&gt;@storybook/angular&lt;/code&gt; usa o &lt;a href="https://github.com/TypeStrong/fork-ts-checker-webpack-plugin" rel="noopener noreferrer"&gt;ForkTsCheckerWebpackPlugin&lt;/a&gt;, precisamos criar o arquivo &lt;code&gt;.storybook/tsconfig.json&lt;/code&gt;:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"../tsconfig.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"exclude"&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;"../src/test.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"../src/**/*.spec.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"../projects/**/*.spec.ts"&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;"include"&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;"../src/**/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"../projects/**/*"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  5) Escreva sua história 🎉
&lt;/h4&gt;

&lt;p&gt;Finalmente! Agora vamos criar nossa própria história e ver como ela se comporta.&lt;/p&gt;

&lt;p&gt;Dentro da pasta do nosso componente &lt;code&gt;simple-button&lt;/code&gt;, vamos criar o arquivo &lt;code&gt;index.stories.ts&lt;/code&gt; com o conteúdo a seguir:&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;SimpleButtonComponent&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="s2"&gt;./simple-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;UI | Button&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;withDefaultValues&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="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SimpleButtonComponent&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;withText&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="k"&gt;return&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;SimpleButtonComponent&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="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ola&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Essa é uma das formas que podemos escrever as histórias. Ela é chamada de &lt;a href="https://storybook.js.org/docs/formats/component-story-format/" rel="noopener noreferrer"&gt;CSF (Component Story Format)&lt;/a&gt;. Também temos a &lt;a href="https://storybook.js.org/docs/formats/storiesof-api/" rel="noopener noreferrer"&gt;StoriesOf API&lt;/a&gt; e o &lt;a href="https://storybook.js.org/docs/formats/mdx-syntax/" rel="noopener noreferrer"&gt;MDX Syntax, que está por vir&lt;/a&gt;. Como o CSF é um adição nova no Storybook, boa parte dos exemplos da internet vão estar usando o StoriesOf API.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dessa forma estamos falando que temos o componente Button, dentro do agrupador UI, com as histórias "With Default Values" e "With Text".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UI
└── Button
    ├── With Default Values
    ├── With Text

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  6) Rode o projeto
&lt;/h4&gt;

&lt;p&gt;Rode o projeto com o &lt;code&gt;npm run storybook&lt;/code&gt; e veja o resultado final:&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ff9cdv0ktd2vxdqvzh1yr.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ff9cdv0ktd2vxdqvzh1yr.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pode comparar o seu progresso com a &lt;a href="https://github.com/klauskpm/angular-storybook/tree/v1.3" rel="noopener noreferrer"&gt;tag v1.3 do repositório&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Próximos passos - addons
&lt;/h2&gt;

&lt;p&gt;Agora que você aprendeu como configurar o Storybook e escrever uma história, você pode melhorar a qualidade das suas histórias com simples pluggins, chamados de &lt;a href="https://storybook.js.org/addons/" rel="noopener noreferrer"&gt;addons&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Por exemplo, com o addon de &lt;a href="https://github.com/storybookjs/storybook/blob/master/addons/actions/README.md" rel="noopener noreferrer"&gt;actions&lt;/a&gt; você pode adicionar logs para ações, como clicks, e ouvir o que eles estão enviando. Com o addon de &lt;a href="https://github.com/storybookjs/storybook/tree/master/addons/knobs/README.md" rel="noopener noreferrer"&gt;knobs&lt;/a&gt; você pode expor &lt;code&gt;@Input&lt;/code&gt;s do seu componente e altera-los na hora.&lt;/p&gt;

&lt;p&gt;Pra não ficar só na explicação e sonhos, vamos montar ele agora. É muito fácil.&lt;/p&gt;

&lt;h4&gt;
  
  
  1) Instale as dependências
&lt;/h4&gt;

&lt;p&gt;Além dos pacotes óbvios do knobs e do actions, precisamos também instalar o pacote do addons, que vai ser responsável por carregar os addons no Storybook.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @storybook/addons @storybook/addon-knobs @storybook/addon-actions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2) Crie o arquivo de configuração dos addons
&lt;/h4&gt;

&lt;p&gt;Crie o arquivo &lt;code&gt;.storybook/addons.js&lt;/code&gt; com a seguinte configuração:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import '@storybook/addon-knobs/register';
import '@storybook/addon-actions/register';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;A ordem que você &lt;em&gt;importa&lt;/em&gt; eles é importante. Ela vai dizer a ordem em que esses addons vão aparecer nos paineis&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  3) Aplique os addons na sua história
&lt;/h4&gt;

&lt;p&gt;No nosso caso, vamos usar o knobs para expor o &lt;code&gt;@Input&lt;/code&gt; text e o actions para exibir uma mensagem ao clicar no botão. Como vamos lidar com um evento e não uma propriedade, não podemos mais usar o &lt;code&gt;component&lt;/code&gt; na história &lt;code&gt;withText&lt;/code&gt;, pois o &lt;code&gt;props&lt;/code&gt; só define propriedades e não eventos. Precisamos usar o &lt;code&gt;template&lt;/code&gt;, mas para usarmos o template, precisamos definir o módulo com o componente &lt;code&gt;SimpleButtonComponent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;No final das contas, o nosso &lt;code&gt;index.stories.ts&lt;/code&gt; do &lt;code&gt;SimpleButtonComponent&lt;/code&gt; vai ficar assim:&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;SimpleButtonComponent&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="s2"&gt;./simple-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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;withKnobs&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/addon-knobs&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;moduleMetadata&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&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;action&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/addon-actions&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;UI | Button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;decorators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;withKnobs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;moduleMetadata&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;declarations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;SimpleButtonComponent&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;withDefaultValues&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="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SimpleButtonComponent&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;withText&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
        &amp;lt;ui-simple-button
          [text]="text"
          (click)="click($event)"
        &amp;gt;&amp;lt;/ui-simple-button&amp;gt;
    `&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="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ola&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&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;Clicou&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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E quando rodarmos o Storybook:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fs4izuk7rgt6ohjnbhdxk.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fs4izuk7rgt6ohjnbhdxk.png" alt="História "&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Frsn2w4c4pto3zr59en57.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Frsn2w4c4pto3zr59en57.png" alt="História "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pode comparar o seu progresso com a &lt;a href="https://github.com/klauskpm/angular-storybook/tree/v1.4" rel="noopener noreferrer"&gt;tag v1.4 do repositório&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  Conclusão
&lt;/h1&gt;

&lt;p&gt;Agora, você sabe como...&lt;br&gt;
✅ Instalar e configurar o Storybook&lt;br&gt;
✅ Criar histórias para componentes&lt;br&gt;
✅ Instalar e configurar addons&lt;/p&gt;

&lt;p&gt;Você não vai ter mais problemas em relação ao que sua aplicação tem ou não tem, e o desenvolvimento vai seguir com mais confiança e agilidade, por poder testar as mudanças em diversos cenários.&lt;/p&gt;

&lt;p&gt;Se você se interessou pelo Storybook e quer saber o que mais ele pode fazer, você pode começar a ver como...&lt;br&gt;
❗ &lt;a href="https://storybook.js.org/docs/basics/writing-stories/" rel="noopener noreferrer"&gt;Aprender o que compõe uma história&lt;/a&gt;&lt;br&gt;
❗ &lt;a href="https://storybook.js.org/docs/basics/exporting-storybook/" rel="noopener noreferrer"&gt;Exportar e deployar arquivos estáticos das histórias&lt;/a&gt;&lt;br&gt;
❗ &lt;a href="https://storybook.js.org/docs/configurations/theming/" rel="noopener noreferrer"&gt;Tematizar o Storybook&lt;/a&gt;&lt;br&gt;
🎉 &lt;a href="https://storybookjs-next.now.sh/angular-cli/?path=/story/addon-background--background-component" rel="noopener noreferrer"&gt;E muito mais&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Se você ❤️ esse artigo, não deixe de me seguir e compartilhar com seus colegas. E se achar que tem algo para mudar no artigo, não deixe de comentar!&lt;/p&gt;

&lt;p&gt;Te vejo na próxima! 😬&lt;/p&gt;

</description>
      <category>angular</category>
      <category>storybook</category>
    </item>
  </channel>
</rss>
