<?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: Carlos Azaustre</title>
    <description>The latest articles on DEV Community by Carlos Azaustre (@carlosazaustre).</description>
    <link>https://dev.to/carlosazaustre</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%2F114897%2F117c2c1a-09ff-4f1e-a9ca-1a03235b2034.jpeg</url>
      <title>DEV Community: Carlos Azaustre</title>
      <link>https://dev.to/carlosazaustre</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/carlosazaustre"/>
    <language>en</language>
    <item>
      <title>SOLID Principles in JavaScript</title>
      <dc:creator>Carlos Azaustre</dc:creator>
      <pubDate>Tue, 17 Oct 2023 09:49:45 +0000</pubDate>
      <link>https://dev.to/carlosazaustre/solid-principles-in-javascript-123c</link>
      <guid>https://dev.to/carlosazaustre/solid-principles-in-javascript-123c</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR:
&lt;/h2&gt;

&lt;p&gt;Prefers video content? Here are the 5 SOLID programming principles explained, applied to JavaScript (in Spanish)&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;a href="https://www.youtube.com/watch?si=gFpXcHmo00yeccjW&amp;amp;v=6PdAOfsPh48&amp;amp;feature=youtu.be" rel="noopener noreferrer"&gt;
      youtube.com
    &lt;/a&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Introduction to SOLID - What They Are and Why They Matter
&lt;/h2&gt;

&lt;p&gt;The SOLID principles are an acronym of five design values:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Single Responsibility Principle (S)&lt;/li&gt;
&lt;li&gt;Open-Closed Principle (O)&lt;/li&gt;
&lt;li&gt;Liskov Substitution Principle (L)&lt;/li&gt;
&lt;li&gt;Interface Segregation Principle (I)&lt;/li&gt;
&lt;li&gt;Dependency Inversion Principle (D)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We'll delve into each of these principles applying them to our favorite programming language: JavaScript. We begin with the first principle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Single Responsibility Principle (S)
&lt;/h2&gt;

&lt;p&gt;According to this principle, a class should have only one reason to change, that is, it should have only one task or responsibility. &lt;/p&gt;

&lt;p&gt;To illustrate this principle, let’s think of an orchestra. Each musician has an instrument they know how to play perfectly. The violinist knows how to play the violin, but if we also put them to play the drum, surely something would not work well.&lt;/p&gt;

&lt;p&gt;Applying this example to programming, each class or function should have a single responsibility. This simplifies understanding, maintenance, and modification of the code in the future.&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;calculateSalary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;employee&lt;/span&gt;&lt;span class="p"&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;salary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hoursWorked&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hourlyRate&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;report&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="cm"&gt;/*...*/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;report&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;salary&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;Example provided with a &lt;code&gt;calculateSalary()&lt;/code&gt; function, which is refactored to adhere to the single responsibility principle.&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;calculateSalary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;employee&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;employee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hoursWorked&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hourlyRate&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;generateReport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;salary&lt;/span&gt;&lt;span class="p"&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;report&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="cm"&gt;/*...*/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Open-Closed Principle (O)
&lt;/h2&gt;

&lt;p&gt;The second SOLID principle is the open-closed principle. Its official definition holds that software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.&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;processPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cardDetails&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&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;Payed with Card.&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;Example provided with a &lt;code&gt;processPayment()&lt;/code&gt; function and how it can be extended to handle different payment methods without modifying the existing code.&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;processPaymentWithPayPal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;accountDetails&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&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;Payed with PayPal.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Liskov Substitution Principle (L)
&lt;/h2&gt;

&lt;p&gt;The Liskov substitution principle states that "objects of a superclass should be replaceable by objects of a subclass without affecting the correctness of the program".&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;// example function to make HTTP requests&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;makeRequest&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;errorHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&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="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;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;errorHandler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handle&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// We can have several functions to handle errors&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;consoleErrorHandler&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;handle&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;externalErrorHandler&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;handle&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="nf"&gt;sendErrorToExternalService&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="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;makeRequest&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;consoleErrorHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;makeRequest&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;externalErrorHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Example provided with a &lt;code&gt;makeRequest()&lt;/code&gt; function and how different error handler objects can be used interchangeably without causing errors in the program.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interface Segregation Principle (I)
&lt;/h2&gt;

&lt;p&gt;The fourth SOLID principle, "I," refers to the Interface Segregation Principle. Based on this principle, no class should be forced to implement interfaces or methods that it will not use.&lt;/p&gt;

&lt;p&gt;It's better to have specific interfaces, rather than a single general interface. And this also applies to functions in JavaScript.&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;class&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;getDetails&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;saveToDb&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;displayInFrontEnd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&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;class&lt;/span&gt; &lt;span class="nc"&gt;DigitalProduct&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// saveToDb() is extended but not necessary }&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ---- //&lt;/span&gt;
&lt;span class="c1"&gt;// Refactor&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;getDetails&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;displayInFrontEnd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&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;class&lt;/span&gt; &lt;span class="nc"&gt;PhysicalProduct&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;saveToDb&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&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;class&lt;/span&gt; &lt;span class="nc"&gt;DigitalProduct&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// saveToDb() is not extended&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Example provided with a &lt;code&gt;Product&lt;/code&gt; class, illustrating the violation of this principle when a &lt;code&gt;DigitalProduct&lt;/code&gt; class extends &lt;code&gt;Product&lt;/code&gt; but doesn't need one of its methods. The example then shows the refactoring following this principle to have a &lt;code&gt;PhysicalProduct&lt;/code&gt; class extending &lt;code&gt;Product&lt;/code&gt; where the unnecessary method is moved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependency Inversion Principle (D)
&lt;/h2&gt;

