<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Daniil Sitdikov</title>
    <description>The latest articles on DEV Community by Daniil Sitdikov (@dsitdikov).</description>
    <link>https://dev.to/dsitdikov</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%2F293019%2F44421adc-dece-4433-b11d-ad915bebffaa.jpeg</url>
      <title>DEV Community: Daniil Sitdikov</title>
      <link>https://dev.to/dsitdikov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dsitdikov"/>
    <language>en</language>
    <item>
      <title>Frontend Performance Glossary: The 11 Most Common Metrics</title>
      <dc:creator>Daniil Sitdikov</dc:creator>
      <pubDate>Tue, 24 Oct 2023 10:02:22 +0000</pubDate>
      <link>https://dev.to/dsitdikov/frontend-performance-glossary-the-11-most-common-metrics-76o</link>
      <guid>https://dev.to/dsitdikov/frontend-performance-glossary-the-11-most-common-metrics-76o</guid>
      <description>&lt;p&gt;This glossary contains a list of the most common metrics which may appear in articles, DevTools, Lighthouse, and other various tools for working with web performance. Everything is sorted in the alphabetical order.&lt;/p&gt;

&lt;p&gt;The factual data is primarily sourced from MDN, web.dev and w3c, however the short description has been rewritten and enhanced.&lt;/p&gt;




&lt;h2&gt;
  
  
  CLS
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Cumulative Layout Shift&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Measurement Unit: Score (lower is better)&lt;/p&gt;

&lt;p&gt;Shows how often users experience unexpected changes in the layout. It measures the instability of elements and their overall impact. For example, the banner element changes its height during the loading process, which causes a shift in the elements below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://web.dev/articles/cls"&gt;more details&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  DCL
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;DOMContentLoaded&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Measurement Unit: Milliseconds (ms)&lt;/p&gt;

&lt;p&gt;Refers to the moment in a webpage's loading process when the DOM is completely parsed. And all deferred scripts have downloaded and executed. It doesn't wait for resources.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/DOMContentLoaded_event"&gt;more details&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  FCP
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;First Contentful Paint&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Measurement Unit: Milliseconds (ms)&lt;/p&gt;

&lt;p&gt;Measures the time it takes for first bit of any actual content on a page to become visible on the screen. This includes text, images, background images, SVG elements, and non-white canvas elements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://web.dev/articles/fcp"&gt;more details&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  FID
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;First Input Delay&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Measurement Unit: Milliseconds (ms)&lt;/p&gt;

&lt;p&gt;Measures the time it takes for the browser to respond to a user's first interaction. This interaction can include clicks, hovers, touches, and other user events.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://web.dev/articles/fid"&gt;more details&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  FP
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;First Paint&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Measurement Unit: Milliseconds (ms)&lt;/p&gt;

&lt;p&gt;Marks the first time the browser renders anything visually different from the default background color of the body.&lt;/p&gt;




&lt;h3&gt;
  
  
  INP
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Interaction to Next Paint&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Measurement Unit: Milliseconds (ms)&lt;/p&gt;

&lt;p&gt;Measures the time it takes for the browser to paint the next frame after a user interaction. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://web.dev/articles/inp"&gt;more details&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  L
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;On Load&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Measurement Unit: Milliseconds (ms)&lt;/p&gt;

&lt;p&gt;Measures the time when the entire page and its resources are fully loaded. It includes all dependent resources: stylesheets, scripts, iframes, and images.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event"&gt;more details&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  LCP
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Largest Contentful Paint&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Measurement Unit: Milliseconds (ms)&lt;/p&gt;

&lt;p&gt;Measures the time when the largest content block is rendered in the user viewport. The content may include images, background images, SVG, video, and text.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://web.dev/articles/lcp"&gt;more details&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  SI
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Speed Index&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Measurement Unit: Score (lower is better)&lt;/p&gt;

&lt;p&gt;Measures how swiftly the contents of a page are visually populated. Technically, in a graph, it is represented by the area above the curve, which will approach 0 as the page loads faster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Speed_index"&gt;more details&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  TBT
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Total Blocking Time&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Measurement Unit: Milliseconds (ms)&lt;/p&gt;

&lt;p&gt;Measures the time between FCP and TTI when the main thread was blocked for long enough to prevent input responsiveness. More specifically, it's the sum of the blocking time for each long task (&amp;gt;50 ms). For web frameworks, this time is usually consumed by virtual DOM renders and hydration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://web.dev/articles/tbt"&gt;more details&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  TTFB
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Time To First Byte&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Measurement Unit: Milliseconds (ms)&lt;/p&gt;

&lt;p&gt;Measures when the first byte of data from the web server reaches the browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://web.dev/articles/ttfb"&gt;more details&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  TTI
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Time to Interactive&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Measurement Unit: Milliseconds (ms)&lt;/p&gt;

&lt;p&gt;Measures the time when than at least for 5 seconds where weren't long tasks (&amp;gt;50ms) and no more than two in-flight network GET requests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://web.dev/articles/tti"&gt;more details&lt;/a&gt;&lt;/p&gt;




</description>
      <category>webdev</category>
      <category>performance</category>
      <category>javascript</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Frontend Optimization: My Journey to Accelerate Load Times in Heavy Frontend</title>
      <dc:creator>Daniil Sitdikov</dc:creator>
      <pubDate>Sun, 08 Oct 2023 16:44:29 +0000</pubDate>
      <link>https://dev.to/dsitdikov/my-journey-to-accelerate-load-times-in-heavy-frontend-30c7</link>
      <guid>https://dev.to/dsitdikov/my-journey-to-accelerate-load-times-in-heavy-frontend-30c7</guid>
      <description>&lt;p&gt;Recently, the business approached us with a complaint that our product loads slowly in regions where old mobile devices and slow internet prevail. As a result, users are opting to switch to our competitors. In this article, I will share how I was able to improve the app's load time by implementing techniques such as import and render on visibility, image proxy, proficient work with SVG images, and other methods. I hope you'll find something useful for your app as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Brief Introduction
&lt;/h2&gt;

&lt;p&gt;On our page, we have a lot of components, including a banner, interactive dynamic content in the center, several sliders, and extensive navigation in the header and sidebar. However, this leads to a large number of DOM elements (6500) and a lengthy total blocking time (12 seconds) on mobile devices. Additionally, the fully rendered main page has a total height of 11000 pixels. Even React Profiler in DevTools can’t handle it and crashes.&lt;/p&gt;

&lt;p&gt;We use React with Next.js. The majority of the content on the main page is dynamic and interactive, updating in real-time.&lt;/p&gt;

&lt;p&gt;Some obvious performance enhancements have already been made:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Caching on the CDN side&lt;/li&gt;
&lt;li&gt;Gzip compression&lt;/li&gt;
&lt;li&gt;http/2 server&lt;/li&gt;
&lt;li&gt;Correctly set loading priorities for resources: defer and async&lt;/li&gt;
&lt;li&gt;Images are set to lazy&lt;/li&gt;
&lt;li&gt;All internal pages are lazy-loaded by default&lt;/li&gt;
&lt;li&gt;The bundle is split into chunks.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Shortcut
&lt;/h2&gt;

&lt;p&gt;First, what I started with and what could quickly solve many problems: &lt;br&gt;
🥁 1..2..3…&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;just reduce the amount of content on the main page.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;create a special main page in pure HTML and vanilla JS for such regions.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;However, in my case, I was unable to convince the business, and I had to solve the problem using an engineering approach.&lt;/p&gt;
&lt;h2&gt;
  
  
  Render on Visibility
&lt;/h2&gt;

&lt;p&gt;The question I asked myself was: why spend so much time and resources rendering something the user doesn't even see? The entire page height is 11000px, but a mobile user typically only sees about 700px upon starting. Therefore, 10300px of content can simply be skipped from rendering. The situation is the same on desktop.&lt;/p&gt;

&lt;p&gt;I created a basic component that only renders content when it is about to be visible in the user's viewport. It starts loading the content in advance, with an additional 100px on top, to accommodate slower CPUs. This optimization also applies horizontally. For example, if a slide's content is not within the user's view, it won't be rendered. This approach has proven to be beneficial, especially considering that each slide contains logic and multiple components.&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%2Fx0mat0qyng7i2nxbdd0c.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%2Fx0mat0qyng7i2nxbdd0c.png" alt="Lazy Rendered Scheme"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The component receives two props:&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// 1. Children - the content which will be hidden&lt;/span&gt;
&lt;span class="c1"&gt;// 2. Classname - a special class with height and skeleton loader to avoid layout &lt;/span&gt;
&lt;span class="c1"&gt;//                shifts after content appear&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;LazyLoadedComponentUI&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;intersectionRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// useIntersection is used from the react-use library&lt;/span&gt;
  &lt;span class="c1"&gt;// However, it can be easily implemented manually.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;intersection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useIntersection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;intersectionRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;rootMargin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100px 0px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isShown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsShown&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Content won't be removed after it has been rendered. &lt;/span&gt;
    &lt;span class="c1"&gt;// However, this behavior can be easily changed.&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;intersection&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;intersection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;intersectionRatio&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isShown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setIsShown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;intersection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isShown&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;isShown&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;intersectionRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;classNames&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lazy-rendered-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How it looks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FooterNav&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;complicated component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;span class="c1"&gt;// It's important not to forget to include loader styles to avoid layout shifts.&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;LazyRenderedComponent&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;footer-nav-loader loader&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;FooterNav&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="na"&gt;LazyRenderedComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My goal was to include only the necessary content for the earliest visuals in the main bundle. This includes what the user sees. Modal windows and collapsing sidebars are downloaded and displayed only when needed.&lt;/p&gt;

&lt;p&gt;Sometimes, it wasn’t obvious as it seemed to be. We have a list of 20-30 dynamic items with nested components and logic inside. To prevent layout shifts and maintain smoothness, I implemented lazy rendering specifically for the content of each item on this list. This means that the application reserves empty spaces for a specific item and renders it only when it is near.&lt;/p&gt;

&lt;p&gt;Eventually, after applying the lazy load component to many items, we ended up with approximately 700 DOM elements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Import on Visibility
&lt;/h2&gt;

