<?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>Forem: Michel Araujo</title>
    <description>The latest articles on Forem by Michel Araujo (@michelaraujo).</description>
    <link>https://forem.com/michelaraujo</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%2F440385%2F87b62a60-74d5-4e96-92e9-ca7aaabe3c1e.jpeg</url>
      <title>Forem: Michel Araujo</title>
      <link>https://forem.com/michelaraujo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/michelaraujo"/>
    <language>en</language>
    <item>
      <title>First look in Chrome Built-in AI [Early Preview] with Gemini Nano</title>
      <dc:creator>Michel Araujo</dc:creator>
      <pubDate>Sat, 12 Oct 2024 14:47:06 +0000</pubDate>
      <link>https://forem.com/michelaraujo/first-look-in-chrome-built-in-ai-early-preview-with-gemini-nano-34b8</link>
      <guid>https://forem.com/michelaraujo/first-look-in-chrome-built-in-ai-early-preview-with-gemini-nano-34b8</guid>
      <description>&lt;p&gt;In the past few weeks, I have been testing the Gemini Nano built into Google Chrome. The goal of this post is to provide some initial feedback on this new feature, which may be officially released in Chrome soon.&lt;/p&gt;

&lt;h3&gt;
  
  
  A little context
&lt;/h3&gt;

&lt;p&gt;The main goal of integrating Gemini Nano into Google Chrome via a Web API is to promote and facilitate small AI features within web pages, without affecting performance or requiring server requests for simple responses, so, with this goal in mind, the Chrome team is working to make Gemini Nano available through an API in Chrome. This initial implementation has some limitations: it currently only works on desktops, requires a device with a GPU, and needs some available storage. To learn more about this project, you can view the official documentation here =&amp;gt; &lt;a href="https://developer.chrome.com/docs/ai/built-in" rel="noopener noreferrer"&gt;https://developer.chrome.com/docs/ai/built-in&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; It’s important to emphasize that this implementation is still in its early stages, and changes or improvements may be coming soon.&lt;/p&gt;

&lt;h3&gt;
  
  
  My test
&lt;/h3&gt;

&lt;p&gt;To build my test I used a web page that I have in my lab repository build in NextJS, I used this page for a variety of tests so this project can looks like a little messy but is only for test, if you want to take a look check it out in =&amp;gt; &lt;a href="https://github.com/MichelAraujo/lab-playground/tree/master/my-app-next" rel="noopener noreferrer"&gt;https://github.com/MichelAraujo/lab-playground/tree/master/my-app-next&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this test I used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Macbook Pro M3, 18Gbs&lt;/li&gt;
&lt;li&gt;macOS 15.0&lt;/li&gt;
&lt;li&gt;Google Chrome Canary 131.0&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My goal here was build a simple feature for understand how this built-in AI in Chrome works, for that I build a English sentence feedback, in summary works like this, I put a sentence in English and the AI give some feedback about my sentence and how I can improve it (all using AI built-in in Chrome without make any request in the server).&lt;/p&gt;

&lt;p&gt;A little bit about my prompt config (for this test I used the Prompt API, you can learn more about in the official doc):&lt;br&gt;
Note: In this built-in AI experimentation, we had access to other available APIs, such as the Summarization API, Language Detection, and a few others.&lt;/p&gt;

&lt;p&gt;The Prompt initialization example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createPromptSession&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;available&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assistant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;capabilities&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;available&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;no&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;session&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;## Create session ##&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nx"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assistant&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;systemPrompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;you're an English teacher&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nf"&gt;monitor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;downloadprogress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;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="s2"&gt;`Downloaded &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loaded&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; of &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; bytes.`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;session&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;session&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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;# Error - assistant is not available&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key point here is the context I provide in the prompt, like 'you're an English teacher,' to ensure that my feature delivers accurate feedback on English usage in the results.&lt;/p&gt;

&lt;p&gt;Next, I create the prompt and send a string with context about what I want in the response, along with the user input from the page.&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;streaming&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;clonedSession&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;promptStreaming&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Give me feedback about the grammar on the following sentence in English. Sentence: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sentence&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;streaming&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check out some feedback that AI give me with this setup, this is a simple Prompt setup but you can check the accuracy of the response, check out:&lt;/p&gt;

&lt;p&gt;First, a simple sentence "I want to be a good guitar player!"&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%2Fn2yq77yap7e2h7j5jxa4.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%2Fn2yq77yap7e2h7j5jxa4.png" alt="Print of the page with the result AI text" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Second, I use the same sentence to check for a different result.&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%2F4sfq0zn159es495dxvxy.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%2F4sfq0zn159es495dxvxy.png" alt="Print of the page with the result AI text" width="800" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Third, a more complex sentence with little mistake:&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%2Fzdr5asb33zi66pgff5l7.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%2Fzdr5asb33zi66pgff5l7.png" alt="Print of the page with the result AI text" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I like this feedback!&lt;/p&gt;

&lt;p&gt;Forth, the suggestion sentence of the previous answer:&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%2Fvxjvbqm7tbh0xaj2m3xa.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%2Fvxjvbqm7tbh0xaj2m3xa.png" alt="Print of the page with the result AI text" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The average quality of the answers (in my opinion) is OK, some with little mistakes or lack of context but in general is very good! Like I said, my Prompt setup can be improved too.&lt;br&gt;
In the code example in the repository, I've included some prompt configuration commands that adjust the quality and context of the responses, if you'd like to check them out.&lt;/p&gt;

&lt;h3&gt;
  
  
  About performance
&lt;/h3&gt;

&lt;p&gt;Here is the point that surprised my a lot, the performance is very good, for all of my tests I can't detect any lake of the performance or degradation in some aspects of my page. I make the tests in a page running animation and when I run the test I don't see lake of the performance in render.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I tried running the same test on an old notebook I have with Windows to check the performance, but it doesn't have enough storage to run the experimental Chrome Canary with the built-in features installed. =(&lt;/p&gt;

&lt;p&gt;For performance tests I like to show running in live, so I made a quick video that shows some tests.&lt;br&gt;
For this tests I simulate 6x slowdown CPU and Slow 4g connection and the performance runs very good like you can see in the video below:&lt;br&gt;
&lt;a href="https://youtu.be/DI2pAZ-N8tw" rel="noopener noreferrer"&gt;https://youtu.be/DI2pAZ-N8tw&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I made some record in Devtools performance panel to see show the main thread, GPU thread, behaves when I run the AI prompts, the result was:&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%2F3aic8yheicp10sz0b3r1.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%2F3aic8yheicp10sz0b3r1.png" alt="show performance test result" width="800" height="335"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see a lot of GPU used as expected because de IA execution uses GPU.&lt;/p&gt;

&lt;p&gt;Next, test:&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%2Ft9jqn6ywcj5dbu5aynze.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%2Ft9jqn6ywcj5dbu5aynze.png" alt="show performance test result" width="800" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The main thread seems to be running very smoothly with little JS / Render tasks that don't compromise other JS tasks execution.&lt;/p&gt;

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

&lt;p&gt;This is a very early-stage feature, so it will see significant improvements in the future. However, it already looks very promising, and I can't wait to see how web pages will leverage it to create new features for users.&lt;br&gt;
I hope this arrives for mobile too, let's wait and see.&lt;br&gt;
Maybe I will share more tests.&lt;/p&gt;

&lt;p&gt;Thanks!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ia</category>
      <category>javascript</category>
      <category>gemini</category>
    </item>
    <item>
      <title>INP (Interaction to Next Paint) Dicas para ajudar a melhorar essa métrica do Core Web Vitals</title>
      <dc:creator>Michel Araujo</dc:creator>
      <pubDate>Mon, 15 Apr 2024 14:49:11 +0000</pubDate>
      <link>https://forem.com/michelaraujo/como-iniciar-na-jornada-de-melhorar-o-inp-de-uma-pagina-web-4aj2</link>
      <guid>https://forem.com/michelaraujo/como-iniciar-na-jornada-de-melhorar-o-inp-de-uma-pagina-web-4aj2</guid>
      <description>&lt;p&gt;Esse post tem como objetivo mostrar algumas técnicas simples que podem ser usadas em aplicações reais e ajudar você a da os primeiros passos na melhora do INP, os exemplos aqui em termos de codificação e funcionalidades são realmente simples mas o ideal é fazer o exercício de pegar o que achar interessante aqui entender mais a fundo e abstrair para o seu cenário em questão.&lt;/p&gt;

&lt;h3&gt;
  
  
  O que o INP tenta resolver?
&lt;/h3&gt;

&lt;p&gt;Primeiro é importante de fato entender o que é a métrica Interaction to Next Paint (INP), qual problema ela tenta resolver (evidenciar) e se quiser entender um pouco mais do histórico seria bom pesquisar porque ela substituiu o FID como métrica do Core Web Vitals.&lt;br&gt;
Dando um resumo inicial o INP tenta medir a responsividade que uma página web tem metrificando o tempo que leva para o navegador renderizar algo na tela depois de alguma interação do usuário, essa interação pode ser click, tab, eventos de teclado, mouse e etc, com base nesse valor (em MS) podemos medir seguindo as definições do Google se um interação tem uma boa, média ou pobre responsividade (INP).&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%2Fx00cpqo9nwo2ek0jcq2g.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%2Fx00cpqo9nwo2ek0jcq2g.png" alt="Imagem que mostra o range para o INP ser considerado bom, medio ou ruim" width="688" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para a medição do Core Web Vitals em si que é o valor mostrado na página do pagespeed, por exemplo:&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%2Fayeul69q32dl59x1zo6x.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%2Fayeul69q32dl59x1zo6x.png" alt="Imagem que mostra um print da pagina do pagespeed mostrando um fica o INP" width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cada interação na sua página vai gerar um valor em MS que conta para essa métrica, usuários que usam o Chrome o CrUX (Chrome User Experience Report) vai pegar sempre o maior valor para contar como a métrica INP daquela sessão, exemplo:&lt;br&gt;
Se o usuário clicar em dois botões na página e essas interações ficarem em torno de 30ms e depois na mesma sessão o usuário clicar em um link e a interação lever 200ms é os 200 que conta, que é enviado pelo CrUX.&lt;br&gt;
Tem algumas regrinhas para remover outliers e gera um número baseado no 75 percentil com base nos acessos de outros usuários, mas em resumo é mais ou menos assim que funciona.&lt;/p&gt;