&lt;p&gt;The last principle, "D," is the Dependency Inversion Principle. This principle holds that high-level modules, i.e., the modules that contain strategic decisions and high-level directives, should not depend on low-level modules, which are the modules that contain detailed and low-level logic.&lt;/p&gt;

&lt;p&gt;Both, high-level and low-level modules, should depend on abstractions.&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;class&lt;/span&gt; &lt;span class="nc"&gt;MySqlConnection&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&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;class&lt;/span&gt; &lt;span class="nc"&gt;PasswordReminder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dbConnection&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;MySQLConnection&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;// Refactor&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MySqlConnection&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&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;class&lt;/span&gt; &lt;span class="nc"&gt;PostgreSqlConnection&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&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;class&lt;/span&gt; &lt;span class="nc"&gt;PasswordReminder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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;dbConnection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;connection&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;Example provided with a &lt;code&gt;PasswordReminder&lt;/code&gt; class initially depending directly on a &lt;code&gt;MySQLConnection&lt;/code&gt; class. The refactoring follows the principle by having &lt;code&gt;PasswordReminder&lt;/code&gt; receive an instance of a class implementing a common "database connection" interface, showing both &lt;code&gt;MySQLConnection&lt;/code&gt; and &lt;code&gt;PostgreSqlConnection&lt;/code&gt; classes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;SOLID rules are a very useful tool for programming. However, like any tool, they should not be applied blindly in all cases. The advice is to follow these principles where it makes sense and can help you maintain and improve your code in the long term.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Software is a cycle in which you are developing code, new features or functionalities are needed, bugs appear unintentionally or intentionally, and you will need to refactor. You don't necessarily always have to be writing new code. Most of your time you will be reading code from others or even yours and you will be able to see that there are parts that you can refactor to improve maintenance and even the performance of your application."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;See you next time!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You have a spanish version of this article &lt;a href="https://carlosazaustre.es/javascript-solid" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>React Tutorial: How to develop an application from scratch with modern libraries</title>
      <dc:creator>Carlos Azaustre</dc:creator>
      <pubDate>Tue, 26 Sep 2023 17:09:46 +0000</pubDate>
      <link>https://dev.to/carlosazaustre/how-to-develop-a-react-application-from-scratch-with-modern-libraries-2n7f</link>
      <guid>https://dev.to/carlosazaustre/how-to-develop-a-react-application-from-scratch-with-modern-libraries-2n7f</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this step-by-step tutorial, we are going to learn how to develop a React web application from scratch using some of the most popular tools in the React ecosystem.&lt;/p&gt;

&lt;p&gt;Specifically, we will use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zustand for global state management&lt;/li&gt;
&lt;li&gt;React Query for data fetching and caching&lt;/li&gt;
&lt;li&gt;React Hook Form for form handling&lt;/li&gt;
&lt;li&gt;React Router for navigation&lt;/li&gt;
&lt;li&gt;React Hot Toast for showing notifications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The application we will build will simulate a hotel booking system, with a page to list hotels and a details page to book rooms in a specific hotel.&lt;/p&gt;

&lt;p&gt;Here are some of the features we will implement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fetch and display a list of hotels from an API&lt;/li&gt;
&lt;li&gt;Navigate to the detail page of a specific hotel&lt;/li&gt;
&lt;li&gt;Form to select dates and book a room&lt;/li&gt;
&lt;li&gt;Global state management for bookings&lt;/li&gt;
&lt;li&gt;Notifications on errors or successful bookings&lt;/li&gt;
&lt;li&gt;Form validations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So without further ado, let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparing the project
&lt;/h2&gt;

&lt;p&gt;The first thing we need to do is prepare our React project. For this, we will use &lt;code&gt;create-react-app&lt;/code&gt; which will allow us to bootstrap quickly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-react-app hotel-reservations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will generate the basic React project structure in a folder called &lt;code&gt;hotel-reservations&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, we install the dependencies by running &lt;code&gt;npm install&lt;/code&gt; inside that folder.&lt;/p&gt;

&lt;p&gt;The dependencies we will use in this project are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;zustand&lt;/li&gt;
&lt;li&gt;react-query&lt;/li&gt;
&lt;li&gt;react-hook-form&lt;/li&gt;
&lt;li&gt;react-router-dom&lt;/li&gt;
&lt;li&gt;react-hot-toast&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So we install them by running:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;zustand react-query react-hook-form react-router-dom react-hot-toast
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Our project is now setup and ready! We can now start coding.&lt;/p&gt;
&lt;h2&gt;
  
  
  Global state with Zustand
&lt;/h2&gt;

&lt;p&gt;First we are going to configure our global state using Zustand.&lt;/p&gt;

&lt;p&gt;Zustand is a lightweight library for managing global state in React. It allows us to have a centralized store that can be accessed from any component to read and update state.&lt;/p&gt;