&lt;p&gt;This allows us to go even further. If we don’t render it outside the viewport, maybe we can even don’t download it? It is possible that the user never scrolls to this content at all. All that remains is to pass the content to our &lt;code&gt;LazyRenderComponent&lt;/code&gt; Suspense.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FooterNav&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./footer-nav&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"footer-nav-loader loader"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;LazyRenderedComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;FooterNav&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="na"&gt;LazyRenderedComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The alternative usage with the plain React:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FooterNav&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./footer-nav&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;LazyRenderedComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Suspence&lt;/span&gt; &lt;span class="na"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"footer-nav-loader loader"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;FooterNav&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Suspence&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;LazyRenderedComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when the viewport is near this component, it will start loading it. &lt;/p&gt;

&lt;p&gt;⚠️ As in the previous item, it is very important not to forget about the loading state in order to avoid layout shifts. Here, we pass the fallback property to the Suspense component.&lt;/p&gt;

&lt;h2&gt;
  
  
  Selective Hydration
&lt;/h2&gt;

&lt;p&gt;During React hydration, React recreates the state it had on the server, essentially re-recreating the virtual DOM. This process can be time-consuming as React needs to parse the current DOM tree. Initially, there may be content in the viewport that should be visible, but it doesn't necessarily need to be interactive right away. To improve performance, I tried deferring hydration by wrapping these components in Suspense, which temporarily delays hydration and keeps them inactive. I initially believed that it completely transformed the game and reduced everything to zero seconds. However, it actually only removed two seconds from TBT.&lt;/p&gt;

&lt;h2&gt;
  
  
  Image Proxy
&lt;/h2&gt;

&lt;p&gt;In our application, the LCP (Largest Contentful Paint) refers to a banner. Typically, these banners are high-resolution PNG files, with an average size of around 3 MB each. However, the challenge lies in the fact that we have no control over the sizes or file formats uploaded by the operator. Furthermore, imposing restrictions on the operators would not be a favorable design approach.&lt;/p&gt;

&lt;p&gt;We agreed to convert, compress and resize images on the fly, during the request. This means that we only need to specify the desired URL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//IMG_PROXY_URL/resize:fit::300/quality:75/plain/image.jpg@avif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our solution was to use &lt;strong&gt;&lt;a href="https://github.com/imgproxy/imgproxy" rel="noopener noreferrer"&gt;image-proxy&lt;/a&gt;&lt;/strong&gt;. It perfectly fit our needs in terms on performance, functionality and scalability.&lt;/p&gt;

&lt;p&gt;We use three formats: &lt;code&gt;avif&lt;/code&gt;, &lt;code&gt;webp&lt;/code&gt;, and &lt;code&gt;jpg/png&lt;/code&gt;. The browser automatically loads the best format based on its capabilities. For example, if a browser does not support avif format, it will use webp. If no supported formats are available, the default &lt;code&gt;img&lt;/code&gt; tag will be used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;picture&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;source&lt;/span&gt; &lt;span class="na"&gt;srcSet&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"URL_TO_AVIF"&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"image/avif"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;source&lt;/span&gt; &lt;span class="na"&gt;srcSet&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"URL_TO_WEBP"&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"image/webp"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"URL_TO_DEFAULT_FALLBACK"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;picture&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The resize and compression operation is performed only once. Immediately after that, the result of each image request is cached on CDN. This makes sure we don't sacrifice speed.&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%2Fb74jgdxhb3m55i7y680n.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%2Fb74jgdxhb3m55i7y680n.png" alt="Architecture Diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, each image is 120-200 kb instead of 1-2 Mb. They are in the optimal format and have an optimal size based on the device.&lt;/p&gt;

&lt;h3&gt;
  
  
  Alternative Solutions
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;If you are using Next.js, perhaps &lt;code&gt;next/images&lt;/code&gt; will be sufficient. However, you won’t be flexible enough and you lose an opportunity to reuse this solution in different place other than Next.&lt;/li&gt;
&lt;li&gt;There is also a library that Next.js itself uses: &lt;a href="https://github.com/lovell/sharp" rel="noopener noreferrer"&gt;sharp&lt;/a&gt;. It can be setup as Node.js service. I even played around a little: &lt;a href="https://github.com/Danilqa/image-proxy-service" rel="noopener noreferrer"&gt;image-proxy-service&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Cloudflare and other services offers its own service for resizing and converting images.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Loading Priority
&lt;/h2&gt;

&lt;p&gt;Since only one image is visible in the main LCP banner, we explicitly set it to &lt;code&gt;loading=eager&lt;/code&gt;, and for the other slides, we used &lt;code&gt;loading=lazy&lt;/code&gt;. They will load as soon as the user sees them.&lt;/p&gt;

&lt;p&gt;Also, for the first slide, I added the attribute &lt;code&gt;fetchPriority="high"&lt;/code&gt;, which allows the image to be loaded as a priority. As we have up to 100 different request at the first seconds, prioritizing LCP-image was crucial.&lt;/p&gt;

&lt;h2&gt;
  
  
  SVG Images
&lt;/h2&gt;

&lt;p&gt;We had around 150 SVG icons and several images that we stored directly in React components. This significantly increased the bundle's weight by 60 KB, and their rendering clogged up our thread during the initial paint.&lt;/p&gt;