&lt;p&gt;Para entender melhor como esses dados são coletados aconcelho da uma olhada nesse post: &lt;a href="https://web.dev/articles/vitals#measure-report"&gt;https://web.dev/articles/vitals#measure-report&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ponto importante:&lt;/strong&gt; Vale ressaltar aqui que essas métricas do Web Vitals não são feitas de forma aleatórias pelo Google, nem para “ferrar” os donos de site mas é um meio de metrificar, evidenciar problemas nas páginas web que impactam diretamente a experiência do usuário e que muitas vezes passam despercebidas, então sempre tenha em mente que as métricas do Web Vitals no fim de dia é para ajudar na UX da sua página.&lt;/p&gt;
&lt;h3&gt;
  
  
  Recomendo entender um pouco como o browser funciona
&lt;/h3&gt;

&lt;p&gt;Para entender mais facilmente como identificar os pontos de gargalos e entender como as técnicas mostradas aqui ajudam é recomendado ter uma noção básica de como o navegador funciona, eu gosto bastante desse vídeo ele dá uma boa introdução sobre o event loop e como o JS é executado na página:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/cCOL7MC4Pl0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Tem também a transcrição do vídeo em formato de post:&lt;br&gt;
&lt;a href="https://www.andreaverlicchi.eu/blog/jake-archibald-in-the-loop-jsconf-asia-talk-transposed/"&gt;https://www.andreaverlicchi.eu/blog/jake-archibald-in-the-loop-jsconf-asia-talk-transposed/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  O problema
&lt;/h2&gt;

&lt;p&gt;Beleza, agora temos uma noção um pouco melhor do que é o INP e de como esses dados são coletados, agora vamos entender mais a fundo o problema que essa métrica tenta evidenciar. Para exemplificar de uma forma mais didática eu criei uma página de exemplo que tem apenas uma interação (click em um botão para mostrar uma imagem) mas essa interação está com uma podre responsividade (problema de INP).&lt;/p&gt;

&lt;p&gt;Obs: O objetivo aqui não é focar no código fonte ou boas práticas de programação mas sim nas técnicas para melhora do INP.&lt;/p&gt;

&lt;p&gt;A página de exemplo está em Next JS 14.1.4 e React 18, a estrutura inicial foi criada usando os comando CLI do próprio Next JS, para esse post foi escolhida essas tecnologias apenas pela facilidade do setup inicial.&lt;br&gt;
Todos os testes realizados são simulando um Samsung Galaxy S8 com 4x CPU slowdown pelo DevTools.&lt;/p&gt;

&lt;p&gt;O código do exemplo pode ser encontrado &lt;a href="https://github.com/MichelAraujo/lab/tree/master/nextjs-setup/my-app"&gt;aqui&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  O exemplo
&lt;/h4&gt;

&lt;p&gt;Na nossa página de exemplo temos um botão de click que mostra uma imagem de gato (claro!) e por baixo dos panos é executado algumas outras tasks JS que no mundo real pode ser comparada com acesso a uma API, processar alguma regra de negócio, envia uma tag de Analytics e etc.&lt;br&gt;
Inicialmente ao clicar no botão de “So Something” temos um INP de 2 a 3 segundos!!&lt;br&gt;
Lembrando que o ideal segundo a documentação do Google é ficar abaixo de 200 ms.&lt;/p&gt;

&lt;p&gt;Exemplo em video:&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/XjzVTH-vsl4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Beleza.. Sabemos que temos um problema, agora vamos começar a entender a causa e como resolver. Para mostrar no console os MS de cada interação na página igual mostrado no vídeo estamos usando esse código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(()=&amp;gt;{let o=globalThis;return void 0===o.winp&amp;amp;&amp;amp;(o.winp=0,new PerformanceObserver(n=&amp;gt;{for(let e of n.getEntries()){if(!e.interactionId)continue;o.winp=Math.max(e.duration,o.winp);let r=o=&amp;gt;o&amp;lt;=200?"color: green":o&amp;lt;=500?"color: yellow":"color: red";console.log(`%c[Interaction: ${e.name.padEnd(12)}] %cDuration: %c${e.duration}`,"color: grey; font-family: Consolas,monospace","",r(e.duration))}}).observe({type:"event",durationThreshold:0,buffered:!0})),o.winp})();


performance.interactionCount;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basta colar no console do navegador e começar a interagir na página, esse código mostra os MS de cada interação e seu tipo (click, keyup e etc).&lt;/p&gt;

&lt;p&gt;Sabendo de tudo isso a primeira coisa que vamos fazer é gravar essas interações usando a aba de performance do DevTools, no momento temos o seguinte resultado:&lt;br&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%2Fvr525qv7cqiyb8akt1on.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%2Fvr525qv7cqiyb8akt1on.png" alt="Image description" width="800" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cada coluna desta é uma task JS que foi disparada pela iteração feita no botão, se observarmos com atenção podemos ver que cada task JS desta está relacionada a um evento de click, se passar o mouse em cima da task vamos ver o tempo que a mesma levou para executar, vale lembrar que esse é o tempo que o event loop fica preso executando essa task até poder fazer outra coisa como entrar no passo de render (pintar algo na tela). Um pouco mais acima temos a parte das interações “Interactions” essa parte mostra o tempo que uma interação demorou desde do seu início até seu fim e quais task JS afetou essa interação ou seja, por aqui também podemos medir o tempo do INP e de quebra entender quais tasks são responsáveis pelo delay na interação, veja esse exemplo, essa interação demorou 2.55 segundos (tempo do INP).&lt;br&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%2Ftpm12jd599acz8a27fga.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%2Ftpm12jd599acz8a27fga.png" alt="Image description" width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nesse exemplo, olhando para esse relatório gravado pelo DevTools já dá para saber que apenas uma task JS está bloqueando toda a main thread, mas o que ela faz? &lt;br&gt;
Olhando com mais atenção a Call Tree podemos ver que lá no final temos uma função de onClick sendo executada e depois 3 tasks grandes de uns 900 ms cada sendo executadas de forma sequencial (indício de problema).&lt;br&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%2Fjcy2gq6ykjltvxidww1l.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%2Fjcy2gq6ykjltvxidww1l.png" alt="Image description" width="492" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Obs&lt;/strong&gt; o INP é calculado no próximo render do browser que na gravação do DevTools é a parte verde que geralmente é o “Paint” ou “Commit” que significa que o browser renderizou algo na tela, no nosso exemplo se dermos um zoom nessa gravação podemos achar o Commit lá depois de toda essa task grande JS ser executada, esse é um problema de fato para o INP&lt;br&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%2Fa8hk4abgoof06bildqum.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%2Fa8hk4abgoof06bildqum.png" alt="Image description" width="800" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se você tiver acesso ao código fonte da aplicação que estiver analisando e se for em frameworks como o Next JS geralmente tem como você executar em modo de desenvolvimento, fazendo essa mesma gravação no DevTools em mode de desenvolvimento pode ser que fique mais claro o nome de cada função que está sendo executada e facilite na hora de achar o problema, veja a próxima imagem, vale lembrar também que testando a aplicação em modo de desenvolvimento pode ser que a performance fique pior ainda e o resultado mais distante de produção.&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%2Fswqveq8a230fzm9b9npd.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%2Fswqveq8a230fzm9b9npd.png" alt="Image description" width="728" height="242"&gt;&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%2F7ss9984ec0wd73glisey.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%2F7ss9984ec0wd73glisey.png" alt="Image description" width="520" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O que sabemos até agora..&lt;br&gt;
Tem uma função de onClick que realiza 3 tarefas pesadas dentro dela e compromete o next paint do browser consequentemente o INP.&lt;br&gt;
Olhando para o código da nossa função temos isso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const doSomething = () =&amp;gt; {
    const rTask1 = task1();
    const rTask2 = task2();
    const rTask3 = task3();

    // Change state
    setShowImage(!showImage);
  };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;A função doSomething é a nossa função de handler do click e de cara podemos ver as 3 funções que estão sendo chamadas de forma sequencial seguido de um setState.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tendo esse pequeno código em mente vou da a principal dica para melhorar o INP:&lt;br&gt;
&lt;strong&gt;Sempre priorize o render (o feedback para o usuário) depois de alguma interação.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Todas as técnicas mostradas a seguir foram pensadas seguindo essa dica.&lt;/p&gt;
&lt;h3&gt;
  
  
  A técnica do yielding
&lt;/h3&gt;