&lt;p&gt;For this, we create a &lt;code&gt;store.js&lt;/code&gt; file and add 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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zustand&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;reservations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="na"&gt;addReservation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hotel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dates&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;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;reservations&lt;/span&gt;&lt;span class="p"&gt;:&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="nx"&gt;reservations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;hotel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dates&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;useStore&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Basically we are creating a &lt;code&gt;useStore&lt;/code&gt; hook that gives us access to the &lt;code&gt;reservations&lt;/code&gt; global state and an &lt;code&gt;addReservation&lt;/code&gt; action to add new bookings.&lt;/p&gt;

&lt;p&gt;We can import and use this hook from any component in our app.&lt;/p&gt;
&lt;h2&gt;
  
  
  Data fetching with React Query
&lt;/h2&gt;

&lt;p&gt;Now we are going to take care of fetching data from an API. For this we will use React Query.&lt;/p&gt;

&lt;p&gt;React Query allows us to perform data fetching, caching, and updating. It also handles loading, error and automatic revalidation states.&lt;/p&gt;

&lt;p&gt;First, we create a &lt;code&gt;db.json&lt;/code&gt; file with mock data:&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="nl"&gt;"hotels"&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&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;"Hotel Sunshine"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Beachfront hotel with pool"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hotel-1.jpg"&lt;/span&gt;&lt;span class="p"&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&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;"Hotel Mountain Spa"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Luxury hotel in the mountains"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hotel-2.jpg"&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;Then, we create a script in &lt;code&gt;package.json&lt;/code&gt; to spin up a dev server with that data:&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;"server"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"json-server --watch db.json --port 3001"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now we can create our fetching function:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// hotels.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchHotels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3001/hotels&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Network error&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="nx"&gt;response&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="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fetchHotels&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And use it in our &lt;code&gt;HotelsList&lt;/code&gt; 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="c1"&gt;// HotelsList.js&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;fetchHotels&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;./hotels&lt;/span&gt;&lt;span class="dl"&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;useQuery&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;react-query&lt;/span&gt;&lt;span class="dl"&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;HotelsList&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;data&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;isLoading&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hotels&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetchHotels&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="c1"&gt;// display data or loading/error statereturn (// JSX to display hotels)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That's all we need to implement data fetching with React Query!&lt;/p&gt;
&lt;h2&gt;
  
  
  Forms with React Hook Form
&lt;/h2&gt;

&lt;p&gt;Now let's implement the booking form with React Hook Form.&lt;/p&gt;

&lt;p&gt;React Hook Form allows us to build forms easily in React, with validations, error handling and state management.&lt;/p&gt;

&lt;p&gt;First we create our &lt;code&gt;BookingForm&lt;/code&gt; component:&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;// BookingForm.js&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;useForm&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;react-hook-form&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;BookingForm&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;register&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;formState&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useForm&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;onSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="c1"&gt;// submit form}return (&amp;lt;form onSubmit={handleSubmit(onSubmit)}&amp;gt;&amp;lt;input{...register('checkinDate', { required: true })}/&amp;gt;{errors.checkinDate &amp;amp;&amp;amp; (&amp;lt;p&amp;gt;Checkin date required&amp;lt;/p&amp;gt;)}// ...more inputs and validations&amp;lt;/form&amp;gt;)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We are registering the inputs so React Hook Form controls them, handling submit, and displaying any validation errors.&lt;/p&gt;

&lt;p&gt;And that's all we need for powerful form handling with React Hook Form!&lt;/p&gt;
&lt;h2&gt;
  
  
  Navigation with React Router
&lt;/h2&gt;

&lt;p&gt;Now we are going to configure navigation between different views using React Router.&lt;/p&gt;

&lt;p&gt;First, we wrap our app with a &lt;code&gt;&amp;lt;BrowserRouter&amp;gt;&lt;/code&gt; in &lt;code&gt;index.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then, we create the routes in &lt;code&gt;App.js&lt;/code&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Route&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;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Routes&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt; &lt;span class="na"&gt;element&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;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hotels&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/hotel/:id"&lt;/span&gt; &lt;span class="na"&gt;element&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="nc"&gt;HotelDetails&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;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Routes&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;Finally, we use the &lt;code&gt;useNavigate&lt;/code&gt; hook inside our &lt;code&gt;HotelsList&lt;/code&gt; to navigate to a hotel's detail view when clicked.&lt;/p&gt;

&lt;p&gt;And that's all we need for navigation with React Router!&lt;/p&gt;
&lt;h2&gt;
  
  
  Notifications with React Hot Toast
&lt;/h2&gt;

&lt;p&gt;Lastly, we are going to add notifications using React Hot Toast.&lt;/p&gt;

&lt;p&gt;React Hot Toast allows us to show popup messages very easily.&lt;/p&gt;

&lt;p&gt;We import it in our &lt;code&gt;BookingForm&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;toast&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;react-hot-toast&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And show a success notification when booking:&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;// inside onSubmit&lt;/span&gt;
&lt;span class="nx"&gt;toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Booking successful!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We also wrap it in &lt;code&gt;&amp;lt;Toaster&amp;gt;&lt;/code&gt; to make it work app-wide.&lt;/p&gt;