&lt;p&gt;We consolidated all icons into one large SVG sprite and placed it on a CDN. The icons are loaded just once to avoid clogging network connections and to save time on connection establishment. We use the &lt;strong&gt;&lt;code&gt;use&lt;/code&gt;&lt;/strong&gt; element to display the required sprite from the entire list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;
  &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;viewBox&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0 0 512 512"&lt;/span&gt;
  &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;use&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`#&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;symbol&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"icon-1"&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"10"&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"10"&lt;/span&gt; &lt;span class="na"&gt;viewBox&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0 0 2 2"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;circle&lt;/span&gt; &lt;span class="na"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt; &lt;span class="na"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt; &lt;span class="na"&gt;r&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;symbol&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"icon-2"&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"10"&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"10"&lt;/span&gt; &lt;span class="na"&gt;viewBox&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0 0 2 2"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;circle&lt;/span&gt; &lt;span class="na"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt; &lt;span class="na"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt; &lt;span class="na"&gt;r&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another solution could be to move them to the icons font, although it may not offer the same level of flexibility. &lt;/p&gt;

&lt;p&gt;Regarding images, we just relocated them to a CDN as separate files.&lt;/p&gt;

&lt;h2&gt;
  
  
  DNS Prefetch
&lt;/h2&gt;

&lt;p&gt;Before starting to load a resource from an external URL, the browser spends 20 - 120 ms just on DNS resolving. I marked two &lt;strong&gt;&lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt;&lt;/strong&gt; tags with the attribute &lt;code&gt;rel="preconnect"&lt;/code&gt; so the browser could start the handshake processes in advance: DNS, TCP, and TLS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt; 
  &lt;span class="na"&gt;crossOrigin&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"anonymous"&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://fonts.gstatic.com"&lt;/span&gt; 
  &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"preconnect"&lt;/span&gt; 
&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Undoubtedly, this was a significant step in performance improvement. Some of the core web vitals on low-end mobile devices:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;LCP decreased from 12s to 2.5s. &lt;/li&gt;
&lt;li&gt;Number of DOM elements decreased from 6500 to 700.&lt;/li&gt;
&lt;li&gt;The lighthouse score was increased from 3 to 52&lt;/li&gt;
&lt;li&gt;TBT was decreased from 12s to 5.6s. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These numbers have not yet reached the green zone. It means that there is a lot of work to be done. See you in the second part, where I'll share new results! &lt;/p&gt;

&lt;h2&gt;
  
  
  Future Plans
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Consider replacing the default virtual DOM with an alternative solution. For instance, &lt;a href="https://github.com/aidenybai/million" rel="noopener noreferrer"&gt;Million.js&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Experiment with service workers.&lt;/li&gt;
&lt;li&gt;Remove SSR from components where it causes rehydration and negatively affects performance.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Let's Learn Together
&lt;/h2&gt;

&lt;p&gt;Each of us has our own unique experiences, challenges faced, and solutions discovered. I'd love to hear about your own adventures in frontend optimization. What worked for you? What would you recommend doing? Please share your experiences in the comments below!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>react</category>
      <category>performance</category>
    </item>
    <item>
      <title>How to Transform Vim to a Complete IDE?</title>
      <dc:creator>Daniil Sitdikov</dc:creator>
      <pubDate>Tue, 19 Sep 2023 13:32:07 +0000</pubDate>
      <link>https://dev.to/dsitdikov/how-to-transform-vim-to-a-complete-ide-2m6f</link>
      <guid>https://dev.to/dsitdikov/how-to-transform-vim-to-a-complete-ide-2m6f</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Recently, fate forced me to work on my old personal MacBook from 2015. Over the years of development, I've got used to powerful IDEs, such as IntelliJ IDEA, but my laptop couldn't handle it anymore. Having three projects open simultaneously made their development practically impossible. Everything was very laggy. I also noticed the same problems in VSCode. In frustration, I decided to take a radical approach and try out the classic Vim.&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%2Fct4sst7jf72u1k3fwmvd.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%2Fct4sst7jf72u1k3fwmvd.png" alt="classic vim"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After working in classic Vim for 30 minutes, I realized that this method might be too harsh for me. A lot has to be done through the terminal: finding the necessary files, making edits, running the linter separately. Additionally, to work comfortably, you need to know a lot of commands. But at least there were no lags anymore. Still, in 2023, I'd at least like to see:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Syntax highlighting&lt;/li&gt;
&lt;li&gt;Linter and Prettier&lt;/li&gt;
&lt;li&gt;Fuzzy search across the entire project and the current file&lt;/li&gt;
&lt;li&gt;Tips to speed up the writing process&lt;/li&gt;
&lt;li&gt;Visual navigation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, my choice fell on NeoVim. Essentially, it's a significantly reworked and improved Vim. It retains almost all of its functionality, but at the same time, it adds rich expansion capabilities. One of the key features is the support for the Language Server Protocol, which allows for syntax highlighting, adding linters, and providing suggestions similar to VSCode. All of this has enabled developers to create a large number of plugins, replicating the functionality of the IDEs we are accustomed to these days.&lt;/p&gt;

&lt;p&gt;And here's what I got:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ntpemr57trc71i9et4u.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%2F9ntpemr57trc71i9et4u.png" alt="nvim"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It uses only 170-250 MB of RAM!&lt;/p&gt;

&lt;h1&gt;
  
  
  Ready-made packages
&lt;/h1&gt;

&lt;p&gt;The quickest and easiest way to start is to use a pre-made setup. Here are a few great well-known options to choose from:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://www.lunarvim.org/" rel="noopener noreferrer"&gt;https://www.lunarvim.org/&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.lazyvim.org/" rel="noopener noreferrer"&gt;https://www.lazyvim.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://astronvim.com/" rel="noopener noreferrer"&gt;https://astronvim.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nvchad.com/" rel="noopener noreferrer"&gt;https://nvchad.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://spacevim.org/" rel="noopener noreferrer"&gt;https://spacevim.org/&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Personally, I use LunarVim. It's quick and easy to install, and it has good documentation. There are many more here: &lt;a href="https://github.com/topics/neovim-config" rel="noopener noreferrer"&gt;https://github.com/topics/neovim-config&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;An important note: most likely, the standard terminal won't be enough for full-fledged work. On MacOS, I switched to iTerm.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to use it?
&lt;/h1&gt;

&lt;p&gt;So, I've downloaded and installed it, what's next?&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffzaapzwdxqj1vj4tac8y.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%2Ffzaapzwdxqj1vj4tac8y.png" alt="opened file via nvim"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's a nuance here. Everything is controlled by keys, and only sometimes by the mouse. Almost any build has a project search, code hints, file explorer, and code hints. &lt;/p&gt;

&lt;p&gt;There are numerous plugins available. For instance, this is a Copilot implementation: &lt;a href="https://github.com/zbirenbaum/copilot-cmp" rel="noopener noreferrer"&gt;https://github.com/zbirenbaum/copilot-cmp&lt;/a&gt;. Or prettier: &lt;a href="https://github.com/MunifTanjim/prettier.nvim" rel="noopener noreferrer"&gt;https://github.com/MunifTanjim/prettier.nvim&lt;/a&gt;. You might need just edit your configuration file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cheat sheet
&lt;/h2&gt;

&lt;p&gt;Here's a short list of commands that will help you quickly get the hang of it and start playing around:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Navigation:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open file explorer on the left: &lt;code&gt;Space + e&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Go to the file reference: &lt;code&gt;g&lt;/code&gt; + mouse click&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Search&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;All-available menu: &lt;code&gt;:Telescope&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Fuzzy search for files: &lt;code&gt;Space + f&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Search within the file itself: &lt;code&gt;Space + s + t&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;What's needed the most&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Copy the selected: &lt;code&gt;y&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Paste: &lt;code&gt;Ctrl + V&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Edit mode: &lt;code&gt;i&lt;/code&gt;, default mode: &lt;code&gt;Esc&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Save file: &lt;code&gt;:w&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Quit: &lt;code&gt;:q&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By default, most of nvim packages have &lt;a href="https://github.com/folke/which-key.nvim" rel="noopener noreferrer"&gt;WhichKey&lt;/a&gt; plugin which shows popup with available commands. For instance, you press &lt;code&gt;space&lt;/code&gt; or &lt;code&gt;g&lt;/code&gt; and what for a second:&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%2Fs1sbl3cfjg7m4jkvq07h.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%2Fs1sbl3cfjg7m4jkvq07h.png" alt="which key example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Add more terminals at the bottom
&lt;/h2&gt;

&lt;p&gt;You can attach terminals using:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;:ToggleTerm size=8 direction=horizontal&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;But I personally prefer adding them using native terminal’s functionality. For instance, iTerms can attach several terminal sessions to the current window.&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%2F10svn2as3yr6cnf3ycpv.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%2F10svn2as3yr6cnf3ycpv.png" alt="split terminals"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning native Vim commands
&lt;/h2&gt;

&lt;p&gt;If you want to become thoroughly familiar with the commands of Vim and remember them forever, there is a browser game that can help you achieve this: &lt;a href="https://vim-adventures.com/" rel="noopener noreferrer"&gt;https://vim-adventures.com&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;And this comprehensive guide: &lt;a href="https://github.com/iggredible/Learn-Vim" rel="noopener noreferrer"&gt;https://github.com/iggredible/Learn-Vim&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Git
&lt;/h1&gt;

&lt;p&gt;You can also work conveniently with git from the terminal. For this, you can install &lt;a href="https://github.com/jesseduffield/lazygit" rel="noopener noreferrer"&gt;LazyGit:&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx301ya2k0qa4l3tze5jq.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%2Fx301ya2k0qa4l3tze5jq.png" alt="LazyGit window"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick cheat-sheet for the essentials:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add files to staged changes: just a mouse click on files and folders&lt;/li&gt;
&lt;li&gt;Discard changes: &lt;code&gt;d&lt;/code&gt;. 
It can be applied for lines and for files. &lt;/li&gt;
&lt;li&gt;Git pull: &lt;code&gt;p&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Commit changes: &lt;code&gt;c&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Git push: &lt;code&gt;P&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;I am impressed by how enthusiasts have managed to implement such complex features from modern IDEs inside the terminal using minimal resources. Personally, I find it to be a great choice when you have limited resources on your laptop or when you need to navigate through system files and make edits. It's also a great idea to set it up on a remote server. However, when I switched back to the powerful laptop, I stopped using it as a main IDE. Thank you &lt;a href="https://dev.to/phil9l"&gt;phil9l&lt;/a&gt; for sharing with me such amazing approach and inspiring to write this article!&lt;/p&gt;

</description>
      <category>vim</category>
      <category>nvim</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
    <item>
      <title>File-Based Routing in Node.js</title>
      <dc:creator>Daniil Sitdikov</dc:creator>
      <pubDate>Thu, 31 Aug 2023 18:45:16 +0000</pubDate>
      <link>https://dev.to/dsitdikov/file-based-routing-in-nodejs-n6f</link>
      <guid>https://dev.to/dsitdikov/file-based-routing-in-nodejs-n6f</guid>
      <description>&lt;p&gt;About a year ago, I tried Next.js for the first time and was so impressed by their file-based routing that I decided to implement a similar system on the backend. I couldn't find anything suitable, so I took it upon myself to create my own solution. It turned out to be technology-agnostic and works with both pure Node.js, Bun and the popular Express.js.&lt;/p&gt;

&lt;p&gt;In this brief guide, we will attempt to partially implement a shop's API. This tutorial uses JavaScript and CommonJS module types to keep things simple and quick to get started. &lt;/p&gt;

&lt;h2&gt;
  
  
  1. Installation
&lt;/h2&gt;

&lt;p&gt;💿 Install &lt;code&gt;node-file-router&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;npm install node-file-router
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Initialization
&lt;/h2&gt;

&lt;p&gt;Create an &lt;code&gt;server.js&lt;/code&gt; file and do the following&lt;/p&gt;

&lt;p&gt;If you use pure Node.js:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 1. Import default http module and node-file-router&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initFileRouter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node-file-router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Create an entry-point function&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// 3. Initialize node-file-router and the handler function&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useFileRouter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;initFileRouter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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="c1"&gt;// 4. Create a server and invoke created function on each request&lt;/span&gt;
    &lt;span class="nf"&gt;useFileRouter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// 5. Start listening a server on 4000 port&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="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;`Server running at http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 6. Run entry-point function&lt;/span&gt;
&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you use Express.js:&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initFileRouter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node-file-router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileRouter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;initFileRouter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4004&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileRouter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. A first route
&lt;/h2&gt;

&lt;p&gt;🏡 We will create a home route that displays welcome content. &lt;/p&gt;

&lt;p&gt;1. Create an &lt;code&gt;api&lt;/code&gt; folder at the root of your project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── api/ &amp;lt;-
├── server.js
└── package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2. Create a file named &lt;code&gt;index.js&lt;/code&gt; inside this folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── api/
│  └── index.js &amp;lt;-
├── server.js
└── package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Welcome to our shop!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3. Run a server using: &lt;code&gt;node server.js&lt;/code&gt; command&lt;br&gt;
4. Open a browser and navigate to &lt;a href="http://localhost:4000"&gt;http://localhost:4000&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
You should see the message &lt;code&gt;Welcome to our shop!&lt;/code&gt; displayed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Congratulations! 🎉 You've created a first file route&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Add http methods
&lt;/h2&gt;