&lt;p&gt;A primeira vez que eu vi essa técnica foi lento &lt;a href="https://web.dev/articles/optimize-long-tasks"&gt;esse post&lt;/a&gt; que por sinal recomendo muito.&lt;br&gt;
Tentando explicar de forma resumida, essa técnica consiste em quebrar task JS grandes em menores, se lembrarmos um pouco de como o browser funciona o pipeline de render é executado pelo event loop entre a execução de task JS, o event loop pode executar centenas de task JS antes de decidir fazer um render, quebrando tasks grandes em menores podemos dizer então que estamos dando mais oportunidade para o browser fazer o render de algo na tela, lembrando da dica de sempre priorizar o render já dá para perceber como essa técnica ajuda, &lt;strong&gt;vamos ter tasks menores e o browser pode fazer o render mais vezes.&lt;/strong&gt;&lt;br&gt;
Para implementar essa técnica basta apenas criar uma função assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function yieldToMain () {
  return new Promise(resolve =&amp;gt; {
    setTimeout(resolve, 0);
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E chamar ela onde você tem oportunidade de quebrar a task em execuções menores.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Para maiores informações sobre essa técnica vale dá uma olhada &lt;a href="https://web.dev/articles/optimize-long-tasks"&gt;aqui&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A primeira alteração que vamos fazer no código então é a seguinte, vamos chamar a função de yieldToMain() depois de cada task que temos na função doSomething, o código ficou assim:&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%2F35us5xm2lir5cwc6mju3.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%2F35us5xm2lir5cwc6mju3.png" alt="Codigo de exemplo usando yielding" width="582" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Gravando novamente as interações já dá para notar que não temos mais aquela task gigante mas sim apenas 3 task grande =D e monitorando as interações da para perceber uma pequena melhoria o que antes estava em torno de 3 segundos agora foi para 1 segundo, ainda é muito ruim mas vamos continuar as alterações…&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%2F0ypxjv5w16d8h0d6kme7.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%2F0ypxjv5w16d8h0d6kme7.png" alt="Image monstrando a gravação depois de usar Yielding" width="800" height="348"&gt;&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%2Ftworaknvhdyohq2fzqeo.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%2Ftworaknvhdyohq2fzqeo.png" alt="Image monstrando o resultado do INP depois de usar Yielding" width="800" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Continuando as melhorias pensando na dica de sempre priorizar o render vamos supor que essas 3 taks sejam coisas de background e o setState não precise esperar o retorno dessas função para ser executado então podemos priorizar totalmente o setState, o código fica assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const doSomething = async () =&amp;gt; {
    //Change state
    setShowImage(!showImage);

    await yieldToMain();

    const rTask1 = task1();
    await yieldToMain();

    const rTask2 = task2();
    await yieldToMain();

    const rTask3 = task3();                                                                                             });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fazendo isso podemos ver mais alguma melhora no resultado dos testes, olhando novamente o resultado das interações e as gravações temos o seguinte resultado:&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%2F07nzaj0p2kb0if64rc5g.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%2F07nzaj0p2kb0if64rc5g.png" alt="Image que mostra o resultado após priorizar o setState" width="476" height="287"&gt;&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%2Flwth4l5hrrq5o8j1w5vq.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%2Flwth4l5hrrq5o8j1w5vq.png" alt="Image que mostra o resultado do INP após priorizar o setState" width="577" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Aqui vem um pouco muito importante, mesmo com esse resultado bom para o INP não quer dizer que já temos a melhor UX, o browser aqui pode ter considerado o change do botão, borda, pequena mudança de cor na hora do click mas a imagem em si que queremos mostrar ainda vai ter o delay de algum tempo, temos que ficar espertos com isso se nosso objetivo é melhorar a UX como um todo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;O ponto chave dessa alteração é esse&lt;/strong&gt;&lt;br&gt;
Agora temos uma task menor que provavelmente já está processando o setState (linha verde no report gravado, próxima imagem) depois tem uma quebra com o yieldToMain que foi acrescentado depois do setState no código (repare no código acima) dando oportunidade para o browser fazer o render (seta vermelha na imagem).&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%2Fup67j1wypjhzb5esuux9.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%2Fup67j1wypjhzb5esuux9.png" alt="Image com setas monstrando os detalhes das alterações" width="800" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para esse caso as interações já estariam aprovadas &amp;lt; 200 ms, mas como no mundo real nem tudo são flores ainda temos alguns casos que podem degradar nosso INP. O primeiro deles é se nosso render (setState) depender do retorno de alguma função dessa, nesse cenário a solução é até simples, podemos colocar um loading para fazer o browser executar o next render depois de uma interação o mais rápido possível dando o feedback para o usuário de que algo está sendo processado, fazendo essa modificação no nosso código fica assim:&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%2Fspxlfshqw5sildy7lkqq.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%2Fspxlfshqw5sildy7lkqq.png" alt="Image do codigo alterado" width="800" height="437"&gt;&lt;/a&gt;&lt;br&gt;
Nesse caso teoricamente não é para ter grandes modificações nas medições de performance, tudo é para continuar verde.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note que o setState que faz a alteração da imagem de fato voltou para depois que as task são executadas.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Resultado em video:&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/lI3wAWCLUaw"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Cenario do usuarios impacientes
&lt;/h3&gt;

&lt;p&gt;Novamente o mundo real é mais cruel do que a gente testando em laboratório, vamos supor que nossos usuários são impacientes e ficam clicando no botão antes que de tempo das task JS realmente terminar de fato, nesse cenário ainda vamos ter um problema de INP sério, veja a reprodução desse cenário:&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/2ECwb4DlfpY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nesse vídeo estou clicando no botão de doSomething várias vezes&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Lembrando que não foi feita mais nem uma alteração de código depois dos últimos testes o que mudou apenas foi o comportamento do usuário (nesse caso a forma que estamos testando)&lt;/p&gt;

&lt;p&gt;Nesse cenário o que está acontecendo é a próxima interação que é feita está iniciando enquanto o browser ainda não terminou de processar umas das task grandes, podemos ver isso na gravação:&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%2Fdittdqi1dv95w3rhd8gk.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%2Fdittdqi1dv95w3rhd8gk.png" alt="Iniciando uma interação sem concluir uma task" width="800" height="185"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Perceba as interações iniciando no meio da task.&lt;/p&gt;

&lt;h3&gt;
  
  
  PAUSA NOS CENÁRIOS - Entendendo um pouco mais do INP
&lt;/h3&gt;

&lt;p&gt;Para o cálculo do valor total do INP é considerado 3 sub métricas que são:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input Delay&lt;/li&gt;
&lt;li&gt;Processing time&lt;/li&gt;
&lt;li&gt;Presentation delay&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Juntando o valor em MS dessas 3 sub métricas temos o valor total do INP, exemplo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input Delay - 30 ms&lt;/li&gt;
&lt;li&gt;Processing time - 50 ms&lt;/li&gt;
&lt;li&gt;Presentation delay - 10 ms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Valor do INP é de 90 MS&lt;/p&gt;

&lt;p&gt;Prestar atenção nessas sub métricas pode nos ajudar a identificar onde está o gargalo de algum ponto.&lt;/p&gt;

&lt;h3&gt;
  
  
  Voltando para o exemplo..
&lt;/h3&gt;

&lt;p&gt;Podemos ver que o que mais está demorando é o presentation delay ou seja, a task está pronto para o browser renderizar mas o browser estava ocupado executando as outras task e levou 721 ms até achar um tempo para renderizar.&lt;br&gt;
Em outras casos é o input delay que demora mais ou seja o browser está ocupado processando alguma task que não conseguiu nem iniciar a nova task referente a interação, &lt;strong&gt;por todos esses motivos que é importante ter em mente sempre tentar ter tasks JS menores possível.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Para melhorar esse cenário podemos fazer algumas alterações no código e usar algumas outras técnicas como o requestAnimatedFrame para sinalizar para o browser que no próximo frame teremos alguma renderização na tela e que aquela task JS vai ter alguma renderização.&lt;br&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame"&gt;doc&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Podemos também deixar as task async para as mesmas serem executadas em paralelo reduzindo o tempo total de processamento e evitando o “choque” de entrar uma nova task de interação enquanto ainda tem coisa processando.&lt;/p&gt;

&lt;p&gt;Com todas essas alterações chegamos na melhor otimização possível até o momento, o código ficou assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const doSomething = async () =&amp;gt; {
    // Show loading
    window.requestAnimationFrame(() =&amp;gt; {
      setPageState({ ...pageState, loading: true });
    });
    await yieldToMain();

    const promiseTask1 = task1();
    const promiseTask2 = task2();
    const promiseTask3 = task3();

    await promiseTask1;
    await yieldToMain();

    await promiseTask2;
    await yieldToMain();

    await promiseTask3;
    await yieldToMain();

    // Hide loading and show image
    window.requestAnimationFrame(() =&amp;gt; {
      setPageState({ showImage: !pageState.showImage, loading: false });
    });
  };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Execução ficou assim:&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%2Fpnsklsoud2r36nky5uhl.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%2Fpnsklsoud2r36nky5uhl.png" alt="Teste com todas as interações" width="773" height="590"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A imagem acima foi feita simulando todos os cenários de um simples clique e de ficar clicando múltiplas vezes, sendo assim podemos observar que apesar de termos uma boa melhora do início do post que a média ficava em torno de 2 a 3 segundo ainda temos alguns gargalos para melhorar.&lt;br&gt;
Até o momento a gente só trabalhou no gerenciamento das tasks e ajudando o browser a entender que algo deve ser renderizado na tela, as funções que estão lenta de propósito até o momento ainda continuam lentas (não foram alteradas), o objetivo até aqui foi mostrar que mesmo que temos funções difíceis de otimizar apenas gerenciando bem as task podemos conseguir melhorar consideravelmente a média do INP mas para melhorar de fato temos que foca em sempre fazer as tasks menores possíveis, para exemplificar isso vamos mexer agora nas tasks de exemplos que estavam lenta de propósito (task1, task2, task3), vamos criar um novo cenário em que temos mais tasks porém com tempo de execução menor, o código vai fica assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const doSomething = async () =&amp;gt; {
    window.requestAnimationFrame(() =&amp;gt; {
      setPageState({ ...pageState, loading: true });
    });

    const tasks = [];

    for (let i = 0; i &amp;lt; 10; i++) {
      const rTaskPromise = task1();
      tasks.push(rTaskPromise);
      await yieldToMain();
    }

    await Promise.all(tasks);

    window.requestAnimationFrame(() =&amp;gt; {
      setPageState({ showImage: !pageState.showImage, loading: false });
    });
  };

  const manageImage = () =&amp;gt; {
    if (pageState.showImage) {
      return &amp;lt;img
        src="http://localhost:3000/cat_img.webp"
        width={612}
        height={408}
        alt="Image of the a Cat"
        decoding="async"
      /&amp;gt;
    }

    if (pageState.loading) {
      return &amp;lt;img
        src="http://localhost:3000/loading.webp"
        width={300}
        height={300}
        alt="Image of the loading"
        decoding="async"
      /&amp;gt;
    }
  };

  return (
    &amp;lt;&amp;gt;
      &amp;lt;button onClick={doSomething} title="Show or hide image button"&amp;gt;Do Something&amp;lt;/button&amp;gt;
      &amp;lt;br /&amp;gt;
      {manageImage()}
    &amp;lt;/&amp;gt;
  );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Coloquei o código mais completo dessa vez para vocês terem uma noção do que está acontecendo no render também.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;O resultado do report ficou assim:&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%2F4yfi6k1tq6qvr8wvmsl7.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%2F4yfi6k1tq6qvr8wvmsl7.png" alt="Image of the DevTools performance report" width="800" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Com esse report podemos observar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O INP foi super rápido, ficou nos 29 ms ou seja está verde.&lt;/li&gt;
&lt;li&gt;O loading está sendo mostrado o mais rápido possível.&lt;/li&gt;
&lt;li&gt;Agora temos várias tasks pequenas (simulando a quebra daquelas task grande que teríamos antes), assim se o browser precisar tem mais oportunidade para fazer um render no meio dessas tasks.&lt;/li&gt;
&lt;li&gt;Por fim temos o render da imagem em si.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se a gente simular um cenário de stress agora (vários clicks seguidos) vamos observar que tem bem menos engasgo do que antes, isso é onde as tasks menores ajudam!&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%2F9n78k3sk8phcckamzhr6.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%2F9n78k3sk8phcckamzhr6.png" alt="Resultado do teste com varios clicks" width="734" height="690"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Bônus - mostrar e sumir com um elemento
&lt;/h3&gt;

&lt;p&gt;Minha ideia era parar o post por aqui, mas fazendo esses testes com esse exemplo simples apareceu um cenário muito interessante que dependendo da sua funcionalidade pode surgir na vida real também.&lt;br&gt;
Se você já não reparou observe no último report que temos um step de commit que está tomando bastante tempo, isso pode ser um problema principalmente para o cenário de stress, como em task JS uma nova interação pode surgir e o browser está executando essa task de commit longa, exemplo:&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%2F3t55l2nfg4zvapzrzu9r.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%2F3t55l2nfg4zvapzrzu9r.png" alt="Long commit task" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como você já deve ter entendido isso é ruim para o INP.&lt;/p&gt;

&lt;p&gt;Nesse meu exemplo simples isso aconteceu pelo modo que estou fazendo o elemento de imagem (tag img) ser removida e incluída no DOM toda hora que interagimos com o botão, isso força o browser fazer todo o processo de layout, paint, render em toda interação, para melhorar isso em vez de ficar adicionando e removendo o elemento do DOM vou trabalhar com opacidade e animação, assim o browser só vai executar os passos realmente necessários para a animação mas o elemento em si vai continuar na árvore do DOM e Layout, vamos ver como fica:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/_j-A8vhtb3o"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;O report agora ficou assim, podemos notar que não tem mais aquela task de commit grande, tudo parece fluir muito melhor agora com todas tasks pequenas!&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%2F78gmflimqshsxjwotjee.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%2F78gmflimqshsxjwotjee.png" alt="Report final with animation" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Espero que algumas dessas dicas ajude alguém nas suas otimizações na vida real, a ideia do post foi realmente passar o contexto e ajudar nos primeiros passos dessa jornada de otimização, como prática faça seus próprios testes, tente criar exemplo usando as dicas desse post, depois pode comentar se o resultado foi parecido com os dos meus teste.&lt;br&gt;
Acredito que nos próximos meses/ano vai ter muito mais coisa boa vindo ai que pode ajudar ainda mais, muita feature nova nos browser que hoje só funciona no Chrome (por isso nem citei aqui), WebAPIs que vão ajudar a usar menos JS na página e etc.&lt;/p&gt;

&lt;p&gt;O código completo deste exemplo vai está nesse &lt;a href="https://github.com/MichelAraujo/lab/tree/master/nextjs-setup/my-app"&gt;github&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>performance</category>
      <category>webperf</category>
    </item>
    <item>
      <title>Como debugar nossas aplicações em NodeJS com mais eficiência!</title>
      <dc:creator>Michel Araujo</dc:creator>
      <pubDate>Sat, 01 Aug 2020 15:59:20 +0000</pubDate>
      <link>https://forem.com/michelaraujo/como-debugar-nossas-aplicacoes-em-nodejs-com-mais-eficiencia-1hb3</link>
      <guid>https://forem.com/michelaraujo/como-debugar-nossas-aplicacoes-em-nodejs-com-mais-eficiencia-1hb3</guid>
      <description>&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%2Fi%2F4zob11h20c3mwc4syg87.jpg" 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%2Fi%2F4zob11h20c3mwc4syg87.jpg" alt="Intro image post" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Neste post vou falar um pouco de como podemos usar o Chrome Devtools para debugar nossas aplicações em NodeJS e como podemos usar os logs a o nosso favor.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;O que vamos abordar neste post:&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fazendo debug de aplicações em NodeJS usando o Chrome Devtools&lt;/li&gt;
&lt;li&gt;Agora vamos falar um pouco sobre Logs!&lt;/li&gt;
&lt;li&gt;Lembrando de funções básicas de log&lt;/li&gt;
&lt;li&gt;Boas ferramentas!&lt;/li&gt;
&lt;li&gt;Dicas&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Fazendo debug de aplicações em NodeJS usando o Chrome Devtools&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A partir da versão 6.3.0 do NodeJS temos disponível a flag — inspect que disponibiliza para nós uma porta específica para debug via conexão socket, isso possibilita que nossas aplicações em NodeJS sejam analisadas usando o Chrome Devtools e todos seus recursos mais legais. Para saber mais sobre esse protocolo e como podemos usar ele não só com o Chrome Devtools sugiro que leiam o documento &lt;a href="https://chromedevtools.github.io/debugger-protocol-viewer/v8/"&gt;Chrome Debugging Protocol Viewer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Vamos da uma olhada como isso funciona de uma forma simples com alguns exemplos.&lt;/p&gt;

&lt;p&gt;O código a seguir simplesmente calcula quantos anos você estaria a 10 anos atrás e quantos anos você vai estar daqui a 10 anos.&lt;/p&gt;

&lt;p&gt;O código está separado em 3 arquivos, future.js, past.js e index.js, segue a baixo:&lt;/p&gt;

&lt;p&gt;future.js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const future = (age, gap) =&amp;gt; {
  return `In ${gap} years you will be ${Number(age)+gap}&amp;lt;br/&amp;gt;`;
}

module.exports = future;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;past.js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const past = (age, gap) =&amp;gt; {
  return `${gap} years ago you were ${Number(age)-gap}&amp;lt;br/&amp;gt;`;
};

module.exports = past;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;index.js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const past = require('./past');
const future = require('./future');

const app = express();

app.get('/:age', (req, res) =&amp;gt; {
  res.send(past(req.params.age, 10) + future(req.params.age, 10));
});

app.listen(3000);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Executando esse app e acessando a url: &lt;a href="http://localhost:3000/30"&gt;http://localhost:3000/30&lt;/a&gt; temos o seguinte resultado:&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%2Fi%2F1pxw60tb26hvbfw2ohci.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%2Fi%2F1pxw60tb26hvbfw2ohci.png" alt="Imagem do resultado localhost no browser" width="657" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Podemos ver que a um resultado não esperado “NaN”, vamos usar o Chrome Devtools para tentar achar o problema. Para fazermos isso temos que iniciar nosso app com a flag — inspect ficando assim:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ node — inspect index.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Podemos notar que na saída do console vamos ter algo parecido com:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Debugger listening on ws://127.0.0.1:9229/60b72ae3–68ce-4123-bab4-cf8d2e180df6
For help, see: https://nodejs.org/en/docs/inspector
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso quer dizer que nosso debug está funcionando e pronto para ser conectado a um cliente via socket com essa url:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ws://127.0.0.1:9229/60b72ae3–68ce-4123-bab4-cf8d2e180df6&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Para se conectar a ele vamos abrir uma nova aba do Chrome e digitar o seguinte endereço: "chrome://inspect", se tudo der certo já podemos ver que o Devtools encontrou nosso app.&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%2Fi%2F58yol2qafxfk6j5df9a3.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%2Fi%2F58yol2qafxfk6j5df9a3.png" alt="Pagina do chrome://inspect" width="700" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para iniciar nosso Devtools vamos clicar em “Open dedicated DevTools for Node” e então podemos ver nosso Devtools aberto:&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%2Fi%2Flpi8bxtpkbsm5kxabq2o.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%2Fi%2Flpi8bxtpkbsm5kxabq2o.png" alt="Alt Text" width="700" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vamos focar agora em descobrir o que está de errado no nosso app que está retornando o valor “NaN”, de início vamos colocar um breakpoint na linha 8 e fazer um novo request para nosso app na url "&lt;a href="http://localhost:3000/30"&gt;http://localhost:3000/30&lt;/a&gt;", no navegador a página deve se manter esperando pelo nosso server já que temos um breakpoint interrompendo a continuidade da execução, no nosso devtools podemos ver que a linha com o breakpoint ficou destacada:&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%2Fi%2F1ewx7x5xz4fll4xt6fjc.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%2Fi%2F1ewx7x5xz4fll4xt6fjc.png" alt="Alt Text" width="700" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Podemos notar algumas coisas interessantes aqui, uma delas é que se passamos o mouse sobre a variável req.params podemos ver os valores que estão chegando na nossa request, com base nisso já podemos descobrir a causa no nosso problema mas vamos continuar dando uma olhada.. Na coluna à direita podemos ver toda call stack que foi chamada até o momento, e no início da coluna temos alguns controles que podem ser muito úteis no nosso debug, vamos clicar no terceiro botão de controle para seguir um passo à frente na execução do nosso programa.&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%2Fi%2Ffqdxnt09ukvafn83fwip.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%2Fi%2Ffqdxnt09ukvafn83fwip.png" alt="Botões de controle do Chrome DevTools" width="261" height="43"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feito isso vamos entrar no próximo passo da execução do nosso programa que nesse caso é a função past como podemos ver na imagem a seguir:&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%2Fi%2F7g4neofnbqiu6zgndsc7.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%2Fi%2F7g4neofnbqiu6zgndsc7.png" alt="Alt Text" width="700" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Passando o mouse sobre as variáveis/parâmetros podemos conferir se todos os valores estão chegando corretamente, uma outra forma de ver isso é olhando na coluna à direita em baixo da Call Stack temos uma parte chamada Scope -&amp;gt; Local aí podemos ver todas as variáveis do escopo local no momento e seus respectivos valores, veja a imagem abaixo:&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%2Fi%2Fyokxyffqrqme5p44ye5n.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%2Fi%2Fyokxyffqrqme5p44ye5n.png" alt="Alt Text" width="275" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Certo, conferindo que aqui está tudo ok vamos voltar para a função principal no arquivo index clicando no quarto botão de controle (setinha para cima).&lt;/p&gt;

&lt;p&gt;Voltando para o arquivo index podemos notar que a função future na linha 8 agora está destacada, isso quer dizer que ela será a próxima na execução, então se a gente clicar no terceiro botão de controle novamente indo para a próxima execução do nosso programa vamos cair no arquivo future.js na função future como mostrado na imagem abaixo:&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%2Fi%2Fkfn99ak9chmy11kjoat5.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%2Fi%2Fkfn99ak9chmy11kjoat5.png" alt="Alt Text" width="700" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Passando o mouse pelas variáveis/parâmetros podemos notar que o parâmetro age está com o valor undefined (podemos ver também no Scope -&amp;gt; Local na coluna a direita), ou seja ele está recebendo um valor undefined mas o problema não está nesta função, vamos voltar novamente para função principal no arquivo index.js clicando no quarto botão de controle (setinha para cima).&lt;/p&gt;

&lt;p&gt;No arquivo index.js passando o mouse pelo parâmetro que é passado para a função future podemos notar que realmente está undefined e se observarmos com mais atenção podemos ver que está errada por não existir o parâmetro future req.params.future o correto seria req.params.age, podemos editar isso direto no devtools ou na sua IDE de preferência. Fazendo essa correção vamos remover o breakpoint e clicar no botão azul (primeiro botão de controle) para dar continuidade na execução do nosso programa. Feito isso podemos notar que no navegador os valores já vão estar corretos. Pronto! Problema resolvido.&lt;/p&gt;

&lt;p&gt;O exemplo mostrado aqui é bem simples mas existem diversos outros recursos no Devtools que pode nos ajudar a debugar nossa aplicação de uma forma bem completa como o uso de memória e cpu, como descobrir gargalos de memória, como podemos aproveitar a Call Stack para entender como nossa aplicação está funcionando e etc.&lt;/p&gt;

&lt;p&gt;Para um exemplo mais aprofundado pode da uma olhada nesse post &lt;a href="https://marmelab.com/blog/2018/04/03/how-to-track-and-fix-memory-leak-with-nodejs.html"&gt;Finding And Fixing Node.js Memory Leaks: A Practical Guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Podemos usar esse recurso do — inspect para debugar aplicações que estão rodando em container também, para saber mais sugiro dar uma olhada nesse post &lt;a href="https://blog.risingstack.com/how-to-debug-a-node-js-app-in-a-docker-container/"&gt;How to Debug a Node.js app in a Docker Container&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Podemos também usar esse recurso em produção mas isso é extremamente perigoso já que abre uma porta direto com sua aplicação e todo seu contexto, se realmente for necessario usar isso em produção sugiro que siga essa recomendação &lt;a href="https://nodejs.org/en/docs/guides/debugging-getting-started/#enabling-remote-debugging-scenarios"&gt;Node Doc, remote debugging scenarios&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Algumas curiosidades de como tudo isso funciona&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Tudo isso é possível graças a engine JavaScript V8, quando executamos o node com a flag — inspect a engine V8 abre uma porta que aceita conexão WebSocket, uma vez que a conexão é feita comandos em formato de pacotes JSON são enviados entre o Inspector e o cliente.&lt;/li&gt;
&lt;li&gt;O Inspector WebSocket é escrito em C e roda em uma thread separada assim quando o processo é pausado (breakpoint) o inspector continua funcionando.&lt;/li&gt;
&lt;li&gt;Quando um breakpoint é colocado o event loop é pausado e toda informação (Call Stack, Variáveis) daquele momento são enviadas para o cliente, cada interação com os botões de controle é despausado o event loop e pausado novamente atualizando essas informações no cliente.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Agora vamos falar um pouco sobre Logs!&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Logs no STDOUT&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Quando estamos executando nosso programa e algo dá errado um log de erro é mostrado no nosso STDOUT como esse:&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%2Fi%2Fh9q0vz3fj7l4u8td15k6.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%2Fi%2Fh9q0vz3fj7l4u8td15k6.png" alt="Exemplo saida STDOUT de erro" width="700" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mas se precisamos ver um trace maior do que é mostrada por padrão? Para isso podemos usar a flag -stack-trace-limit=21 para alterar o limite de trace da saída para um valor que for melhor para nós, exemplo:&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%2Fi%2Fxeqqlsmosn1de54uxdr7.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%2Fi%2Fxeqqlsmosn1de54uxdr7.png" alt="Exemplo saida STDOUT de erro" width="700" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Uso da env DEBUG&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Outro recurso legal que podemos aproveitar é usar o máximo o debug do node, por exemplo, podemos habilitar o debug do node para nos mostrar todo log de execução que está acontecendo no express, para isso vamos executar o node com a flag DEBUG=express:*.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DEBUG=express:* node index.js&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%2Fi%2F7rylcwhl0s2oa2emut8t.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%2Fi%2F7rylcwhl0s2oa2emut8t.png" alt="Exemplo debug em nodejs" width="700" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como a imagem acima nos mostra essas informações podem ser úteis para uma investigação mais aprofundada do que está acontecendo na aplicação.&lt;/p&gt;

&lt;p&gt;Se eu quiser saber o log só do express router por exemplo:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DEBUG=express:router node index.js&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%2Fi%2Fpask66kxk8pmemnjbgp7.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%2Fi%2Fpask66kxk8pmemnjbgp7.png" alt="Exemplo debug em nodejs" width="700" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para mostra tudo: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;DEBUG=* node index.js&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Lembrando de funções básicas de log&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;console.log(arguments): printa algo na saída padrão&lt;/li&gt;
&lt;li&gt;console.error(arguments): printa algo na saída de erro&lt;/li&gt;
&lt;li&gt;console.trace(label): printa um trace da execução&lt;/li&gt;
&lt;li&gt;console.time(label) / console.timeEnd(label): essa combinação pode ser usada para mostrar o tempo de execução de uma parte do código.&lt;/li&gt;
&lt;li&gt;console.dir(object): printa a estrutura de um objeto na saída padrão&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para aproveitar a o máximo todo o poder que os logs podem fornecer nos momentos em que mais precisamos não podemos deixar de lado os bons padrões para se ter em um log, já existem vários desses padrões muito bem definidos na comunidade e um que recomendo a análise é a do &lt;a href="https://12factor.net/logs"&gt;Twelve-Factor App Logs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Dicas&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Não se esqueça dos testes&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Os testes podem ajudar a ampliar o entendimento da sua aplicação facilitando assim achar o motivo de um possível bug, lembre sempre de olhar seus testes em um processo de debug e melhorar ainda escrever o teste para a caso em questão ajudando assim que o mesmo problema não retornar futuramente.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Aproveite a evn NODE_DEBUG em seu localhost&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Você pode usar essa env para um “scan” do que está acontecendo na sua aplicação em tempo de execução separadamente por módulos do node por exemplo, module, http e etc.&lt;br&gt;
Para mais informações: &lt;a href="https://nodejs.org/api/cli.html#cli_node_debug_module"&gt;node_debug&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Tome cuidado com a forma que você está fazendo seus logs&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Para finalizar gostaria de recomendar uma palestra que mostra o impacto em desempenho que os logs podem ter na sua aplicação em especial quando usamos alguma lib de log, &lt;a href="https://vimeo.com/180476148"&gt;Node Summit 2016 — The Cost of Logging&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Boas ferramentas!&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;stackup:&lt;/strong&gt; É um módulo do npm que enriquece as informações de erro quando algo dá errado, ele é bem útil principalmente quando algo dá erro em chamada async.
Saiba mais em: &lt;a href="https://www.npmjs.com/package/stackup"&gt;https://www.npmjs.com/package/stackup&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Bom espero que esse post possa te auxiliar em fazer cada vez mais debugs de forma eficiente ajudando a solucionar os problema que nos deparamos no dia a dia sem bater muita a cabeça.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Fonts:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/PacktPublishing/Node-Cookbook-3rd-Ed"&gt;node cookbook 3rd edition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/othiym23/bug-clinic"&gt;Nodeschool bug-clinic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@paul_irish/debugging-node-js-nightlies-with-chrome-devtools-7c4a1b95ae27"&gt;Debugging Node.js with Chrome DevTools&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Stay hungry Stay foolish!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>debug</category>
      <category>devtools</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Conheça um pouco mais sobre o sistema de módulos em Node.JS e NPM</title>
      <dc:creator>Michel Araujo</dc:creator>
      <pubDate>Sat, 25 Jul 2020 15:41:41 +0000</pubDate>
      <link>https://forem.com/michelaraujo/conheca-um-pouco-mais-sobre-o-sistema-de-modulos-em-node-js-e-npm-31gk</link>
      <guid>https://forem.com/michelaraujo/conheca-um-pouco-mais-sobre-o-sistema-de-modulos-em-node-js-e-npm-31gk</guid>
      <description>&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%2Fi%2Fuup2tyz6f55kffru01jn.jpg" 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%2Fi%2Fuup2tyz6f55kffru01jn.jpg" alt="Imagem intro do post Conheça um pouco mais sobre o sistema de módulos em Node.JS e NPM" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O objetivo desse post é mostrar de uma maneira objetiva como algumas coisas funcionam no sistema de módulos do Node.JS e recursos que podem ser úteis no dia a dia.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;O que vamos abordar neste artigo:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Começando do começo! (Comandos basicos do NPM)&lt;/li&gt;
&lt;li&gt;Está rodando NPM com sudo ? Saiba como ajustar isso.&lt;/li&gt;
&lt;li&gt;Como funciona a versão dos módulos&lt;/li&gt;
&lt;li&gt;Para que serve o caracter “^” ?&lt;/li&gt;
&lt;li&gt;Como funciona exports e require em NodeJS&lt;/li&gt;
&lt;li&gt;NPM Scripts&lt;/li&gt;
&lt;li&gt;Como configurar um registry Scope&lt;/li&gt;
&lt;li&gt;Boas ferramentas!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Começando do começo!&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Vamos apresentar aqui algumas configurações básicas do NPM.&lt;br&gt;
O comando “npm config” pode ser usado para alterar as configurações do seu npm permanentemente, por exemplo para configurar um nome de autor podemos usar o seguinte comando:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm config set init.author.name "&amp;lt;name here&amp;gt;"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Obs: Esse nome de autor será usado quando executamos o comando “npm init”&lt;/p&gt;

&lt;p&gt;Você pode listar todas as configurações atuais que você fez usando o comando “npm config ls” ou visualizar todas as configurações inclusive as que já vem por padrão com o comando “npm config ls -l”.&lt;/p&gt;

&lt;p&gt;Para visualizar a documentação completa das configurações do NPM acesse &lt;a href="https://docs.npmjs.com/misc/config"&gt;npm-config page&lt;/a&gt;, sabendo usar essas configurações ao nosso favor podemos aproveitar muito mais alguns recursos do NPM como cache, diferentes locais de instalação de dependências ou usar um registry customizado, ao longo deste post vamos ver mais a fundo algumas dessas config.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Comandos basicos do NPM&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;npm install : Baixa um módulo para o diretório node_modules sem salvar permanentemente, ou seja, se o diretório node_modules for deletado no próximo npm install essa módulo não será baixado.&lt;/li&gt;
&lt;li&gt;npm install --save : Baixa um módulo no diretório node_modules e registra a versão baixada no arquivo package.json assim no próximo npm install o módulo será baixado novamente, atualiza o package-lock quando há alguma atualização de versão.&lt;/li&gt;
&lt;li&gt;npm install --save-dev : Baixa um módulo no diretório node_modules e registra no package.json como uma dependência de desenvolvimento.&lt;/li&gt;
&lt;li&gt;npm install --production: Baixa todas as dependências menos as que são instaladas com a flag --save-dev (dependências de desenvolvimento)&lt;/li&gt;
&lt;li&gt;npm ci: Baixa todas as dependência seguindo exatamente as versões que estão no arquivo package-lock não fazendo nem uma alteração no mesmo. &lt;/li&gt;
&lt;li&gt;npm ls: Vai retornar toda a árvore de dependência de produção e desenvolvimento, pode ser muito útil para achar sub-dependências ou dependências que não deveriam existir.&lt;/li&gt;
&lt;li&gt;npm audit: Faz uma varredura nas suas dependências procurando por versões que podem possuir algum tipo de vulnerabilidade, no final retorna um relatório com cada descoberta e sua criticidade.&lt;/li&gt;
&lt;li&gt;npm outdated: Mostra todas as dependências que tem atualização disponível.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Está rodando NPM com sudo ? Saiba como ajustar isso.&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Você já se deparou com a necessidade de executar algum comando do npm com sudo ? Ou todos os comandos? Se sim isso acontece provavelmente porque o usuário que você está executando o comando não tem permissão para acessar o diretório que contém os módulos globais ou locais do npm.&lt;br&gt;
Existem algumas maneiras de ajustar isso, vou mostrar aqui a que eu mais gosto =).&lt;/p&gt;