&lt;p&gt;And that's all we need to show notifications! React Hot Toast handles the UI.&lt;/p&gt;
&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this article we have seen how to develop a React web application from scratch using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zustand for global state&lt;/li&gt;
&lt;li&gt;React Query for data fetching&lt;/li&gt;
&lt;li&gt;React Hook Form for forms&lt;/li&gt;
&lt;li&gt;React Router for navigation&lt;/li&gt;
&lt;li&gt;React Hot Toast for notifications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We have learned how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setup a global store with Zustand&lt;/li&gt;
&lt;li&gt;Fetch data from an API with React Query&lt;/li&gt;
&lt;li&gt;Create a form with validations using React Hook Form&lt;/li&gt;
&lt;li&gt;Add navigation between views with React Router&lt;/li&gt;
&lt;li&gt;Show notifications to the user with React Hot Toast&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tools have allowed us to quickly build a React application in a straightforward, declarative way with great practices.&lt;/p&gt;

&lt;p&gt;You can find the code in &lt;a href="https://github.com/carlosazaustre/hotel-reservation-app"&gt;this GitHub Repository&lt;/a&gt; (You can give a Star ⭐️ if you like it)&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/carlosazaustre"&gt;
        carlosazaustre
      &lt;/a&gt; / &lt;a href="https://github.com/carlosazaustre/hotel-reservation-app"&gt;
        hotel-reservation-app
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Hotel booking application, using React along with some of the most popular and powerful libraries in the ecosystem: React/TanStack Query, Zustand, Wouter, React Hooks Forms, React Hot Toast, and Material UI
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1 id="user-content-hotel-reservation-app"&gt;&lt;a class="heading-link" href="https://github.com/carlosazaustre/hotel-reservation-app#hotel-reservation-app"&gt;hotel-reservation-app&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Code from the ReactJS Video Tutorial on &lt;a href="https://www.youtube.com/watch?v=KRrzBkxxMbc" rel="nofollow"&gt;YouTube&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://github.com/carlosazaustre/hotel-reservation-app/assets/650752/ca8b3b18-2daf-4727-9ecc-1d5b17858adc"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YWHmfTvU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/carlosazaustre/hotel-reservation-app/assets/650752/ca8b3b18-2daf-4727-9ecc-1d5b17858adc" alt="yt-react-tutorial-query-vouter-zustand"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You will learn:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How to set up a React JS project from scratch.&lt;/li&gt;
&lt;li&gt;Integration and use of &lt;strong&gt;React/TanStack Query&lt;/strong&gt; to manage queries and mutations.&lt;/li&gt;
&lt;li&gt;Global state with &lt;strong&gt;Zustand&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Navigation with &lt;strong&gt;Wouter&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Forms with &lt;strong&gt;React Hooks Forms&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Notifications with &lt;strong&gt;React Hot Toast&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Design and styles with &lt;strong&gt;Material UI&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This tutorial is perfect for both beginners looking for a detailed "react js tutorial" and experienced developers wanting to expand their knowledge and learn about new libraries.&lt;/p&gt;
&lt;p&gt;You don't need to download anything beforehand; I'll show you how to do everything from the beginning.&lt;/p&gt;
&lt;p&gt;So, prepare your development environment and join me on this exciting journey through the world of React JS!&lt;/p&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/carlosazaustre/hotel-reservation-app"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Also, you can find this tutorial in video format (in spanish)&lt;br&gt;
&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://www.youtube.com/watch?si=ztRnlpMlMK-wVBpX&amp;amp;v=KRrzBkxxMbc&amp;amp;feature=youtu.be" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--aWbFRZlX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ytimg.com/vi/KRrzBkxxMbc/maxresdefault.jpg" height="450" class="m-0" width="800"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://www.youtube.com/watch?si=ztRnlpMlMK-wVBpX&amp;amp;v=KRrzBkxxMbc&amp;amp;feature=youtu.be" rel="noopener noreferrer" class="c-link"&gt;
          TUTORIAL REACT JS desde cero | Crea una aplicación paso a paso | React Query, Zustand, Wouter. - YouTube
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          En este tutorial de React JS desde cero te guiaré paso a paso en la creación de una aplicación de reservas de Hotel, utilizando React junto con algunas de la...
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--1imkzWU6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.youtube.com/s/desktop/0c0555f3/img/favicon.ico" width="16" height="16"&gt;
        youtube.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I hope you found this tutorial useful! Don't forget to share it and follow me for more web development content. See you next time!&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Conventional Commits - Specification for Your Commit Messages</title>
      <dc:creator>Carlos Azaustre</dc:creator>
      <pubDate>Thu, 02 Feb 2023 11:18:31 +0000</pubDate>
      <link>https://dev.to/carlosazaustre/conventional-commits-specification-for-your-commit-messages-14lo</link>
      <guid>https://dev.to/carlosazaustre/conventional-commits-specification-for-your-commit-messages-14lo</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This content was originally published in spanish on &lt;a href="https://carlosazaustre.es/conventional-commits" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What are Commit Messages?
&lt;/h2&gt;

&lt;p&gt;Commit messages are a way of documenting changes made in a code repository.&lt;/p&gt;