&lt;p&gt;1. Before we start, we need a small utility function which will parse json from a request.&lt;br&gt;
Create a folder &lt;code&gt;utils&lt;/code&gt; and put &lt;code&gt;http.utils.js&lt;/code&gt; file inside.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── api/
├── ...
├── utils/
│  └── http.utils.js &amp;lt;-
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;parseJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data&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;chunk&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;data&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;end&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parsedData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parsedData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;reject&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="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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2. Create a folder called &lt;code&gt;products&lt;/code&gt; and an &lt;code&gt;index.js&lt;/code&gt; file inside it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── api/
│  ├── products/ &amp;lt;-
│  │  └── index.js &amp;lt;-
│  └── ...
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3. Implement &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;post&lt;/code&gt; methods:&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parseJson&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../utils/http.utils&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;list of products&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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="nx"&gt;newProduct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;parseJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`a product will be created: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newProduct&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3. Open a browser and go to &lt;a href="http://localhost:4000/products"&gt;http://localhost:4000/products&lt;/a&gt;. &lt;br&gt;&lt;br&gt;
You should see a &lt;code&gt;list of products&lt;/code&gt; message displayed.&lt;/p&gt;

&lt;p&gt;4. Make a POST request using &lt;code&gt;curl&lt;/code&gt;, &lt;code&gt;Postman&lt;/code&gt; or any tool you like on &lt;a href="http://localhost:4000/products"&gt;http://localhost:4000/products&lt;/a&gt; &lt;br&gt;&lt;br&gt;
The response should display &lt;code&gt;a product will be created&lt;/code&gt; along with your content.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Perfect! 🎉 Let's move on&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Dynamic routes
&lt;/h2&gt;

&lt;p&gt;1. Create a new file with the name &lt;code&gt;[id]&lt;/code&gt; inside the &lt;code&gt;product&lt;/code&gt; folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── api/
│  ├── products/
│  │  ├── ...
│  │  └── [id].js &amp;lt;-
│  └── index.js
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2. Fill it the same way as you did before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Add the `routeParams` argument as the final argument to the function. This argument will contain&lt;/span&gt;
  &lt;span class="c1"&gt;// all the taken route parameters.&lt;/span&gt;
  &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;routeParams&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;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;routeParams&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`product &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; info`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3. Open a browser and go to &lt;a href="http://localhost:4000/products/123"&gt;http://localhost:4000/products/123&lt;/a&gt;. &lt;br&gt;&lt;br&gt;
The page should display a message: &lt;code&gt;product 123&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Alright, let's make it more sophisticated.&lt;/p&gt;

&lt;p&gt;Say, we want to address the following case:&lt;br&gt;
&lt;code&gt;/catalog/tag-1/tag-2/tag-n&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;4. Create a &lt;code&gt;catalog&lt;/code&gt; folder with &lt;code&gt;[[...categories]].js&lt;/code&gt; inside.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── api/
│  ├── catalog/
│  │  ├── ...
│  │  └── [[...categories]].js &amp;lt;-
│  ├── index.js
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And add a single &lt;code&gt;get&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;routeParams&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;categories&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;routeParams&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// This type of route also covers just "/catalog"&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;categories&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;all products&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`get products that have such tags: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5. Open a browser and go to &lt;a href="http://localhost:4000/catalog/men/sneakers/nike"&gt;http://localhost:4000/catalog/men/sneakers/nike&lt;/a&gt;. &lt;br&gt;&lt;br&gt;
The page should display a list of categories: men, sneakers, nike&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🥁 That's it!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://danilqa.github.io/node-file-router/docs/route-matching"&gt;Discover more capabilities of the routing system&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://danilqa.github.io/node-file-router/docs/route-matching"&gt;Configuration and More Details&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Danilqa/node-file-router/tree/main/examples"&gt;Examples with Express, WebSockets, ECMAScript, and more&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://danilqa.github.io/node-file-router/docs/custom-adapter"&gt;How to create your own custom adapter and use it with your favourite framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://danilqa.github.io/node-file-router/docs/use-with-bun/"&gt;Usage with Bun&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>node</category>
      <category>routing</category>
    </item>
    <item>
      <title>Selecting the Right Dependencies: A Comprehensive Practical Guide</title>
      <dc:creator>Daniil Sitdikov</dc:creator>
      <pubDate>Sun, 16 Apr 2023 11:14:22 +0000</pubDate>
      <link>https://dev.to/dsitdikov/selecting-the-right-dependencies-a-comprehensive-practical-guide-1ilp</link>
      <guid>https://dev.to/dsitdikov/selecting-the-right-dependencies-a-comprehensive-practical-guide-1ilp</guid>
      <description>&lt;p&gt;If you were a chef at an upscale Michelin-starred restaurant, would you buy vegetables and meat from random, unverified sources? The cost of almost any average project is measured in hundreds of thousands or even millions of dollars. I believe that our industry should have the same approach as restaurants.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The first question to ask yourself right away: do you really need a new dependency? Could the problem be solved using the current environment, such as the language or installed libraries?&lt;/strong&gt; For example, there's no need to install an additional library to generate UUIDs. Node.js and browsers &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Crypto" rel="noopener noreferrer"&gt;support&lt;/a&gt; it out of the box: &lt;code&gt;crypto.randomUUID()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The second question: do you need the entire library?&lt;/strong&gt; For instance, if you only need a dropdown, is it worth installing something like Bootstrap? Perhaps it's better to limit yourself to a single, focused library with an &lt;a href="https://www.radix-ui.com/docs/primitives/components/dropdown-menu" rel="noopener noreferrer"&gt;unstyled dropdown component from Radix UI&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;Okay. We have a few candidates in mind. So, how do we choose the right one?&lt;/p&gt;

&lt;p&gt;A beautifully formatted README? A well-known name? More forks, stars, and downloads than others? Unfortunately, these factors alone aren't enough. Here, we are selecting a service provider. We want any issues that arise to be resolved quickly, the functionality to remain up-to-date, and, above all, for the service to be safe and reliable. Simple external metrics don't always indicate the quality or long-term suitability. Before installing what we've found on the repository catalog, it would be great to visit the GitHub repository and analyze its content.&lt;/p&gt;

&lt;p&gt;I have prepared a list of criteria that I have been using for the last few years. I hope they will help you choose the most suitable libraries. It's essential to consider them comprehensively and, in some cases, make compromises when choosing between them.&lt;/p&gt;

&lt;p&gt;Disclaimer: I am not criticizing the libraries mentioned below or trying to discourage their use. In some instances, I have intentionally omitted names to focus on the criterion example while maintaining factual accuracy.&lt;/p&gt;

&lt;h1&gt;
  
  
  1. Security
&lt;/h1&gt;

&lt;p&gt;How safe is it to use? It may sound like fiction, but yes, dependencies can be dangerous. For example, an interesting feature &lt;a href="https://github.com/advisories/GHSA-97m3-w2cp-4xx6" rel="noopener noreferrer"&gt;was added&lt;/a&gt; to a library with 500k downloads: it tries to replace all files on the computer with ❤️ if your IP address falls within a specific range.&lt;/p&gt;

&lt;p&gt;An interesting fact is that this dependency was used in &lt;a href="https://github.com/vuejs/vue-cli/issues/7054" rel="noopener noreferrer"&gt;vue-cli&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxkenly2glr980o40jmmx.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%2Fxkenly2glr980o40jmmx.png" alt="Screenshot with issue description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How can we discover such issues? Check the issues page, or try googling by the library's name. Usually, such information surfaces quickly. Also, Snyk can be used as an automated tool for security checks.&lt;/p&gt;

&lt;h1&gt;
  
  
  2. Maintenance
&lt;/h1&gt;

&lt;p&gt;When was the last release? How often do releases occur? Regular releases ensure that issues are resolved and updates support constantly changing technologies. In the context of mobile development, regular releases also ensure that the project compiles successfully.&lt;/p&gt;

&lt;p&gt;Here's an example from the world of Go: the authors of a library with 18.2K stars decided to stop maintaining their dependency and archived it. This means that, in a few years, the lack of support and updates will become a problem. Now imagine installing a similar dependency without checking GitHub first. It's sort of checking the expiration date of products.&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%2Fd6p22zofv2yy19b7mp2j.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%2Fd6p22zofv2yy19b7mp2j.png" alt="Screenshot with archived library"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is an example of frequent good releases:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F63ke3sg4ju42n5cx9eao.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%2F63ke3sg4ju42n5cx9eao.png" alt="Screenshot with releases"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  3. Open / Closed Issues
&lt;/h1&gt;

&lt;p&gt;1.  What is the ratio of open issues to closed ones? How willing are the authors to accept changes? It's possible that you might need to contribute something someday. For instance, this library is quite popular and has a 98% percentage of closed issues. Only 18 are open.&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%2Feiuvlv0ph6el2mbyumgu.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%2Feiuvlv0ph6el2mbyumgu.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2.  How quickly are critical issues resolved? Once, I chose an ORM with 31k stars, but at some point, we encountered a problem that blocked us. We had to look for workarounds and eventually switch to another solution. Unfortunately, almost four years have passed, and the problem still hasn't been resolved.&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%2F12uoyatqykjbf8uonkm5.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%2F12uoyatqykjbf8uonkm5.png" alt="Screenshot with old issue"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Such issues can be identified by sorting by the most commented.&lt;/p&gt;

&lt;p&gt;3.  Has the contribution process been organized by the creators? Is there a clear, defined workflow in place? For example, the creators of Next.js even recorded a 40-minute video about their contribution process.&lt;/p&gt;

&lt;h1&gt;
  
  
  4. Code Quality
&lt;/h1&gt;

&lt;p&gt;Yes, there may be a lot of code, but it's always possible to examine its different parts. How is the project organized? Is it understandable, and well-structured, and do good practices apply? The worse the code is written, the higher the likelihood of the project's demise in the future. Many small candidates were eliminated at this stage for me.&lt;/p&gt;

&lt;h1&gt;
  
  
  5. Test Coverage
&lt;/h1&gt;

&lt;p&gt;Does the library have tests? What is the test coverage? How were the tests written? Even if maintainers review merge requests, there is a chance that something may be overlooked. There are a lot of different people contribute to the library. Normally, test coverage information is displayed on badges at the top of the repository. However, if it is not, we can always search for tests in the project. For instance, the &lt;code&gt;formatjs&lt;/code&gt; library family has excellent test coverage and includes various types of tests.&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%2Fniue5ktxtw73bezyz18i.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%2Fniue5ktxtw73bezyz18i.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  6. Library Size
&lt;/h1&gt;

&lt;p&gt;Mobile applications often have large dependency sizes and the whole app can be even more than 200MB, which can cause issues during cellular network downloads and consume a lot of storage space. This is especially problematic for front-end CSR apps, where slow internet speeds can dramatically increase loading times.&lt;/p&gt;

&lt;p&gt;For web projects, there is a great tool to determine package sizes: &lt;a href="https://bundlephobia.com" rel="noopener noreferrer"&gt;Bundlephobia&lt;/a&gt;. Of course, server-side rendering and tree shaking might reduce the size, but this needs to be always verified.&lt;/p&gt;

&lt;p&gt;A popular example is date manipulation libraries. The functionality provided by &lt;strong&gt;dayjs&lt;/strong&gt; (2.9KB) might be sufficient, eliminating the need to install &lt;strong&gt;moment.js&lt;/strong&gt; (72.1KB) or &lt;strong&gt;date-fns&lt;/strong&gt; (26.8KB).&lt;/p&gt;

&lt;h1&gt;
  
  
  7. Number of Dependencies
&lt;/h1&gt;

&lt;p&gt;All the points listed above are multiplied, to some extent, by the number of dependencies in the entire dependency tree of the project. A great tool to check the complete dependency tree: &lt;a href="https://npm.anvaka.com" rel="noopener noreferrer"&gt;https://npm.anvaka.com&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  8. License
&lt;/h1&gt;