&lt;p&gt;Primeiro vamos executar o comando “npm config get prefix”, com esse comando podemos ver onde estão sendo instalados nossos módulos, provavelmente estão dentro de /usr/local/.&lt;br&gt;
O que vamos fazer é trocar o local onde os módulos do npm são instalados criando um diretório para isso.&lt;br&gt;
Vamos criar um diretório na nossa pasta home:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir  ~/npm-global&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Depois vamos fazer com que nosso diretório central do npm seja esse que criamos usando o comando:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm config set prefix ~/npm-global&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Vamos precisar adicionar ao nosso PATH do sistema esse nosso diretório para conseguirmos chamar nossas libs pelo terminal sem problemas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export PATH=$PATH:~/npm-global/bin
source ~/.profile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pronto, para conferir se a configuração está ok você pode executar o comando “npm config get prefix” e visualizar se é o seu diretório que retorna.&lt;br&gt;
Se você já tiver algum projeto que esteja usando sudo para executar os comandos recomendo que remova o diretório node_modules e execute npm install novamente, assim tudo deverá funcionar sem sudo agora.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Como funciona a versão dos módulos&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Os módulos do npm segue um padrão de versionamento chamado SemVer (Semantic Versioning), esse padrão consiste basicamente de 3 números sendo eles MAJOR, MINOR e PATCH separados por ponto, ex: 2.3.14. (Como se pode notar o número de cada posição da versão corresponde a Major.Minor.Patch).&lt;/p&gt;