&lt;p&gt;These messages are very useful for understanding what changes were made in a project and why they were made.&lt;/p&gt;

&lt;p&gt;When working in a development team, it is very important that all team members can understand what changes were made to the code and why they were made.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conventional Commits
&lt;/h2&gt;

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

&lt;p&gt;As stated on their official page: It is a specification&lt;br&gt;
for giving meaning to commit messages making them understandable both for machines and for people. &lt;/p&gt;

&lt;p&gt;It provides a simple set of rules for creating an explicit commit history; which makes it easier to write automated tools. &lt;/p&gt;

&lt;p&gt;This convention fits with SemVer, since we can explain in the commit messages if it's a feature, bugfix, even if there are &lt;em&gt;Breaking Changes&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If you were unfamiliar with the term Semantic Versioning, in this short video I'll explain it to you:&lt;/p&gt;

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

&lt;p&gt;The structure of a commit message following the specification would be as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;type&amp;gt;[optional scope]: &amp;lt;commit description&amp;gt;

[message body, optional]

[footer(s), optional]

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Commit Types
&lt;/h2&gt;

&lt;p&gt;The commit types are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;feat&lt;/strong&gt;: A new feature or functionality. It would have correlation with a MINOR version following &lt;em&gt;SemVer&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;fix&lt;/strong&gt;: A corrected error. It would have correlation with a PATCH version following &lt;em&gt;SemVer&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;BREAKING CHANGE&lt;/strong&gt;: A change that contains this word in the message footer or a ! sign after the type or scope,&lt;br&gt;
breaks compatibility with previous versions. It would have correlation with a MAJOR version following &lt;em&gt;SemVer&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following types are also allowed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;build&lt;/strong&gt;: Changes that affect the build system or external dependencies (e.g. changes to the package.json).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ci&lt;/strong&gt;: Changes to our continuous integration configuration files and scripts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;docs&lt;/strong&gt;: Changes to documentation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;chore&lt;/strong&gt;: Other changes that do not affect source code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;perf&lt;/strong&gt;: A code change that improves performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;refactor&lt;/strong&gt;: A code change that does not correct an error or add a feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;style&lt;/strong&gt;: Changes that do not affect the meaning of the code (whitespace, format, missing commas, etc).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;test&lt;/strong&gt;: Add missing tests or correct existing tests.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Scope
&lt;/h3&gt;

&lt;p&gt;The scope is optional and serves to specify the scope of the commit. For example, if we are working on a monorepo project, we can specify the package we are modifying.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;

&lt;p&gt;Let's see some examples of commit messages following the specification:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Commit that adds a new feature, without a specific scope.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat: add support for TypeScript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Commit that fixes a bug, within the ui package of our project.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fix(ui): bugfix on Button component
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Commit that breaks compatibility with previous versions, although it doesn't add new features or fix bugs.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chore!: drop support for Node 6

BREAKING CHANGE: use JavaScript features not available in Node 6.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Commit that adds missing tests.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test(ui): add missing tests for Button component
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Commit that adds a task for the continuous integration/deployment system.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ci: add GitHub Actions workflow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Commit with a long descriptive message and multiple footers.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fix(api): prevent duplicate users from being created

This commit fixes a bug where the API would allow duplicate users to be created with the same email address. This commit also adds a new `unique` constraint to the `users` table to prevent this from happening in the future.

Paired with: X
Fixes #123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why use Conventional Commits?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It allows for automatic generation of the CHANGELOG file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automatically determines version changes following SemVer (based on the types of commits used).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Communicates the nature of changes to other team members or anyone interested.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Activates build and deployment or publishing processes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Makes it easier for others to contribute to the project by allowing them to explore the commit history in a more structured way.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tools to use Conventional Commits
&lt;/h2&gt;

&lt;h3&gt;
  
  
  VSCode Plugin
&lt;/h3&gt;

&lt;p&gt;The first one I use is the VSCode extension or plugin, &lt;a href="https://marketplace.visualstudio.com/items?itemName=vivaxy.vscode-conventional-commits" rel="noopener noreferrer"&gt;Conventional Commit&lt;/a&gt;. It helps me choose the type of commit, the scope, write the message,... all based on dialog windows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gitemoji
&lt;/h3&gt;

&lt;p&gt;To make our commits more colorful, we can use the &lt;a href="https://gitmoji.dev/" rel="noopener noreferrer"&gt;Gitemoji&lt;/a&gt; convention. It's a convention where&lt;br&gt;
emojis represent the type of commit. For example, the emoji 🐛 represents a bugfix, ✨ a new feature, etc... So with a quick glance you can see what type of change has been made.&lt;/p&gt;
&lt;h3&gt;
  
  
  Commitlint
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://commitlint.js.org/#/" rel="noopener noreferrer"&gt;Commitlint&lt;/a&gt; is a tool that allows us to configure rules to validate commit messages.&lt;br&gt;
Just like we use a linter to check if we follow certain style rules in our code, we can use it for commit messages.&lt;/p&gt;

&lt;p&gt;For this, you need to install the &lt;code&gt;@commitlint/cli&lt;/code&gt; and &lt;code&gt;@commitlint/config-conventional&lt;/code&gt; libraries in 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;npm install --save-dev @commitlint/cli @commitlint/config-conventional
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once installed, you must create a configuration file called &lt;code&gt;commitlint.config.js&lt;/code&gt; in the root of your project with the following content:&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;extends&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@commitlint/config-conventional&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Husky
&lt;/h3&gt;