&lt;p&gt;Have you ever thought about this? I hadn't either. For example, the MIT and Apache 2.0 licenses allow for the free use of libraries in commercial projects, while some GPL v2 licenses have specific requirements and restrictions. In one of our projects, we had a table prepared by a lawyer to check all our dependency tree's licenses. So if you see something unusual in a license, it's better to consult a lawyer to avoid problems during an audit. We can extract all licenses from existing npm dependencies using the &lt;a href="https://www.npmjs.com/package/legally" rel="noopener noreferrer"&gt;legally&lt;/a&gt; utility or the same tool mentioned above in the previous point. &lt;/p&gt;

&lt;p&gt;P.S. I'm not a lawyer, and this wasn't legal advice. It's a rare and specialized case that something might not be suitable due to the license, but it's still possible.&lt;/p&gt;

&lt;h1&gt;
  
  
  The End!
&lt;/h1&gt;

&lt;p&gt;Thank you for reading my article! The key point of it was to show real-world examples that shallow and fast decision-making sometimes can lead not to the best option. By considering these criteria, you will be able to make a more informed decision.&lt;/p&gt;

&lt;p&gt;Please feel free to leave any comments or suggestions you may have. Don't hesitate to share your experience in the comments as well. Your likes and comments inspire me to write new articles. Happy cooking :)&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>opensource</category>
      <category>github</category>
    </item>
    <item>
      <title>Unit Testing Components with Jest in React Native. Approaches</title>
      <dc:creator>Daniil Sitdikov</dc:creator>
      <pubDate>Fri, 07 Apr 2023 13:04:11 +0000</pubDate>
      <link>https://dev.to/dsitdikov/unit-testing-components-with-jest-in-react-native-approaches-2d57</link>
      <guid>https://dev.to/dsitdikov/unit-testing-components-with-jest-in-react-native-approaches-2d57</guid>
      <description>&lt;p&gt;If you are interested in technical details, how it integrates into the project and common problems resolutions: &lt;a href="https://medium.com/@dsitdikov/unit-testing-components-with-jest-in-react-native-setup-and-trouble-resolutions-ad2d2e3f909d"&gt;read this article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I've used &lt;a href="https://github.com/callstack/react-native-testing-library"&gt;react-native-testing-library&lt;/a&gt;. It has similar API as react-testing-library but includes fewer abilities. &lt;a href="https://callstack.github.io/react-native-testing-library/docs/api"&gt;A full API is located here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's get started with a simple example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; A user inputs some title&lt;/li&gt;
&lt;li&gt; A component finds 1 the most relevant item.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Search&lt;/span&gt;
    &lt;span class="na"&gt;testID&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'search-input'&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;searchQuery&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;onChangeText&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onSearchQueryChanged&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;sup&gt;In this article, I don't use the unnecessary code (such as the whole component, logic of the filter, etc.)&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;There are 2 approaches to testing:&lt;/p&gt;

&lt;h1&gt;
  
  
  Snapshots
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should rerender component with filtered panels after search text input has been changed&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="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;toJSON&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getByTestId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
       &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt; &lt;span class="na"&gt;store&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Cars&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;fireEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;changeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;search-input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Porsche Macan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;toJSON&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;toMatchSnapshot&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Good reliability. It covers the whole state of component: makeup, small details, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  It could be huge like in an example below, and it's hard to find and change something (if business-requirements has been changed and you wanna update your snapshot for next test-driven development).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wxNOpmB7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pmxa2n27c22e7ssqinye.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wxNOpmB7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pmxa2n27c22e7ssqinye.gif" alt="A huge snapshot" width="800" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Query
&lt;/h1&gt;

&lt;p&gt;It finds a node or list of nodes in the tree of some component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should rerender component with filtered panels after search text input has been changed&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="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;toJSON&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getByTestId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt; &lt;span class="na"&gt;store&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Cars&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;fireEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;changeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;search-input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Porsche Macan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;queryByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Porsche Macan S 2019, London&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeTruthy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;sup&gt;An example of testing by node's content&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  It looks like more as specification and easy to read and understand&lt;/li&gt;
&lt;li&gt;  It's ready for use for TDD&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  It's a very small point of testing, and it can't guarantee that bugs in the resulting state of the component will be found.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is a full API (at the moment of writing the article, 2019) of query functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;queryByName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactType&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;queryByType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;P&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;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ComponentType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;P&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;queryByText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;queryByPlaceholder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;queryByProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;queryByTestId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;testID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;queryAllByName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactType&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;queryAllByType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;P&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;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ComponentType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;P&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;queryAllByText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;queryAllByPlaceholder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;queryAllByProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>reactnative</category>
      <category>testing</category>
      <category>react</category>
      <category>jest</category>
    </item>
    <item>
      <title>Unit Testing Components with Jest in React Native. Setup and Trouble Resolutions</title>
      <dc:creator>Daniil Sitdikov</dc:creator>
      <pubDate>Fri, 07 Apr 2023 06:22:16 +0000</pubDate>
      <link>https://dev.to/dsitdikov/unit-testing-components-with-jest-in-react-native-setup-and-trouble-resolutions-31c9</link>
      <guid>https://dev.to/dsitdikov/unit-testing-components-with-jest-in-react-native-setup-and-trouble-resolutions-31c9</guid>
      <description>&lt;h1&gt;
  
  
  Setup
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Jest configuration
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;I removed properties not related to react-native (such as testMatch, testUrl, etc.)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"jest"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"preset"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-native"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"moduleNameMapper"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"styled-components"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"styled-components/native"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"transform"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"^.+\\.js$"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;rootDir&amp;gt;/node_modules/react-native/jest/preprocessor.js"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Also, it could be jest.config.js (depends on your project organization)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Mocking store
&lt;/h2&gt;

&lt;p&gt;I used &lt;code&gt;redux-mock-store&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;1. For decrease duplicate code &lt;a href="https://jestjs.io/docs/manual-mocks"&gt;I put it into &lt;strong&gt;mocks&lt;/strong&gt;.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;As an example of middleware, there is a thunk here. You could use any.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;configureStore&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;redux-mock-store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;thunk&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;redux-thunk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;middlewares&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;thunk&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;configureStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;middlewares&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;mockStore&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;sup&gt;Redux mock store located in &lt;strong&gt;mocks&lt;/strong&gt; folder&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;2. I've created a separate render component function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { render } from 'react-native-testing-library';
import { Provider } from 'react-redux';
import * as React from 'react';