&lt;p&gt;PATCH: Está relacionado a qualquer alteração feita que não quebra a funcionalidade já existente e não adiciona uma funcionalidade nova, o melhor exemplo para isso é correção de bug.&lt;br&gt;
Vamos imaginar que temos um módulo na versão 1.0.0, fizemos uma correção de bug e adicionamos uma documentação, a próxima versão será 1.0.1.&lt;/p&gt;

&lt;p&gt;MINOR: Seu valor é aumentado quando adicionamos uma nova funcionalidade que não quebra as já existentes, mantendo a compatibilidade.&lt;br&gt;
Voltando a o nosso módulo de exemplo vamos imaginar que adicionamos uma nova função para retorna uma lista de produtos, não altera as já existentes apenas faz algo novo então a próxima versão do nosso módulo será 1.1.0.&lt;/p&gt;

&lt;p&gt;MAJOR: Está relacionado a qualquer alteração que tenha uma quebra de compatibilidade, por exemplo a alteração da interface de uma função, alteração no padrão de retorno de uma função já existente e etc.&lt;br&gt;
Voltando a o nosso módulo imaginário digamos que vamos alterar nossa função que retorna a lista de produtos trocando seu retorno de Array para Json, sendo assim a próxima versão do nosso módulo será 2.0.0.&lt;/p&gt;