&lt;p&gt;We already saw &lt;a href="https://carlosazaustre.es/husky-lintstaged" rel="noopener noreferrer"&gt;what Husky was used for in a previous post&lt;/a&gt;. Now we will add a new rule to the &lt;code&gt;pre-commit&lt;/code&gt; hook to verify and validate if the commit message complies with the Conventional Commits rules.&lt;/p&gt;

&lt;p&gt;If you already have Husky configured, all you have to do is run the following command in the root of your project to add the command to the &lt;code&gt;commit-msg&lt;/code&gt; hook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx husky add .husky/commit-msg  'npx --no -- commitlint --edit ${1}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it, every time you make a commit, it will verify that it follows the rules.&lt;/p&gt;

&lt;h3&gt;
  
  
  CHANGELOG
&lt;/h3&gt;

&lt;p&gt;Finally, it is also interesting to be able to automatically generate the CHANGELOG file from the commit messages. There are various tools for this, one of them is &lt;a href="https://github.com/conventional-changelog/conventional-changelog" rel="noopener noreferrer"&gt;Conventional Changelog&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Hope this is helpful ✨&lt;/p&gt;




&lt;p&gt;Do Like 💛 &amp;amp; Save 🔖&lt;/p&gt;




&lt;p&gt;Do &lt;strong&gt;Follow&lt;/strong&gt; me on &lt;a href="https://twitter.com/carlosazaustre" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and &lt;a href="https://linkedin.com/in/carlosazaustre" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt; for more content related to Web Programming and JavaScript&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%2Fr3me5n5aghext9ano5ap.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%2Fr3me5n5aghext9ano5ap.png" alt="Carlos Azaustre on Twitter"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>productivity</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to deploy a webapp to Google Cloud Run with Cloud Build</title>
      <dc:creator>Carlos Azaustre</dc:creator>
      <pubDate>Thu, 11 Jul 2019 08:34:57 +0000</pubDate>
      <link>https://dev.to/carlosazaustre/how-to-deploy-a-webapp-to-google-cloud-run-with-cloud-build-4eel</link>
      <guid>https://dev.to/carlosazaustre/how-to-deploy-a-webapp-to-google-cloud-run-with-cloud-build-4eel</guid>
      <description>&lt;p&gt;This article was originally published in &lt;a href="https://carlosazaustre.es/google-cloud-run/" rel="noopener noreferrer"&gt;spanish on my blog&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;In the past Cloud Next event, Google announced a new product of its services: &lt;a href="https://cloud.google.com/run/" rel="noopener noreferrer"&gt;Cloud Run&lt;/a&gt;. This is an evolution of App Engine which let us run any backend language on a Docker container.&lt;/p&gt;

&lt;p&gt;In this article, I will describe how to start with this service and run your first Node.js app with it. Let's go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a project on Google Cloud.
&lt;/h2&gt;

&lt;p&gt;Go to &lt;a href="https://console.cloud.google.com/" rel="noopener noreferrer"&gt;Google Cloud Console&lt;/a&gt; and create a new project. I'm named &lt;code&gt;hello-cloud-run&lt;/code&gt; but you can name it as you want. Keep in mind the &lt;code&gt;ProjectID&lt;/code&gt; which we are using later.&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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-21.02.43.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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-21.02.43.png" alt="Create a new project on google cloud"&gt;&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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-21.03.12.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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-21.03.12.png" alt="Create a new project on google cloud"&gt;&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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-21.03.25.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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-21.03.25.png" alt="Creating a new project on Google Cloud"&gt;&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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-21.03.51.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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-21.03.51.png" alt="Project created"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To be able to use Google Cloud Platform you will need a Gmail/GSuite account, and to activate the billing. If it is the first time you sign up, you have &lt;a href="https://console.developers.google.com/billing/freetrial?hl=en" rel="noopener noreferrer"&gt;$300 free in credits&lt;/a&gt; to use for one year.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  API Activation
&lt;/h2&gt;

&lt;p&gt;We need to activate some APIs to have not problems. One is the Cloud Run API and another one is Cloud Build API which we will use later.&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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-21.05.19.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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-21.05.19.png" alt="Google Cloud APIs and Services"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on Enable APIs and Services and look for Cloud Run&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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-21.05.50.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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-21.05.50.png" alt="Cloud Run API"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Activate the Cloud Run API and do the same with Cloud Build API&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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-21.05.58.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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-21.05.58.png" alt="Cloud Run API"&gt;&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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-21.34.05.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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-21.34.05.png" alt="Cloud Build API"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Our App code
&lt;/h2&gt;

&lt;p&gt;I have created this example code. It is a Node.js application that in the root path returns a JSON object with two properties: The today date and the time that the application is running up.&lt;/p&gt;

&lt;p&gt;Create a Node project with the following command (remember to have Node.js installed):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm init -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, install &lt;code&gt;express&lt;/code&gt; as dependence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm i express
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create an &lt;code&gt;index.js&lt;/code&gt; file with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const app = express();
const port = process.env.PORT || 3000;