export function renderComponent(content, store) {
    return render(&amp;lt;Provider store={store}&amp;gt;{content}&amp;lt;/Provider&amp;gt;);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;sup&gt;Receives component to render as content and state of the store&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;3. And just use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Catalog&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;mockStore&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;redux-mock-store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../../dev/spec-helpers/state&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;renderComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../../dev/spec-helpers/render-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Catalog&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="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="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mockStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should render component in init state&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="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="nx"&gt;component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;renderCatalog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toJSON&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;toMatchSnapshot&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;renderCatalog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;extendedProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;extendedProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;resultId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;P39&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="nf"&gt;renderComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Catalog&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;, store&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;sup&gt;Fragment of some component testing&lt;/sup&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  3. Add more readable expect method "toBeFound"
&lt;/h1&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;expect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;expect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nf"&gt;toBeFound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;received&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="nx"&gt;received&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Target node doesn&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;t exist&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;sup&gt;Extension of expect-file&lt;/sup&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Create a script config/jest/expect.js&lt;/li&gt;
&lt;li&gt; Add it to setupFiles in your jest config:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should correctly render last-date laboratory result&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="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;getByText&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;renderHomeResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Urogenital swab&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeFound&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Inhibin B&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeFound&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;h1&gt;
  
  
  Trouble resolutions:
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. ES6 in node_modules
&lt;/h2&gt;

&lt;p&gt;Error in using of es6+ libraries from &lt;code&gt;node_modules&lt;/code&gt; such it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;/Users/dsitdikov/Projects/experimentx-dx-app/node_modules/react-native/jest/mockComponent.js:20 static displayName = 'Component'; ^ SyntaxError: Unexpected token =&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Solution:
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;transformIgnorePatterns&lt;/code&gt; in jest config:&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="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;transformIgnorePatterns&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;rootDir&amp;gt;/node_modules/(?!react-navigation|react-native|rn-apple-healthkit|rn-fetch-blob)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;sup&gt;A fragment of the package.json &amp;gt; jest&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;By default, jest transformIgnorePatterns has &lt;code&gt;&amp;lt;rootDir&amp;gt;/node_modules&lt;/code&gt; and ignores all node_modules. So that it transforms each file from es6+ to understandable es5 except &lt;code&gt;node_modules&lt;/code&gt;. Some modules are not in es6, and we should say ignore all &lt;code&gt;node_modules&lt;/code&gt; except &lt;code&gt;react-navigation&lt;/code&gt;, &lt;code&gt;react-native&lt;/code&gt;, &lt;code&gt;rn-apple-healthkit&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://jestjs.io/docs/en/configuration#transformignorepatterns-array-string"&gt;You also can read about it in jest documentation.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Modules don't work in jest.
&lt;/h2&gt;

&lt;p&gt;Something like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;TypeError: Cannot read property 'RNFSFileTypeRegular' of undefined | import RNFS from 'react-native-fs';&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Solution:
&lt;/h3&gt;

&lt;p&gt;It's ok. Just:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Create &lt;code&gt;mocks.js&lt;/code&gt; in your project&lt;/li&gt;
&lt;li&gt; Add &lt;code&gt;setupFiles&lt;/code&gt; in your jest configuration
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"setupFiles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;rootDir&amp;gt;/config/jest/mocks.js"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;sup&gt;Fragment of package.json &amp;gt; jest&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;3. For each unnecessary and unworking module write the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native-camera&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;sup&gt;An example of a mock some module&lt;/sup&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Error in using mocked default exported modules.
&lt;/h2&gt;

&lt;p&gt;An error could be such this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;TypeError: Cannot read property 'dirs' of undefined&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Solution:
&lt;/h3&gt;

&lt;p&gt;Just add this to your mocks file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rn-fetch-blob&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;__esModule&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="na"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="na"&gt;dirs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
               &lt;span class="na"&gt;DocumentDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&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="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A fragment of mocks.js file&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>react</category>
      <category>testing</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Master the Senior Developer Role: 7 Criteria to Follow</title>
      <dc:creator>Daniil Sitdikov</dc:creator>
      <pubDate>Fri, 07 Apr 2023 05:51:43 +0000</pubDate>
      <link>https://dev.to/dsitdikov/how-to-master-the-senior-developer-role-7-criteria-to-follow-4hp3</link>
      <guid>https://dev.to/dsitdikov/how-to-master-the-senior-developer-role-7-criteria-to-follow-4hp3</guid>
      <description>&lt;p&gt;It was a difficult and challenging journey. Many times, I believed that I had reached a senior level, but my tech leaders thought otherwise. The issue was that none of them could provide clear guidance on how to progress in the right direction. Each one had a different opinion. It took me five years to finally overcome this hurdle. I decided to help others who are looking for clear answers and guidance to create an action plan. I am confident that you can achieve your goals faster and with less difficulty.&lt;/p&gt;

&lt;p&gt;After reviewing these criteria, you may realize that your current company is undervaluing you. In this case, you can confidently ask for a promotion or look for a new job. If you are already a senior developer and are unsure whether other companies will evaluate you in the same way, this article will help you identify your growth areas and quickly level up. On average, outsourcing companies often have lower requirements for senior developers because they can sell their services to clients at a higher price. In contrast, product companies try to optimize costs and may undervalue their developers.&lt;/p&gt;

&lt;p&gt;So, let's begin!&lt;/p&gt;

&lt;p&gt;After performing an analysis, I identified seven essential criteria. Every business aims to spend less and earn more. Therefore, money is at the core of each criterion.&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%2Fhw4j3v0h8cdl820pfaic.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhw4j3v0h8cdl820pfaic.jpg" alt="You can create a radar chart like this and track your progress."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Planning and pragmatism
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You manage risks and think strategically. You know when to implement solutions quickly and straightforwardly, recognizing that a certain aspect of the project may no longer exist tomorrow. And when you need to invest time in architecture and profoundly work everything out so that it is fast and reliable in the future.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You have a vision for how the project will develop in the future, and you make architectural decisions based on that vision.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You are capable of independently decomposing large features and then planning the development in an iterative approach. This way, the business can start benefiting as soon as possible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can estimate the time required for a task in a way that doesn't lead to working overnight and missing deadlines. You can take risks into account and don't let the business down. If something is going completely wrong, you timely suggest alternative solutions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You have a good understanding of the current development process and can identify its shortcomings. Based on this knowledge, you can suggest improvements to make the process more efficient and effective.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Speed
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You possess highly advanced skills. What a junior employee might accomplish in a day, you can complete in just a couple of hours. You rarely need to search for information on how a programming language or library functions work. With your extensive experience, intuition guides you towards solutions with ease.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You know how to quickly and consciously debug code.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Accuracy
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You can easily and quickly account for all possible edge cases by considering scenarios such as a large amount of data, unexpected user behavior, or third-party service failures. By anticipating and planning for these situations, you can ensure that the data is saved and users have a positive experience, even if a server goes down completely.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your code is clean, understandable, and minimal. The style is consistent, and the naming is clear.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You understand how to organize a project by considering layers, creating clear abstractions, ensuring modularity, and determining how components are connected to one another.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The number of bugs in production tends toward zero. The money the business would have spent on fixing bugs and retaining unhappy users is already included in your salary.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your code works efficiently. You know about data structures and their differences, and you understand how to achieve fast and smooth product performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ideally, you can solve complex problems with simple and inexpensive solutions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You possess a high level of expertise in the tools and technology you use.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Autonomy
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You no longer need help with code or technology.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You will communicate directly with the business to clarify requirements and work out necessary features for implementation.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Broad knowledge
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You stay up-to-date with the development of the technologies you use, including new features of the language and frameworks. You have already subscribed to various email newsletters and follow industry leaders on Twitter.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You have worked on several projects with different teams, solving various problems and using a variety of technologies. As a result, you have gained an understanding of the pros and cons of different approaches.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Battle experience
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You can integrate the best practices: testing, CI/CD, error monitoring, and so on. By the way, I wrote about this in another article: &lt;a href="https://dev.to/dsitdikov/7-proven-practices-to-boost-development-speed-and-project-quality-122k"&gt;7 Proven Practices to Boost Development Speed and Project Quality&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You have created projects from scratch, guiding them through all stages: from hypothesis validation to a fully-fledged production application.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Knowledge sharing
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You can mentor less experienced colleagues.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You conduct high-quality code reviews: you notice not only the absence of space in a line but also think in terms of solving the problem as a whole.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ideally, but not necessarily, you do this publicly: write articles, teach, engage in mentoring on special platforms, or organize workshops. Receiving external validation is a huge plus.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In conclusion, you can discuss the possibility of including these criteria in your personal development plan with your manager, or ask your colleagues to evaluate you. This can be a valuable way to continue improving in your role.&lt;/p&gt;

&lt;p&gt;Thank you for reading my article! I hope my guide was helpful. Feel free to leave any comments or suggestions you may have, and don't hesitate to share your success stories in the comments. Also, your likes and comments inspire me to write new articles.&lt;/p&gt;

</description>
      <category>career</category>
      <category>productivity</category>
      <category>programming</category>
      <category>guide</category>
    </item>
    <item>
      <title>7 Proven Practices to Boost Development Speed and Project Quality</title>
      <dc:creator>Daniil Sitdikov</dc:creator>
      <pubDate>Mon, 27 Mar 2023 12:54:18 +0000</pubDate>
      <link>https://dev.to/dsitdikov/7-proven-practices-to-boost-development-speed-and-project-quality-122k</link>
      <guid>https://dev.to/dsitdikov/7-proven-practices-to-boost-development-speed-and-project-quality-122k</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;All of these points can be applied to mobile development, web frontend, and backend. I have gathered these practices from different teams and through the issues I faced over the last 6 years. These practices can be especially helpful when you build a project from scratch. Some of them may suit you perfectly, while others may not. If you have your own approaches and different experiences, I would be happy if you share them here. By the way, if you are a middle or junior developer seeking a promotion, implementing these practices in your team can really help. Let’s go!&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Mocking backend responses until it’s ready
&lt;/h2&gt;

&lt;p&gt;In a standard software development process, when a new feature request comes from the business, it is distributed among several teams: front-end, back-end, and mobile app development. Then, each team proceeds with planning and task decomposition. But what if the back-end team requires significantly more time to develop their part? What if they can deliver endpoints only once a week? The backend becomes a bottleneck. The mobile and front-end development teams end up working like this: "Oh, the back-end has already implemented this. Let me take this task." Then, they take a break, switch their context to another feature, and the cycle continues. This leads to fatigue, decreased speed, and reduced quality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; agree on a contract with the back-end team and mock all requests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3Jrwijjf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q6mtx6ihdl54b5vh249o.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3Jrwijjf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q6mtx6ihdl54b5vh249o.jpg" alt='In the classic approach, we have a gap between tasks. In the "mock approach", all work is performed as a flow' width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;1. Coordinate with the back-end team on the endpoints and entities.&lt;/p&gt;

&lt;p&gt;2A. Implement backend API with stub responses. The Faker library can help with sample data generation.&lt;/p&gt;

&lt;p&gt;2B. Or implement stubs on the frontend. This can be an object with data directly in the code. For example, in Node.js, you can efficiently implement this using dynamic imports and avoid increasing the bundle size:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;getUser&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="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../assets/mocks/users&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userById&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deserializeUser&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;This also can be a mock HTTP service that fetches JSON files from assets instead of making real requests.&lt;/p&gt;

&lt;p&gt;3. Hide the feature behind a feature flag.&lt;/p&gt;

&lt;p&gt;4. When the backend is ready, switch to the actual API if you used the front-end stubs approach, and verify that everything works as expected. And turn this feature on.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Feature flag
&lt;/h2&gt;

&lt;p&gt;Now, as you probably noticed, in the previous section, I mentioned feature flags. In a nutshell, feature flags a.k.a feature toggles allow developers to turn features on or off in a live environment. There are also a couple of cases when they are useful: rolling out new features gradually, performing A/B testing, enabling beta features, and implementing hotfixes.&lt;/p&gt;

&lt;p&gt;We use Gitlab for storing feature flags. It’s a dedicated repository that is consumed by both backend and frontend projects. The great news is that it has a user-friendly UI, thus product managers can manage features by themselves. Previously, we used to use feature flags for each project repository separately. However, this approach didn’t provide the ability to disable features for the whole product at once. So we move everything to the single repository.&lt;/p&gt;

&lt;p&gt;In the code, it looks quite simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;In the project, we fetch all active feature flags. As under the hood, Gitlab is based on &lt;a href="https://www.getunleash.io/"&gt;Unleash&lt;/a&gt; (feature toggle service), we use its official client.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And then, just put &lt;code&gt;if features.YOUR_FEATURE&lt;/code&gt; in the code which needs to be hidden.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can expand the use cases by adding different values in the feature flag. For instance, by adding the color value or the discount value.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  3. Monitoring errors for tracking issues in a production environment
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0Nm43wSf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sxbhjq3ln7v53skp1tw0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0Nm43wSf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sxbhjq3ln7v53skp1tw0.jpg" alt="Image description" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When our product transitioned from the MVP stage to a production application, we were concerned that users would get errors that we couldn't reproduce and might not even be aware of. After researching error-tracking tools, we settled on Sentry. The experience was positive. And now, let’s go through some important nuances.&lt;/p&gt;

&lt;h3&gt;
  
  
  Useless Errors
&lt;/h3&gt;

&lt;p&gt;Under the hood, any uncaught exception will be tracked. As the application and the number of users grow, the number of errors can become so overwhelming that it is getting nearly impossible to notice anything truly important. Sentry can turn into a dumpster if you don't filter out the unnecessary stuff. For example, events like canceled requests, connection errors, and errors from connected scripts are utterly useless and will only spam your work email with notifications. As a solution, you can add filters to the configuration. To do this, simply define a &lt;code&gt;beforeSend&lt;/code&gt; callback and put it in your &lt;code&gt;sentryPackage.init&lt;/code&gt;. In this callback, you can analyze each caught error and then discard it (by returning null) if it's useless. Here's an example of a filter that excludes unnecessary errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;beforeSend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;hint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;originalException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;externalScripts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gtm.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Google Tag Manager&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;watch.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// X Analytics&lt;/span&gt;
  &lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;|&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errorsToIgnore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;AxiosError&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ERR_NETWORK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="nx"&gt;AxiosError&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ECONNABORTED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="nx"&gt;AxiosError&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ETIMEDOUT&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;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isCancel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
      &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;errorsToIgnore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
      &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;externalScripts&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Include more data for better debugging
&lt;/h3&gt;

&lt;p&gt;By default, Sentry might not include the content of the request and response in the error report. Without this information, proper debugging is impossible. Fortunately, in the &lt;code&gt;beforeSend&lt;/code&gt; handler, we can include this information.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;beforeSend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;hint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;originalException&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;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isAxiosError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;responseURL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extra&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="p"&gt;...(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extra&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{}),&lt;/span&gt; 
        &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="nx"&gt;request&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;event&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Filter Sensitive Information
&lt;/h3&gt;

&lt;p&gt;Data such as passwords, email addresses, and keys should not be included in the error content. Sentry has a built-in mechanism for hiding this type of information. You can configure it in the security settings. Moreover, you can also remove something in the event object in &lt;code&gt;beforeSend&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Standalone Solution
&lt;/h3&gt;

&lt;p&gt;If the nature of your business prohibits storing this kind of data on a server somewhere else, Sentry offers the ability to use it on your own servers.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Tracing
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IhK1oysI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dskx107sb8xfi1beqwk3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IhK1oysI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dskx107sb8xfi1beqwk3.jpg" alt="The path of trace ID" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imagine a situation where you successfully capture an error in Sentry, but the information in the description is insufficient. You turn to logs, but how can you identify the specific error among thousands of requests and even more log lines per second? How can you distinguish the correct ones, construct the request chain, and pinpoint the exact error, especially when your business has multiple teams and integrates with other services? This is where tracing comes into play.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Tracing provides a complete diagram of invocations and identifies the precise method that failed, even when you have asynchronous communication performed by a message broker.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It allows you to easily determine which side the error occurred on when integrating with different teams.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tracing is also useful for performance debugging. For instance, it can help clarify whether rendering takes longer or if a method in a microservice is not optimized enough.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In our specific implementation, we used &lt;a href="https://www.jaegertracing.io/"&gt;Jaeger&lt;/a&gt;, which is based on the OpenTracing API.&lt;/p&gt;

&lt;p&gt;In a nutshell, each request and all its method calls are tagged with a unique label. Each label has a reference to its parent and some metadata. The structure of this number depends on the implementation but as for OpenTracing you can read how it works and get familiar with terms like span, reference, child, parent, and so on the &lt;a href="https://github.com/opentracing/specification/blob/master/specification.md"&gt;official repository page&lt;/a&gt;. In the real life, tracing luckily will rarely be used. However, in these rare accidents, it can save you time.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Performance optimization
&lt;/h2&gt;

&lt;p&gt;When we implemented the MVP of the fintech app, we had a quite complicated form. At that time, I was still young and inexperienced. And eventually, we realized that our project was slowing down. We had to spend additional hours figuring out the reason. We had many unnecessary re-renders because we ignored basic rules related to props in React. I wanted to do everything possible to avoid such situations in the future. So, I added to the project linters like &lt;a href="https://github.com/cvazac/eslint-plugin-react-perf"&gt;this&lt;/a&gt; and an additional starting configuration to package.json to run &lt;a href="https://github.com/welldone-software/why-did-you-render"&gt;why-did-you-render&lt;/a&gt;. In short, this plugin issues a warning if something is re-rendered unnecessarily and suggests how to avoid it. Also, we included running &lt;a href="https://github.com/GoogleChrome/lighthouse/blob/main/docs/headless-chrome.md"&gt;Lighthouse&lt;/a&gt; in headless mode. Some people say that premature optimizations are bad, but for me, it's a principle: do it right from the start.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Defined code style for all team projects
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eP0Dqscr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a5mxzbeaxof9ip3919jv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eP0Dqscr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a5mxzbeaxof9ip3919jv.jpg" alt="Image description" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You've likely heard of the &lt;a href="https://en.wikipedia.org/wiki/Broken_windows_theory"&gt;broken windows theory&lt;/a&gt;. If there's one broken window in a building and no one replaces it, eventually there won't be a single intact window left in that building.&lt;/p&gt;

&lt;p&gt;The fewer rules and controls there are in a project, the greater the temptation to write low-quality code or to write it in an entirely different style. Inconsistent code increases the time it takes to understand it, while clear, familiar, and concise code allows for quick reading. In one of our teams, we described the coding style in &lt;a href="https://eigenspace.gitbook.io/dev-standards/common"&gt;one place&lt;/a&gt;. As a great starting point, you can take &lt;a href="https://prettier.io/"&gt;Prettier&lt;/a&gt; or &lt;a href="https://github.com/airbnb/javascript"&gt;Airbnb code style&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Regression tests
&lt;/h2&gt;

&lt;p&gt;A significant amount of literature has already been written about the different types of tests, approaches, and how to write them properly. The only thing worth mentioning here is that no production application can survive without regression testing. That's why we focused all our efforts on creating a comprehensive end-to-end testing framework and based on it, we wrote tests that are linked with BDD scenarios and user stories. We used the &lt;code&gt;Page Object&lt;/code&gt; pattern to organize our code and the &lt;a href="https://playwright.dev/"&gt;Playwright&lt;/a&gt; framework for interacting with the browser. To test across different browsers, including Safari, you can use a solution called &lt;a href="https://aerokube.com/moon/latest/"&gt;Moon&lt;/a&gt;. It can be deployed on one of your servers.&lt;/p&gt;

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

&lt;p&gt;Thank you for taking the time to read this article! In conclusion, this article highlights key software engineering practices that enhance development processes and code quality. By adopting techniques such as backend response mocking, feature flags, error monitoring, performance optimization, code style standards, regression tests, and tracing, you can create more efficient and reliable software. Let's continue to improve our software and stay in touch! :)&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>frontend</category>
      <category>backend</category>
      <category>performance</category>
    </item>
    <item>
      <title>8 the most essential tested React Native libraries that will skyrocket your app 🚀</title>
      <dc:creator>Daniil Sitdikov</dc:creator>
      <pubDate>Sun, 30 Jan 2022 16:44:37 +0000</pubDate>
      <link>https://dev.to/dsitdikov/8-the-most-essential-tested-react-native-libraries-that-will-skyrocket-your-app-2b3d</link>
      <guid>https://dev.to/dsitdikov/8-the-most-essential-tested-react-native-libraries-that-will-skyrocket-your-app-2b3d</guid>
      <description>&lt;p&gt;I have an interesting relationship with React Native: it’s like an emotional rollercoaster, to be honest. Sometimes random compilation errors in my terminal make me cry and whine. But, in general, it’s amazing. Huge thanks Meta for this technology. In this article, I want to overview selected libraries that may improve any application.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;a href="https://github.com/react-navigation/react-navigation"&gt;React-Navigation&lt;/a&gt; for the awesome native animated transitions
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OXzYwX_---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/krofmpw1ard2gh3zba6q.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OXzYwX_---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/krofmpw1ard2gh3zba6q.gif" alt="A real-world example from my side-project" width="800" height="555"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Basic screen navigation transition as we got used to them in front-end apps seems to be boring. Let's do that them native, more smoothly, more handsome. By the way, it also supports native header and tabs.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;a href="https://github.com/lottie-react-native/lottie-react-native"&gt;Lottie&lt;/a&gt; for the sophisticated animated images
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--p-deLWHv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uon8wsjn1ehc04sxpk9k.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--p-deLWHv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uon8wsjn1ehc04sxpk9k.gif" alt="Just a random animation from LottieFiles" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can live up your app with the interacted pictures. Lottie is a JSON-based file with some animation. This format is common and designed to be used on many platforms. You can create your own, ask a motion designer, or find something already existing. Just take a peer at the &lt;a href="https://medium.com/r/?url=https%3A%2F%2Flottiefiles.com%2F"&gt;LottieFiles catalogue&lt;/a&gt; and you will better understand what do I mean.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;a href="https://github.com/junina-de/react-native-haptic-feedback"&gt;Haptic-Feedback&lt;/a&gt; for the enjoyable micro-vibrations during user actions
&lt;/h3&gt;

&lt;p&gt;It will involve the real-world experience in the digital one by providing touching feedback. However, be careful about overusing it. More information about use cases is described in &lt;a href="https://developer.apple.com/design/human-interface-guidelines/ios/user-interaction/haptics/"&gt;Apple's guidelines&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;a href="https://github.com/react-native-svg/react-native-svg"&gt;Svg&lt;/a&gt; for any vector graphic like icons or pictures
&lt;/h3&gt;

&lt;p&gt;The main drawback is that you have to convert SVG elements to the library's components firstly.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. &lt;a href="https://github.com/react-native-async-storage/async-storage"&gt;AsyncStorage&lt;/a&gt; with the same API LocalStorage has
&lt;/h3&gt;

&lt;p&gt;Sometimes we need to store the user's settings, cache downloaded data, save sessions and so on. The library is built to satisfy this need. By the way, if for some reason you need a synchronized store you can use the alternative synchronized one.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. &lt;a href="https://github.com/MinaSamir11/react-native-in-app-review"&gt;In-App-Review&lt;/a&gt; for the user's feedback request
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--U8w6g85T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d2m4duav9fe68uelpnz7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U8w6g85T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d2m4duav9fe68uelpnz7.png" alt="Image description" width="750" height="733"&gt;&lt;/a&gt;&lt;br&gt;
The easiest and cheapest way to increase the app's rating is just to ask users about that. I am sure that you came across it in native apps after the user scenario with a positive outcome. Good news: it works for Android as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. &lt;a href="https://github.com/a7ul/react-native-exception-handler."&gt;Exception-Handler&lt;/a&gt; will prevent critical crashes and inform users
&lt;/h3&gt;

&lt;p&gt;This magical thing can save your life. In any critical errors, your app won't just be closed. Now you have not just the opportunity to say sorry and that you are ashamed about what has just happened, but also the ability to provide a choice: relaunch the app or close it.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. &lt;a href="https://github.com/gorhom/react-native-bottom-sheet"&gt;Bottom-Sheet&lt;/a&gt; for the bottom sliding area like in Instagram
&lt;/h3&gt;

&lt;p&gt;No comments. Just take a look at the example below!&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DfHXb7sP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xggxmz4hzrw5ano2zri5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DfHXb7sP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xggxmz4hzrw5ano2zri5.gif" alt="Usage in my app" width="800" height="608"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Words
&lt;/h3&gt;

&lt;p&gt;I wish you good luck with creating the best application in the world! ✨&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Single place of form validation rules for clients and services with JSON Schema</title>
      <dc:creator>Daniil Sitdikov</dc:creator>
      <pubDate>Mon, 17 Jan 2022 20:17:40 +0000</pubDate>
      <link>https://dev.to/dsitdikov/single-place-of-form-validation-rules-for-clients-and-services-with-json-schema-i1g</link>
      <guid>https://dev.to/dsitdikov/single-place-of-form-validation-rules-for-clients-and-services-with-json-schema-i1g</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In our app, we have around 60 form fields among decades of modals and I am sure that this is not the final number. We work in multinational legal and finance business domains. Because of that, we have to validate a lot of form fields based on some conditions (such as country). Moreover, we are in the early stages of development and it means that the power of changes definitely can affect us.&lt;/p&gt;

&lt;p&gt;These circumstances led us to find the solution which has to satisfy these requirements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It should be one source of the truth. In other words, one dedicated file with validation rules for all consumers: services, web apps, mobile apps, etc. Because in the opposite case after successful front-end validation service can reject a request because of invalid incoming data&lt;/li&gt;
&lt;li&gt;It supports conditional validation: for instance, unique rules of legal entity fields for each country.&lt;/li&gt;
&lt;li&gt;Understandable language for product analytics. To be able to amend rules without engineers.&lt;/li&gt;
&lt;li&gt;Ability to show error messages which are clear for users&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EsyWAbXh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cd5xhm8mghbynn5q4iy3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EsyWAbXh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cd5xhm8mghbynn5q4iy3.jpg" alt="Image description" width="800" height="745"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;We decided to use JSON Schema (draft 7). It closed our needs. In a nutshell, it's standard represented as JSON which contains a set of rules for some JSON objects. Now we're going to overview the most common and useful validation patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basic
&lt;/h3&gt;

&lt;p&gt;Let's start with the basic example. We need to verify just one field: it should be required and follow an email regular expression.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bij41LE6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nivua1e5vo84egdvijzp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bij41LE6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nivua1e5vo84egdvijzp.jpg" alt="Image description" width="800" height="687"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our model is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Steve"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and our validation schema is the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nl"&gt;"pattern"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(?:[a-z0-9!#$%&amp;amp;'*+/=?^_`{|}~-]+(?:&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;.[a-z0-9!#$%&amp;amp;'*+/=?^_`{|}~-]+)*|&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;(?:[&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x01-&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x08&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x0b&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x0c&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x0e-&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x1f&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x21&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x23-&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x5b&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x5d-&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x7f]|&lt;/span&gt;&lt;span class="se"&gt;\\\\&lt;/span&gt;&lt;span class="s2"&gt;[&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x01-&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x09&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x0b&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x0c&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x0e-&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x7f])*&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;)@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x01-&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x08&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x0b&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x0c&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x0e-&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x1f&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x21-&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x5a&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x53-&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x7f]|&lt;/span&gt;&lt;span class="se"&gt;\\\\&lt;/span&gt;&lt;span class="s2"&gt;[&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x01-&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x09&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x0b&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x0c&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x0e-&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;x7f])+)&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;])"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nl"&gt;"errorMessage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Can be only in name@domain.com"&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conditional fields
&lt;/h3&gt;