&lt;p&gt;Observe que cada incremento na categoria maior reseta a menor, se fizemos um incremento no MINOR o PATCH é resetado, se fizemos um incremento no MAJOR, o MINOR e o PATCH é resetado.&lt;/p&gt;

&lt;p&gt;Se quiser entender um pouco mais a fundo sobre esse padrão de versionamento recomendo que leia &lt;a href="https://semver.org/"&gt;Semantic Versioning Web Page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Podemos fazer essas alterações de versão alterando diretamente nosso arquivo package.json ou usando os comando do npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm version patch // Incrementa o patch
npm version minor // Incrementa o minor
npm version major // Incrementa o major
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ou setar já tudo de uma vez com:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm version 2.0.0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Para ver a versão do seu módulo como também a do node, npm, v8 é só executar o comando:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm version&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Para que serve o caracter “^” ?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Quando executamos o comando “npm install --save ” por padrão a versão do módulo é adicionado a o nosso package.json com o caractere “^” na frente, ex: express": "^4.17.1".&lt;br&gt;
Esse caractere indica que qualquer alteração de PATCH que houver vai ser adicionada automaticamente, por exemplo vamos supor que foi feito um novo incremento no nível PATCH do express “4.17.2”, quando a gente executar o comando “npm install” novamente esse incremento já vai ser adicionado automaticamente. Segue a mesma regra para toda árvore de dependência, ou seja toda dependência e sub-dependência do express vai seguir essa mesma regra.&lt;br&gt;
Esse comportamento por padrão permite que nossa aplicação receba um bug fixes sem mesmo a gente saber, por outro lado isso requer um certo nível de confiança sobre o módulo que estamos consumindo, se você não quiser esse comportamento pode simplesmente editar manualmente o arquivo package.json removendo o caractere “^”.&lt;br&gt;
Ou se sua aplicação/módulo está em um nível estável e você quer garantir que nem uma alteração não conhecida de dependência seja feita, podemos desabilitar a atualização do arquivo package-lock.json, sendo assim todo “npm install” vai pegar as dependências com a versão fixada do package-lock que serve como um snapshot das dependências, sem fazer qualquer atualização de versão, para fazer isso é só executar o comando:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm config set package-lock false&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Obs: com essa configuração não vai ser gerado arquivo package-lock para novos projetos/módulos, fique atento com isso!&lt;/p&gt;