const dateStart = Date.now();

app.get('/', (req, res) =&amp;gt; {
  const today = new Date();

  res.json({
    date: today,
    up: `${(Date.now() - dateStart) / 1000} seg.` 
  });
});

app.listen(port, () =&amp;gt; {
  console.log(`Server running on port: ${port}`);
  console.log('Press CTRL + C to quit');
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's update the &lt;code&gt;package.json&lt;/code&gt; file to add the &lt;code&gt;start&lt;/code&gt; script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
"scripts": {
   "start": "NODE_ENV=production node index.js"
  },
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On this way, when we execute &lt;code&gt;npm start&lt;/code&gt; command the app will run. We can testing locally.&lt;/p&gt;

&lt;p&gt;Next step is to create the &lt;code&gt;Dockerfile&lt;/code&gt; with this we define the container which contains the application code. Here you have the content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM node:10

WORKDIR /usr/src/app

ENV PORT 8080
ENV HOST 0.0.0.0

COPY package*.json ./

RUN npm install --only=production

# Copy the local code to the container
COPY . .


# Start the service
CMD npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this file we are configuring an environment with &lt;code&gt;Node v10&lt;/code&gt; as a base, the working directory will be &lt;code&gt;/usr/src/app&lt;/code&gt;. We are defining as environment variables the &lt;code&gt;PORT: 8080&lt;/code&gt;and &lt;code&gt;HOST: 0.0.0.0&lt;/code&gt;. We are copying the &lt;code&gt;package.json&lt;/code&gt; and &lt;code&gt;package-lock.json&lt;/code&gt; to the working directory and installing the dependencies with &lt;code&gt;RUN npm install --only=production&lt;/code&gt;.&lt;br&gt;
Finally, we are moving the app code to the container working directory with &lt;code&gt;COPY . .&lt;/code&gt; And with the last one &lt;code&gt;CMD npm start&lt;/code&gt; the app is run.&lt;/p&gt;

&lt;p&gt;We can try if everything is ok so far, generating the image and the start the docker container. Write the following commands on your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker build --tag hello-cloud-run:01 .
$ docker run -p 8080:8080 hello-cloud-run:01
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Keep in mind you need to have Docker installed on your system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;build&lt;/code&gt; command you have created an image following the &lt;code&gt;Dockerfile&lt;/code&gt; steps with the name &lt;code&gt;hello-cloud-run:01&lt;/code&gt;. The &lt;code&gt;run&lt;/code&gt; command let you run the app on &lt;code&gt;http://localhost:8080&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If all is ok you should see the following on your browser:&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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-05-at-17.59.45.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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-05-at-17.59.45.png" alt="App running on localhost"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Automate the container deploying
&lt;/h2&gt;

&lt;p&gt;Once our project is configurated on Google Cloud and the application code is written and containerized, the following step is to upload it to Google Container Registry.&lt;/p&gt;

&lt;p&gt;We are going to create a YAML file with the steps to build and deploy the code using Google Cloud Build. This service is similar to TravisCI but customized to Google Cloud.&lt;/p&gt;

&lt;p&gt;On this way, every time we push our code to Github (for example) Cloud Build will build the Docker image and upload the new code to Cloud Container Registry and deploy it into Cloud Run. So awesome!&lt;/p&gt;

&lt;p&gt;First, we need to create a trigger on Cloud Build:&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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-22.57.51.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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-22.57.51.png" alt="Cloud Build triggers"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once created, we choose Github as source repository option&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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-22.58.02.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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-22.58.02.png" alt="Github as source repository hosting option"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We need to authenticate on the service chosen (in this case Github) and to choose the repository. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You need to store the application code on it. If you prefer other option like Bitbucket or Cloud Source, go ahead.&lt;/p&gt;

&lt;p&gt;You can use &lt;a href="https://dev.tocreating%20a%20fork%20on%20your%20account"&gt;this repository&lt;/a&gt; as the base project.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-22.58.40.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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-22.58.40.png" alt="create trigger"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On settings, to choose Cloud Build Configuration file (yaml or json) as Build configuration, putting the name &lt;code&gt;cloudbuild.yaml&lt;/code&gt; which we write later.&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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-23.30.39.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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-23.30.39.png" alt="Build configuration"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;All right! On the options, you can choose if you want to dispatch the trigger every time you push to a specific branch repo or with a tag.&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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-22.59.41.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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-22.59.41.png" alt="build trigger created"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Add roles and permissions
&lt;/h2&gt;

&lt;p&gt;Once you have activated the &lt;a href="https://console.cloud.google.com/apis/library/run.googleapis.com?_ga=2.191926124.-772456817.1555320972" rel="noopener noreferrer"&gt;Cloud Run API&lt;/a&gt; we need to follow the next steps to bring access from outside to our application.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Grant &lt;em&gt;Cloud Run Admin&lt;/em&gt; role to Cloud Build Service account&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;From Cloud Console, access to &lt;a href="https://console.cloud.google.com/iam-admin/iam/project?_ga=2.217088720.-772456817.1555320972" rel="noopener noreferrer"&gt;IAM Menu&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;On the members' list, locate and select &lt;code&gt;[PROJECT_NUMBER]@cloudbuild.gserviceaccount.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Click on &lt;em&gt;EDIT&lt;/em&gt; button (pencil icon) to approve the new role.&lt;/li&gt;
&lt;li&gt;Click on &lt;em&gt;Add another role&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;em&gt;Cloud Run&lt;/em&gt; and then &lt;em&gt;Cloud Run Admin&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Click on &lt;em&gt;Save&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Grant &lt;em&gt;IAM Service Account User&lt;/em&gt; to Cloud Build Service Account from &lt;a href="https://cloud.google.com/run/docs/securing/service-identity#runtime_service_account" rel="noopener noreferrer"&gt;Cloud Run Runtime service account&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;From Google Cloud Console, access to &lt;a href="https://cloud.google.com/run/docs/securing/service-identity#runtime_service_account" rel="noopener noreferrer"&gt;Service Accounts&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;On the members' list, locate and select &lt;code&gt;[PROJECT_NUMBER]-compute@developer.gserviceaccount.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Click on &lt;em&gt;Show Info Panel&lt;/em&gt; up on the right corner.&lt;/li&gt;
&lt;li&gt;On &lt;em&gt;Permissions&lt;/em&gt; panel, click on &lt;em&gt;Add Member&lt;/em&gt; button.&lt;/li&gt;
&lt;li&gt;Introduce the Cloud Build service account &lt;code&gt;[PROJECT_NUMBER]@cloudbuild.gserviceaccount.com&lt;/code&gt; in the &lt;em&gt;New Member&lt;/em&gt; new field.&lt;/li&gt;
&lt;li&gt;On the &lt;em&gt;Role&lt;/em&gt; dropdown, select &lt;em&gt;Service Accounts&lt;/em&gt; and then &lt;em&gt;Service Account User&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Click on &lt;em&gt;Save&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now in our code, we are going to create the &lt;code&gt;cloudbuild.yaml&lt;/code&gt; file which executes the necessary commands to build the docker image, upload it to container registry and deploy it to Cloud Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;steps:
  # build the container image
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'gcr.io/$PROJECT_ID/hello-cloud-run:${SHORT_SHA}', '.']
  # push the container image to Container Registry
- name: 'gcr.io/cloud-builders/docker'
  args: ['push', 'gcr.io/$PROJECT_ID/hello-cloud-run']
  # deploy container image to Cloud Run
- name: 'gcr.io/cloud-builders/gcloud'
  args: ['beta', 'run', 'deploy', 'hello-cloud-run', '--image', 'gcr.io/$PROJECT_ID/hello-cloud-run:${SHORT_SHA}', '--region', 'us-central1', '--allow-unauthenticated']
  env:
  - 'PORT=8080'
images:
- gcr.io/$PROJECT_ID/hello-cloud-run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep in mind that &lt;code&gt;&amp;lt;PROJECT_ID&amp;gt;&lt;/code&gt; is your project identifier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checking all is working
&lt;/h2&gt;

&lt;p&gt;So now, we will deploy our application code to a repository, in my case I chose Github. (this is my &lt;a href="https://github.com/carlosazaustre/hello-cloud-run" rel="noopener noreferrer"&gt;repo&lt;/a&gt; for this example). When we made a change and we will push it to &lt;code&gt;master&lt;/code&gt; branch, the build configuration will trigger and it will follow all the steps to upload it to Container Registry and then deploy it to Cloud Run!&lt;/p&gt;

&lt;p&gt;When you made &lt;code&gt;push&lt;/code&gt; to your repo, check inside Google Cloud Console if Cloud Build has triggered an event&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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-05-at-18.17.00.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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-05-at-18.17.00.png" alt="Cloud Build triggered an event"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;If it is Ok, you can go to Container Registry section and check if the Docker image has been created:&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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-23.07.23.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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-23.07.23.png" alt="Docker image created in Container Registry"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the last, check if in Cloud Run section you have an application running:&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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-23.18.36.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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-02-at-23.18.36.png" alt="Cloud Run application running"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One last thing is to let external invocations to the service because for default is private.&lt;/p&gt;

&lt;p&gt;Add &lt;code&gt;allUsers&lt;/code&gt; to the new members and the &lt;code&gt;Cloud Run &amp;gt; Cloud Run Invoker&lt;/code&gt; role.&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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-05-at-18.45.44.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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-05-at-18.45.44.png" alt="Grant permissions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see a more detail explanation on &lt;a href="https://dev.to/googlecloud/help-i-forgot-to-click-allow-unauthenticated-invocations-on-google-cloud-run-2hoj"&gt;this post in Dev.to&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And yes! You finish! Click on the URL associated to your Cloud Run deployment and if all is OK you can see something similar to this on your browser&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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-05-at-18.25.03.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%2Fcarlosazaustre.es%2Fcontent%2Fimages%2F2019%2F07%2FScreenshot-2019-07-05-at-18.25.03.png" alt="Cloud Run deployment is running"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/run/docs/" rel="noopener noreferrer"&gt;Cloud Run Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/cloud-build/docs/configuring-builds/build-test-deploy-artifacts" rel="noopener noreferrer"&gt;Cloud Build Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>googlecloud</category>
      <category>javascript</category>
      <category>node</category>
      <category>serverless</category>
    </item>
  </channel>
</rss>