&lt;p&gt;Sometimes we need to apply some validation rules depending on the values in the other selected fields.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Y8s_w1U_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oqnnm4un8o3l5io6hj78.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y8s_w1U_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oqnnm4un8o3l5io6hj78.jpg" alt="Image description" width="800" height="724"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s have a look at concreate case. Here, each country should apply unique validation for a VAT number.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;For the United Kingdom, it can only be: GB000000000(000), GBGD000 or GBHA000&lt;/li&gt;
&lt;li&gt;For Russia: exactly 9 digits and nothing else&lt;/li&gt;
&lt;li&gt;For other countries, we don’t apply any validations for now. (as we’re going to extend this piece by piece)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The model is a bit more complicated. Now we have country:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Samsung Ltd."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GB"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"United Kingdom"&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"vatNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"314685"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To perform conditional validation we’re going to use &lt;strong&gt;allOf&lt;/strong&gt; construction as well as &lt;strong&gt;if&lt;/strong&gt; and &lt;strong&gt;then&lt;/strong&gt; blocks. Please, pay attention to the &lt;strong&gt;required&lt;/strong&gt; field in the &lt;strong&gt;if&lt;/strong&gt; block. It has to be here. Otherwise, it won’t work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"vatNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="s2"&gt;"vatNumber"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"allOf"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nl"&gt;"if"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                   &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                       &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                         &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"const"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GB"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
                       &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
                   &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nl"&gt;"then"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                   &lt;/span&gt;&lt;span class="nl"&gt;"vatNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                       &lt;/span&gt;&lt;span class="nl"&gt;"pattern"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^GB([&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;d]{9}|[&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;d]{12}|GD[&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;d]{3}|HA[&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;d]{3})$"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                       &lt;/span&gt;&lt;span class="nl"&gt;"errorMessage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Can be GB000000000(000), GBGD000 or GBHA000"&lt;/span&gt;&lt;span class="w"&gt;
                   &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nl"&gt;"if"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                   &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                       &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                           &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"const"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RU"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
                       &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
                   &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nl"&gt;"then"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                   &lt;/span&gt;&lt;span class="nl"&gt;"vatNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                       &lt;/span&gt;&lt;span class="nl"&gt;"pattern"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^[0-9]{9}$"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                       &lt;/span&gt;&lt;span class="nl"&gt;"errorMessage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Can be only 9 digits"&lt;/span&gt;&lt;span class="w"&gt;
                   &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Either one or all