&lt;p&gt;Esse recurso pode ser muito útil se seu software passa por auditoria ou um processo mais rigoroso referente a atualização de dependência, com o snapshot do package-lock fica mais fácil controlar as versões e comprovar isso.&lt;/p&gt;

&lt;p&gt;Como podemos ver o package-lock.json funciona como um snapshot de dependências e sub-dependências, ele é nada mais que uma árvore contendo o registro de versões das dependências e das dependências das dependências que são usadas na sua aplicação/módulo, sugiro que você abra um arquivo package-lock.json e dê uma olhada com atenção isso pode clarear mais as coisas.&lt;br&gt;
Para mais informações &lt;a href="https://docs.npmjs.com/files/package-locks"&gt;Documentação npm package-lock.json&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Como funciona exports e require em NodeJS&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Inicialmente para deixar claro todo arquivo que contenha código JS é considerado um módulo no NodeJS, contendo variáveis, funções exportadas ou não.&lt;/p&gt;

&lt;p&gt;Quando fazemos alguma chamada (require) a um módulo em NodeJS o mesmo é encapsulado (wrapped) por uma função, essa função consiste em:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;( function (exports, require, module, __filename, __dirname) {
/* código do modulo aqui */
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como podemos ver essa função contém 5 parâmetros cada uma responsável por armazenar diferentes informações sobre o módulo que está sendo exportado.&lt;br&gt;
Para facilitar o entendimento de cada um desses parâmetros vamos criar um módulo teste chamado myModule.js e ver como isso funciona na prática.&lt;/p&gt;

&lt;p&gt;O código do nosso módulo inicialmente vai ser o seguinte:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;console.log('Exports =&amp;gt; ', exports);
console.log('Require =&amp;gt; ', require);
console.log('Module =&amp;gt; ', module);
console.log('Filename =&amp;gt; ', __filename);
console.log('Dirname =&amp;gt; ', __dirname);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quando executamos esse script (módulo) vamos ter o valor referente a cada parâmetro da função wrapped citada acima.&lt;br&gt;
Vamos executar o comando:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;node myModule.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;E o resultado será o seguinte:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Exports =&amp;gt;  {}
Require =&amp;gt;  [Function: require] {
  resolve: [Function: resolve] { paths: [Function: paths] },
  main: Module {
    id: '.',
    path: '/home/michel/Workspace/lab/examples_posts/modules_npm',
    exports: {},
    parent: null,
    filename: '/home/michel/Workspace/lab/examples_posts/modules_npm/myModule.js',
    loaded: false,
    children: [],
    paths: [
      '/home/michel/Workspace/lab/examples_posts/modules_npm/node_modules',
      '/home/michel/Workspace/lab/examples_posts/node_modules',
      '/home/michel/Workspace/lab/node_modules',
      '/home/michel/Workspace/node_modules',
      '/home/michel/node_modules',
      '/home/node_modules',
      '/node_modules'
    ]
  },
  extensions: [Object: null prototype] {
    '.js': [Function],
    '.json': [Function],
    '.node': [Function]
  },
  cache: [Object: null prototype] {
    '/home/michel/Workspace/lab/examples_posts/modules_npm/myModule.js': Module {
      id: '.',
      path: '/home/michel/Workspace/lab/examples_posts/modules_npm',
      exports: {},
      parent: null,
      filename: '/home/michel/Workspace/lab/examples_posts/modules_npm/myModule.js',
      loaded: false,
      children: [],
      paths: [Array]
    }
  }
}
Module =&amp;gt;  Module {
  id: '.',
  path: '/home/michel/Workspace/lab/examples_posts/modules_npm',
  exports: {},
  parent: null,
  filename: '/home/michel/Workspace/lab/examples_posts/modules_npm/myModule.js',
  loaded: false,
  children: [],
  paths: [
    '/home/michel/Workspace/lab/examples_posts/modules_npm/node_modules',
    '/home/michel/Workspace/lab/examples_posts/node_modules',
    '/home/michel/Workspace/lab/node_modules',
    '/home/michel/Workspace/node_modules',
    '/home/michel/node_modules',
    '/home/node_modules',
    '/node_modules'
  ]
}
Filename =&amp;gt;  /home/michel/Workspace/lab/examples_posts/modules_npm/myModule.js
Dirname =&amp;gt;  /home/michel/Workspace/lab/examples_posts/modules_npm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso acontece porque quando executamos o nosso script (módulo) ele é encapsulado pela função já citada acima e seus parâmetros ficam disponíveis no contexto do atual módulo.&lt;/p&gt;

&lt;p&gt;O parâmetro exports é uma referência para o module.exports (atalho) e contém tudo que é exportado dentro do nosso módulo, no momento como não estamos exportando nada o valor atual é: {}&lt;/p&gt;

&lt;p&gt;Vamos fazer um teste e exporta algo no nosso módulo, uma variável “name” por exemplo, o código vai ficar assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;exports.name = 'João';

console.log('Exports =&amp;gt; ', exports);
console.log('Require =&amp;gt; ', require);
console.log('Module =&amp;gt; ', module);
console.log('Filename =&amp;gt; ', __filename);
console.log('Dirname =&amp;gt; ', __dirname);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E o resultado será esse:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Exports =&amp;gt;  { name: 'João' }
Require =&amp;gt;  [Function: require] {
  resolve: [Function: resolve] { paths: [Function: paths] },
  main: Module {
    id: '.',
    path: '/home/michel/Workspace/lab/examples_posts/modules_npm',
    exports: { name: 'João' },
    parent: null,
    filename: '/home/michel/Workspace/lab/examples_posts/modules_npm/myModule.js',
    loaded: false,
    children: [],
    paths: [
      '/home/michel/Workspace/lab/examples_posts/modules_npm/node_modules',
      '/home/michel/Workspace/lab/examples_posts/node_modules',
      '/home/michel/Workspace/lab/node_modules',
      '/home/michel/Workspace/node_modules',
      '/home/michel/node_modules',
      '/home/node_modules',
      '/node_modules'
    ]
  },
  extensions: [Object: null prototype] {
    '.js': [Function],
    '.json': [Function],
    '.node': [Function]
  },
  cache: [Object: null prototype] {
    '/home/michel/Workspace/lab/examples_posts/modules_npm/myModule.js': Module {
      id: '.',
      path: '/home/michel/Workspace/lab/examples_posts/modules_npm',
      exports: [Object],
      parent: null,
      filename: '/home/michel/Workspace/lab/examples_posts/modules_npm/myModule.js',
      loaded: false,
      children: [],
      paths: [Array]
    }
  }
}
Module =&amp;gt;  Module {
  id: '.',
  path: '/home/michel/Workspace/lab/examples_posts/modules_npm',
  exports: { name: 'João' },
  parent: null,
  filename: '/home/michel/Workspace/lab/examples_posts/modules_npm/myModule.js',
  loaded: false,
  children: [],
  paths: [
    '/home/michel/Workspace/lab/examples_posts/modules_npm/node_modules',
    '/home/michel/Workspace/lab/examples_posts/node_modules',
    '/home/michel/Workspace/lab/node_modules',
    '/home/michel/Workspace/node_modules',
    '/home/michel/node_modules',
    '/home/node_modules',
    '/node_modules'
  ]
}
Filename =&amp;gt;  /home/michel/Workspace/lab/examples_posts/modules_npm/myModule.js
Dirname =&amp;gt;  /home/michel/Workspace/lab/examples_posts/modules_npm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora podemos ver que a variável exports no nosso resultado contém em seu objeto a propriedade name com o valor João, isso vai se manter para tudo que exportamos no nosso módulo (função, classe e etc).&lt;/p&gt;

&lt;p&gt;O parâmetro &lt;strong&gt;require&lt;/strong&gt; armazena o resultado de module.exports seguido de algumas propriedades adicionais como cache, observe o retorno do script mencionado acima.&lt;br&gt;
O parâmetro &lt;strong&gt;module&lt;/strong&gt; armazena as informações do module em geral, é um objeto criado pelo Module system.&lt;br&gt;
O parâmetro &lt;strong&gt;__filename&lt;/strong&gt; é o nome do arquivo (com o caminho completo) e o &lt;strong&gt;__dirname&lt;/strong&gt; é o diretório onde o arquivo foi encontrado (caminho completo).&lt;/p&gt;

&lt;p&gt;Esse foi um resumo de como o export em NodeJS funciona focado na função wrapped, espero que tenha ficado entendível. È claro que essa é uma parte do processo e existe mais alguns passos quando a gente faz require de um módulo até ele ser retornado mas é um pouco “baixo nível” e não sei se teria tanta relevância entrar nos mínimos detalhe aqui, claro se você quiser pesquisar mais a fundo sentasse a vontade, vou deixar aqui uma imagem que resume todo esse processo.&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%2Fi%2Fwox8cpug2w2fowxsitw9.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%2Fi%2Fwox8cpug2w2fowxsitw9.png" alt="Imagem do fluxo do require em node.js" width="800" height="470"&gt;&lt;/a&gt;&lt;br&gt;
Font: Node Js Cookbook&lt;/p&gt;

&lt;p&gt;Se quiser saber mais: &lt;a href="https://nodejs.org/docs/latest/api/modules.html"&gt;Modules DOC&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;NPM Scripts&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Usar os scripts do npm ao nosso favor pode ser uma poderosa ferramenta para nos auxiliar no dia a dia automatizando pequenas tarefas. Podemos configurar scripts a ser executado na sessão “scripts” no arquivo package.json, por exemplo vamos configurar para rodar nossos testes unitários com jest, ficaria assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"scripts": {
    "test": "jest"
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se executamos “npm test” no terminal nossos testes unitários será executado.&lt;/p&gt;

&lt;p&gt;Esse script “test” é um dos vários scripts pré definidos do npm, você pode ver a lista completa aqui &lt;a href="https://docs.npmjs.com/misc/scripts"&gt;Doc npm scripts&lt;/a&gt;.&lt;br&gt;
Além desses scripts pré definidos a gente pode criar nossos próprios scripts adicionando uma propriedade no objeto da sessão “scripts” no package.json, a única diferença é que para executar nossos scripts “custom” vamos ter que add a prop run na execução do script ficando assim: “npm run ”, vamos ver os exemplos:&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight plaintext"&amp;gt;&amp;lt;code&amp;gt;"scripts": {
    "test": "jest",
    "start": "echo \"Start something\"",
    "say_my_name": "echo \"Michel\""
  },
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Ao executar o comando “npm run say_my_name” no terminal o nome “Michel” será mostrado na tela.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Podemos fazer também encadeamento de scripts, exemplo:&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight plaintext"&amp;gt;&amp;lt;code&amp;gt;"scripts": {
    "test": "jest",
    "start": "echo \"Start something\"",
    "say_my_name": "echo \"Michel\"",
    "say_my_name:full": "npm run say_my_name \"Araujo\""
  },
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Acrescentamos uma linha “&amp;amp;quot;say_my_name:full&amp;amp;quot;: &amp;amp;quot;npm run say_my_name \&amp;amp;quot;Araujo\&amp;amp;quot;&amp;amp;quot;” que vai executar o script “say_my_name” e adicionar a palavra “Araujo”, se executamos esse script o resultado será o seguinte:&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight plaintext"&amp;gt;&amp;lt;code&amp;gt;npm run say_my_name:full
Resultado: “Michel Araujo”
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Assim podemos fazer o encadeamento de script o quanto precisamos, exemplo:&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight plaintext"&amp;gt;&amp;lt;code&amp;gt;"scripts": {
    "say_my_name_test": "npm test &amp;amp;amp;&amp;amp;amp; npm run say_my_name \"Araujo\""
  },
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;IMPORTANTE&amp;lt;/strong&amp;gt;: O carácter “&amp;amp;amp;&amp;amp;amp;” fazer a divisão de chamada sincronamente, no exemplo primeiro o “npm test” será executado e depois o “npm run say_my_name”, para fazer chamadas assíncronas basta usar somente um caractere “&amp;amp;amp;”, exemplo:&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight plaintext"&amp;gt;&amp;lt;code&amp;gt;"scripts": {
    "say_my_name_test": "npm test &amp;amp;amp; npm run say_my_name \"Araujo\""
  },
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Vale ressaltar que os scripts no npm é um sh portanto pode ser usado com comandos shell, exemplo:&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight plaintext"&amp;gt;&amp;lt;code&amp;gt;"scripts": {
    "list": "ls -la"
  },
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;npm run list&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Sendo assim podemos abusar da nossa criatividade!&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Nota: Vale a pena citar que quando executamos um script npm os diretórios atual “node_modules/.bin” são adicionados a variável de ambiente PATH, sendo assim mesmo se não tivemos uma diferença de algum executável no PATH do sistema podemos referenciar no scripts do npm que irá funcionar.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Vale uma menção honrosa aqui sobre os scripts hook dê uma olhada aqui &amp;lt;a href="https://docs.npmjs.com/misc/scripts"&amp;gt;doc npm scripts&amp;lt;/a&amp;gt; para saber mais.&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;
  &amp;lt;a name="como-configurar-um-registry-scope" href="#como-configurar-um-registry-scope" class="anchor"&amp;gt;
  &amp;lt;/a&amp;gt;
  &amp;lt;strong&amp;gt;Como configurar um registry Scope&amp;lt;/strong&amp;gt;