&lt;/h3&gt;

&lt;p&gt;Sometimes we need to fill at least one field. As a real-world example, to perform payments in the UK you should know the BIC/SWIFT or sort code numbers of a bank. If you know both — excellent! But at least one is mandatory.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hPidR-Nl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2cd45s7dmiem00dnjuj9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hPidR-Nl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2cd45s7dmiem00dnjuj9.jpg" alt="Image description" width="800" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To do that we will use &lt;strong&gt;anyOf&lt;/strong&gt; construction. As you noticed this is the second keyword after &lt;strong&gt;allOf&lt;/strong&gt;. Just to clarify all of them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;allOf — ALL statements should be valid&lt;/li&gt;
&lt;li&gt;oneOf — ONLY ONE statement should be valid. If more or nothing it fails&lt;/li&gt;
&lt;li&gt;anyOf — ONE OR MORE statements should be valid&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Our model is the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"swiftBic"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"sortCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"402030"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And validation schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"anyOf"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"swiftBic"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"sortCode"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Implementation on JavaScript
&lt;/h3&gt;

&lt;p&gt;JSON Schema is supported by many languages. However, the most investigated by me was the JavaScript version.&lt;/p&gt;

&lt;p&gt;We took ajv library as the &lt;a href="https://github.com/ajv-validator/ajv#performance"&gt;fastest one&lt;/a&gt;. It is platform-independent. In other words, you can use it as in front-end apps with any frameworks and in Node.JS. &lt;/p&gt;

&lt;p&gt;Apart from that, avj makes possible to use custom error messages. Because, unfortunately, they are not supported by standards.&lt;/p&gt;

&lt;p&gt;Before we start, we need to add 2 dependencies: &lt;strong&gt;ajv&lt;/strong&gt; and &lt;strong&gt;ajv-errors&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Ajv&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ajv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;connectWithErrorsLibrary&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ajv-errors&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ajv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Ajv&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="c1"&gt;// 1. The error message is custom property, we have to disable strict mode firstly&lt;/span&gt;
   &lt;span class="na"&gt;strict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="c1"&gt;// 2. This property enables custom error messages&lt;/span&gt;
   &lt;span class="na"&gt;allErrors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// 3. We have to connect an additional library for this&lt;/span&gt;
&lt;span class="nf"&gt;connectWithErrorsLibrary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ajv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 4. Our model&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;dunsNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;abc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// 5. Validation schema&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="na"&gt;dunsNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="na"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^[0-9]{9}$&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="na"&gt;errorMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Can be only 9 digits&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dunsNumber&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// 6. Set up validation container&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;validate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ajv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 7. Perform validation.&lt;/span&gt;
&lt;span class="c1"&gt;// ... It's not straightforward, but the result will be inside the "error" property&lt;/span&gt;
&lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dto&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;field error:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As the result we’ll have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"instancePath"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dunsNumber"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"schemaPath"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#/properties/dunsNumber/errorMessage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"keyword"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"errorMessage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"params"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"errors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"instancePath"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dunsNumber"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"schemaPath"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#/properties/dunsNumber/pattern"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"keyword"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pattern"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"params"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="nl"&gt;"pattern"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^[0-9]{9}$"&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"must match pattern &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;^[0-9]{9}$&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"emUsed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Can be only 9 digits"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and depends on our form implementation we can get the error and put it inside the invalid fields.&lt;/p&gt;

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

&lt;p&gt;To perform the validation which is described in one single place we used JSON Schema. Moreover, we came across the cases like conditional validations, selective validation and the basic one.&lt;/p&gt;

&lt;p&gt;Thanks for reading! ✨&lt;/p&gt;

</description>
      <category>validation</category>
      <category>forms</category>
      <category>architecture</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