&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;Vamos dizer que você tem um registry local e você quer mandar seus módulos para lá como também baixar do mesmo sem afetar o registry padrão ou seja sem influenciar nas outras dependências, você pode criar um Scope para isso simplesmente usando o caractere “@” no nome do módulo, exemplo:&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;&amp;amp;quot;name&amp;amp;quot;: &amp;amp;quot;@local/mymoduletest&amp;amp;quot;,&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Assim quando fomos usar esse módulo como dependência&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight plaintext"&amp;gt;&amp;lt;code&amp;gt;dependencies": {
    "express": "^4.17.1",
    "@local/mymoduletest": "^1.0.0"
  }

&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;E executar npm install o express será baixado do registry padrão e o @local/mymoduletest do nosso registry local.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Exemplo de como ficou nosso package-lock:&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight plaintext"&amp;gt;&amp;lt;code&amp;gt;"@local/mymoduletest": {
      "version": "1.0.0",
      "resolved": "http://localhost:4873/@local%2fmymoduletest/-/mymoduletest-1.0.0.tgz",
      "integrity": "sha512-7+mejz"
    },
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Observe a prop “resolved”.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Usei o Sinopia para criar um registry local e executar esse exemplo.&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;
  &amp;lt;a name="boas-ferramentas" href="#boas-ferramentas" class="anchor"&amp;gt;
  &amp;lt;/a&amp;gt;
  &amp;lt;strong&amp;gt;Boas ferramentas!&amp;lt;/strong&amp;gt;
&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Sinopia:&amp;lt;/strong&amp;gt; Permite que você tenha um registry local e privado com facilidade, tem uma boa integração com o &amp;lt;a href="http://npmjs.org/"&amp;gt;http://npmjs.org/&amp;lt;/a&amp;gt; pode ser usado como cache do npm. Pode ser usado com Docker =)&amp;lt;br&amp;gt;
Saiba mais em: &amp;lt;a href="https://www.npmjs.com/package/sinopia"&amp;gt;https://www.npmjs.com/package/sinopia&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;IPFS protocol:&amp;lt;/strong&amp;gt; Pode ser usado como uma alternativa ao registry oficial do npm para fazer publicação de módulos.&amp;lt;br&amp;gt;
Saiba mais em: &amp;lt;a href="https://ipfs.io/"&amp;gt;https://ipfs.io/&amp;lt;/a&amp;gt; e &amp;lt;a href="https://www.npmjs.com/package/stay-cli"&amp;gt;https://www.npmjs.com/package/stay-cli&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Registry-static:&amp;lt;/strong&amp;gt; Literalmente baixa todo o registry do NPM na máquina local (mais de 200 Gbs) parece absurdo mas pode ser uma boa opção de cache para o npm install ficar mais rápido.&amp;lt;br&amp;gt;
Saiba mais em: &amp;lt;a href="https://www.npmjs.com/package/registry-static"&amp;gt;https://www.npmjs.com/package/registry-static&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;
  &amp;lt;a name="referencias" href="#referencias" class="anchor"&amp;gt;
  &amp;lt;/a&amp;gt;
  &amp;lt;strong&amp;gt;Referencias:&amp;lt;/strong&amp;gt;
&amp;lt;/h2&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Node Cookbook - &amp;lt;a href="https://www.packtpub.com/web-development/node-cookbook-third-edition"&amp;gt;https://www.packtpub.com/web-development/node-cookbook-third-edition&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Node.js Docs - &amp;lt;a href="https://nodejs.org/en/docs/"&amp;gt;https://nodejs.org/en/docs/&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Npm Docs - &amp;lt;a href="https://docs.npmjs.com/"&amp;gt;https://docs.npmjs.com/&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Stay hungry Stay foolish!&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&lt;/p&gt;

</description>
      <category>node</category>
      <category>npm</category>
      <category>javascript</category>
      <category>module</category>
    </item>
  </channel>
</rss>
