<?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: Douglas Matoso</title>
    <description>The latest articles on DEV Community by Douglas Matoso (@doug2k1).</description>
    <link>https://dev.to/doug2k1</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%2F206393%2F3f836474-c7a8-470e-afda-f8d099a6a543.jpg</url>
      <title>DEV Community: Douglas Matoso</title>
      <link>https://dev.to/doug2k1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/doug2k1"/>
    <language>en</language>
    <item>
      <title>HTTP primer for frontend developers </title>
      <dc:creator>Douglas Matoso</dc:creator>
      <pubDate>Sun, 27 Dec 2020 16:51:03 +0000</pubDate>
      <link>https://dev.to/doug2k1/http-primer-for-frontend-developers-172h</link>
      <guid>https://dev.to/doug2k1/http-primer-for-frontend-developers-172h</guid>
      <description>&lt;p&gt;&lt;strong&gt;HTTP&lt;/strong&gt; — Hypertext Transfer Protocol — is how client and server (frontend and backend) talk to each other. As frontend developers (and web developers in general) we should understand at least the basics of this communication, because an important part of our job is to send &lt;em&gt;requests&lt;/em&gt; to the server and handle the &lt;em&gt;responses&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Request and response
&lt;/h2&gt;

&lt;p&gt;Basically the way that communication works is by exchanging messages. The client sends a &lt;em&gt;request&lt;/em&gt; and the server sends back a &lt;em&gt;response&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BX7v8jqP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://webdevdrops.com/wp-content/uploads/2017/08/http-1-1024x648.png" alt=""&gt;Anatomy of a request
&lt;/h2&gt;

&lt;p&gt;An HTTP request is composed of the following parts:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wLbb6ePL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://webdevdrops.com/wp-content/uploads/2017/08/http-2-1024x484.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wLbb6ePL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://webdevdrops.com/wp-content/uploads/2017/08/http-2-1024x484.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Method&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Also referred as &lt;em&gt;verb&lt;/em&gt;, is the kind of action to be performed (GET information, POST information back to the server, etc). The most common are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GET&lt;/strong&gt;
Retrieve information from the server. For example: a webpage, an image file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;POST&lt;/strong&gt;
Send data to the server. For example: a filled registration form.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PUT&lt;/strong&gt;
Send data to completely replace an existing resource.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PATCH&lt;/strong&gt;
Send data to apply partial modifications to a resource.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DELETE&lt;/strong&gt;
Delete the specific resource from the server.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;URI&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Uniform Resource Identifier — is the path on the server that identify the information (the &lt;em&gt;resource&lt;/em&gt; to be fetched, created, modified).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Header&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Additional information about the request and about the client, in the form of key-value pairs.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Body&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Optional. The content the client sends to the server. GET and DELETE requests usually don’t need one. For POST, PUT and PATCH requests this is where the information to be created or modified is sent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Anatomy of a response
&lt;/h2&gt;

&lt;p&gt;An HTTP response is composed of the following parts:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OzZarkWp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://webdevdrops.com/wp-content/uploads/2017/08/http-3-1024x499.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OzZarkWp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://webdevdrops.com/wp-content/uploads/2017/08/http-3-1024x499.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Status
&lt;/h3&gt;

&lt;p&gt;Indicates, by a numeric code, whether a request has been successfully completed. They are grouped in five classes, identified by the first digit. Some of the most used statuses are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;1xx — Information&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2xx — Success
200 OK&lt;/strong&gt;: The request was completed successfully.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;3xx — Redirect&lt;/strong&gt;
&lt;strong&gt;301 Moved Permanently&lt;/strong&gt;: The resource is permanently located in a different URI. A new URI should be given in the response.
&lt;strong&gt;302 Found&lt;/strong&gt;: The resource temporarily moved to a new location.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;4xx — Client error&lt;/strong&gt;
&lt;strong&gt;400 Bad Request&lt;/strong&gt;: The request could not be understood by the server.
&lt;strong&gt;403 Forbidden&lt;/strong&gt;: User not authorized to perform the requested operation.
&lt;strong&gt;404 Not Found&lt;/strong&gt;: The requested resource could not be found at the given URI.
&lt;strong&gt;405 Method Not Allowed&lt;/strong&gt;: The request method is not allowed on the specified resource.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;5xx — Server error&lt;/strong&gt;
&lt;strong&gt;500 Internal Server Error&lt;/strong&gt;: The server encountered an unexpected condition, preventing it to fulfill the request.
&lt;strong&gt;503 Service Unavailable&lt;/strong&gt;: The server is temporarily unavailable, usually due to overloading or maintenance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a more comprehensive list: &lt;br&gt;
&lt;a href="http://www.restapitutorial.com/httpstatuscodes.html"&gt;http://www.restapitutorial.com/httpstatuscodes.html&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Header
&lt;/h3&gt;

&lt;p&gt;Like the request header, this contains additional information about the server and about the response itself.&lt;/p&gt;
&lt;h3&gt;
  
  
  Body
&lt;/h3&gt;

&lt;p&gt;Optional. This is the content returned by the server.&lt;/p&gt;
&lt;h2&gt;
  
  
  Practical examples: HTTP requests with JavaScript
&lt;/h2&gt;

&lt;p&gt;See some examples of how to send HTTP requests on the frontend and how to handle responses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example #1&lt;/strong&gt;: GET information about the latest React release on GitHub&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;// the request:&lt;/span&gt;
&lt;span class="c1"&gt;// GET information about the latest React release on GitHub&lt;/span&gt;
&lt;span class="c1"&gt;// we don't need to inform the method (GET is the default), &lt;/span&gt;
&lt;span class="c1"&gt;//   headers or body (GET request doesn't need one)&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;https://api.github.com/repos/facebook/react/releases/latest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// the URI&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&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;// we received the response and print the status code&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// return response body as JSON&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="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&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;// print the JSON&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// on success will log:&lt;/span&gt;
&lt;span class="c1"&gt;// 200&lt;/span&gt;
&lt;span class="c1"&gt;// { ... contents of the response body as JSON ... }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example #2&lt;/strong&gt;: POST a new email to be associated to my GitHub account&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;// the request:&lt;/span&gt;
&lt;span class="c1"&gt;// POST a new email address to my GitHub account&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;https://api.github.com/user/emails&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;// the URI&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// the method&lt;/span&gt;
  &lt;span class="na"&gt;body&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="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;octocat@github.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;// the body&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&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;// we received the response and print the status code&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// return response body as JSON&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="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&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;// print the JSON&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// on success will log:&lt;/span&gt;
&lt;span class="c1"&gt;// 201&lt;/span&gt;
&lt;span class="c1"&gt;// { ... contents of the response body as JSON ... }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example #3&lt;/strong&gt;: Handling a failed request (status code different than 2xx)&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;// the request:&lt;/span&gt;
&lt;span class="c1"&gt;// try to GET an nonexistent URI&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;https://api.github.com/nonexistent-uri&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;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="c1"&gt;// we should not reach here&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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="nx"&gt;log&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;status&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;// will log:&lt;/span&gt;
&lt;span class="c1"&gt;// 404&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Additional resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP"&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wikipedia.org/wiki/Hypertext_Transfer_Protocol"&gt;https://wikipedia.org/wiki/Hypertext_Transfer_Protocol&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tutorialspoint.com/http/index.htm"&gt;https://www.tutorialspoint.com/http/index.htm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en/docs/Web/API/Fetch_API"&gt;https://developer.mozilla.org/en/docs/Web/API/Fetch_API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feedback? Suggestions?&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>http</category>
    </item>
    <item>
      <title>How to Access Device Cameras with JavaScript (Front and Rear) </title>
      <dc:creator>Douglas Matoso</dc:creator>
      <pubDate>Sat, 30 May 2020 12:57:38 +0000</pubDate>
      <link>https://dev.to/doug2k1/how-to-access-device-cameras-with-javascript-front-and-rear-48lb</link>
      <guid>https://dev.to/doug2k1/how-to-access-device-cameras-with-javascript-front-and-rear-48lb</guid>
      <description>&lt;p&gt;Hey folks! In this post I will show you how to access the device’s cameras on a web page, via &lt;strong&gt;JavaScript&lt;/strong&gt;, with support for multiple browsers and without the need for external libraries.&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%2Fwww.webdevdrops.com%2Fwp-content%2Fuploads%2F2020%2F05%2Fjavascript-camera.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%2Fwww.webdevdrops.com%2Fwp-content%2Fuploads%2F2020%2F05%2Fjavascript-camera.jpg" alt="How to Access Device Cameras with JavaScript (Front and Rear)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to access the camera
&lt;/h2&gt;

&lt;p&gt;To access the user’s camera (and/or microphone) we use the &lt;strong&gt;JavaScript&lt;/strong&gt; &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Media_Streams_API" rel="noopener noreferrer"&gt;MediaStream API&lt;/a&gt;&lt;/strong&gt;. This API allows to access the video and audio captured by these devices through &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaStream" rel="noopener noreferrer"&gt;streams&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The first step is to check if the browser supports this API:&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mediaDevices&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;getUserMedia&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mediaDevices&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ok, browser supports it&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Support is decent in modern browsers (no Internet Explorer, of course).&lt;/p&gt;

&lt;h2&gt;
  
  
  Capturing the video stream
&lt;/h2&gt;

&lt;p&gt;To capture the video stream generated by the camera, we use the &lt;code&gt;getUserMedia&lt;/code&gt; method of the &lt;code&gt;mediaDevices&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;This method receives an object with the types of media we are requesting (video or audio) and some requirements. To start, we can just pass &lt;code&gt;{video: true}&lt;/code&gt; to get the video from the camera.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;videoStream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mediaDevices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUserMedia&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;video&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This call will ask the user for permission to access the camera. If the user denies it, it throws an exception and does not return the stream. So it must be done inside a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch" rel="noopener noreferrer"&gt;try/catch&lt;/a&gt; block to handle this case.&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%2Fwww.webdevdrops.com%2Fwp-content%2Fuploads%2F2020%2F05%2Fcamera-permission.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%2Fwww.webdevdrops.com%2Fwp-content%2Fuploads%2F2020%2F05%2Fcamera-permission.png" alt="Page requesting to use the camera"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that it returns a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise" rel="noopener noreferrer"&gt;Promise&lt;/a&gt;, so you have to use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function" rel="noopener noreferrer"&gt;async/await&lt;/a&gt; or a &lt;code&gt;then&lt;/code&gt; block.&lt;/p&gt;

&lt;h2&gt;
  
  
  Video requirements
&lt;/h2&gt;

&lt;p&gt;We can improve the requirements of the video by passing information about the desired resolution and minimum and maximum limits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;constraints&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;video&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;min&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1280&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;ideal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1920&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2560&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;min&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;720&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;ideal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1080&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1440&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;videoStream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mediaDevices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUserMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;constraints&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That way the stream comes in the correct proportion of width and height. If it is a cell phone in portrait mode it takes care of inverting the dimensions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Displaying the video on the page
&lt;/h2&gt;

&lt;p&gt;Okay, now that we have the stream, what can we do with it?&lt;/p&gt;

&lt;p&gt;We can display the video on the page, in a &lt;code&gt;video&lt;/code&gt; element:&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;// considering there is a&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;lt;video autoplay id="video"&amp;gt;&amp;lt;/video&amp;gt; &lt;/span&gt;
&lt;span class="c1"&gt;// tag in the page&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;video&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#video&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;videoStream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mediaDevices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUserMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;constraints&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;srcObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;videoStream&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the &lt;code&gt;autoplay&lt;/code&gt; attribute in the &lt;code&gt;video&lt;/code&gt; tag. Without it, you need to call &lt;code&gt;video.play()&lt;/code&gt; to actually start displaying the image.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accessing the phone’s front and rear cameras
&lt;/h2&gt;

&lt;p&gt;By default &lt;code&gt;getUserMedia&lt;/code&gt; will use the system’s default video recording device. In the case of a cell phone with two cameras, it uses the front camera.&lt;/p&gt;

&lt;p&gt;To access the rear camera, we must include &lt;code&gt;facingMode: "environment"&lt;/code&gt; in the video requirements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;constraints&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;video&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;width&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="na"&gt;height&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="na"&gt;facingMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;environment&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;The default is &lt;code&gt;facingMode: "user"&lt;/code&gt;, which is the front camera.&lt;/p&gt;

&lt;p&gt;Be aware that, if you want to change the camera with the video already playing, you will need to stop the current stream before replacing it with the stream from the other camera:&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;videoStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTracks&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;track&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;track&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stop&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;
  
  
  Taking screenshots
&lt;/h2&gt;

&lt;p&gt;Another cool thing you can do is capture images (screenshots) of the video.&lt;/p&gt;

&lt;p&gt;You can draw the current video frame on a canvas, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// considering there is a&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;lt;canvas id="canvas"&amp;gt;&amp;lt;/canvas&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// tag in the page&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#canvas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;videoWidth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;videoHeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;drawImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;video&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also display the canvas content in an &lt;code&gt;img&lt;/code&gt; element.&lt;/p&gt;

&lt;p&gt;In the example I created for this tutorial, I added a button that creates images dynamically from the canvas and adds them to the page. Something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;img&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDataURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;image/png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;screenshotsContainer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prepend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;See the running example here: &lt;a href="https://doug2k1.github.io/javascript-camera/" rel="noopener noreferrer"&gt;https://doug2k1.github.io/javascript-camera/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the complete source code is here: &lt;a href="https://github.com/doug2k1/javascript-camera" rel="noopener noreferrer"&gt;https://github.com/doug2k1/javascript-camera&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>React: Forms and Validations with React Hook Form </title>
      <dc:creator>Douglas Matoso</dc:creator>
      <pubDate>Sun, 10 May 2020 20:44:56 +0000</pubDate>
      <link>https://dev.to/doug2k1/react-forms-and-validations-with-react-hook-form-473d</link>
      <guid>https://dev.to/doug2k1/react-forms-and-validations-with-react-hook-form-473d</guid>
      <description>&lt;p&gt;Hey, folks! In this post I will show you how to work with forms and validation in &lt;strong&gt;React&lt;/strong&gt;, in a simple and efficient way, using the &lt;strong&gt;&lt;a href="https://react-hook-form.com/"&gt;React Hook Form&lt;/a&gt;&lt;/strong&gt; library.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DwTMeyrV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2020/05/react-forms-validation.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DwTMeyrV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2020/05/react-forms-validation.jpg" alt="React Forms"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  React Hook Form x Formik x Redux Form
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;React Hook Form&lt;/strong&gt; brought some improvements over other form manipulation libraries in React, such as &lt;strong&gt;&lt;a href="https://jaredpalmer.com/formik/"&gt;Formik&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://redux-form.com/"&gt;Redux Form&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Among these points are &lt;strong&gt;built-in validation&lt;/strong&gt; (with other libs you need to do the validation manually or install one more lib for that), &lt;strong&gt;performance&lt;/strong&gt; (it makes less renders than other libs when changing fields) and &lt;strong&gt;ease of use&lt;/strong&gt; (with the &lt;strong&gt;React Hook Form&lt;/strong&gt; you need to write less code and the learning curve is shorter).&lt;/p&gt;

&lt;p&gt;And the two cherries on top the cake: it works with &lt;strong&gt;&lt;a href="https://reactnative.dev/"&gt;React Native&lt;/a&gt;&lt;/strong&gt;, with few changes, and for those who use &lt;strong&gt;&lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt;&lt;/strong&gt;, it already comes with its own type definitions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: Login Form
&lt;/h2&gt;

&lt;p&gt;Let’s see in practice how to work with React Hook Form by building a login form.&lt;/p&gt;

&lt;p&gt;To start, let’s create a pretty basic &lt;code&gt;LoginForm&lt;/code&gt; component, with the email and password fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./LoginForm.css&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;LoginForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&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;login-form&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="nx"&gt;htmlFor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inputEmail&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;E&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;mail&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/label&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;
          &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inputEmail&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&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="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})}&lt;/span&gt;
        &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="nx"&gt;htmlFor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inputPassword&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Password&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/label&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;
          &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inputPassword&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&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="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})}&lt;/span&gt;
        &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Login&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/form&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;LoginForm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now we need to install &lt;strong&gt;React Hook Form&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i react-hook-form
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And import the &lt;code&gt;useForm&lt;/code&gt; hook in our component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;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="s2"&gt;react-hook-form&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;From the properties the hook returns, we will need &lt;code&gt;handleSubmit&lt;/code&gt;, &lt;code&gt;register&lt;/code&gt; and &lt;code&gt;errors&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;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="nx"&gt;errors&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Registering fields
&lt;/h3&gt;

&lt;p&gt;The first property, &lt;code&gt;register&lt;/code&gt;, is a function that registers fields. You need to register each field that you want to be managed by the React Hook Form, through the field’s prop &lt;code&gt;ref&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&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="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Getting form data on submit
&lt;/h3&gt;

&lt;p&gt;The next property, &lt;code&gt;handleSubmit&lt;/code&gt;, it’s used to handle the form submission and get the filled data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;LoginForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;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="nx"&gt;errors&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;function&lt;/span&gt; &lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Data submitted: &lt;/span&gt;&lt;span class="dl"&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="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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&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;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="c1"&gt;//... campos do formulário&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/form&lt;/span&gt;&lt;span class="err"&gt;&amp;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;Our &lt;code&gt;onSubmit&lt;/code&gt; function will receive an object with the form’s data, that we can send to some backend api or do whatever we want with it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Validating and showing errors
&lt;/h3&gt;

&lt;p&gt;To add field validation, we need to pass some parameters to the register function, informing the validation rules and error messages, in case the validation does not pass.&lt;/p&gt;

&lt;p&gt;See how our email field looks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&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="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Enter your e-mail&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="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;A-Z0-9._%+-&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;+@&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;A-Z0-9.-&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;\.[&lt;/span&gt;&lt;span class="sr"&gt;A-Z&lt;/span&gt;&lt;span class="se"&gt;]{2,4}&lt;/span&gt;&lt;span class="sr"&gt;$/i&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Enter a valid e-mail address&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="p"&gt;})}&lt;/span&gt;
 &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We have two validations: required field (required) and a regular expression (pattern) to validate that the email is in the right format.&lt;/p&gt;

&lt;p&gt;With that, the React Hook Form will prevent the form from being sent if any field fails validation.&lt;/p&gt;

&lt;p&gt;To display the error messages to the user, we will use the other hook property: &lt;code&gt;errors&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&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="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Enter your e-mail&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="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;A-Z0-9._%+-&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;+@&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;A-Z0-9.-&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;\.[&lt;/span&gt;&lt;span class="sr"&gt;A-Z&lt;/span&gt;&lt;span class="se"&gt;]{2,4}&lt;/span&gt;&lt;span class="sr"&gt;$/i&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Enter a valid e-mail address&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="p"&gt;})}&lt;/span&gt;
 &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;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="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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="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;error&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;{&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;errors&lt;/code&gt; property will be automatically filled in with the field errors, which we can use to show a message below each invalid field. We could also use it to change some CSS class and change the style of the error fields (add a red border, some icon, etc.).&lt;/p&gt;

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

&lt;p&gt;The complete code for this example is in GitHub: &lt;a href="https://github.com/doug2k1/react-login-form"&gt;https://github.com/doug2k1/react-login-form&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see the form in action below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.webdevdrops.com/wp-content/uploads/2020/05/demo-react-login-form.mp4"&gt;https://www.webdevdrops.com/wp-content/uploads/2020/05/demo-react-login-form.mp4&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
    </item>
    <item>
      <title>Node.js with TypeScript </title>
      <dc:creator>Douglas Matoso</dc:creator>
      <pubDate>Sun, 03 May 2020 19:27:40 +0000</pubDate>
      <link>https://dev.to/doug2k1/node-js-with-typescript-6go</link>
      <guid>https://dev.to/doug2k1/node-js-with-typescript-6go</guid>
      <description>&lt;p&gt;Hey, folks! In this post I will show you how you can develop in &lt;strong&gt;&lt;a href="https://nodejs.org/"&gt;Node.js&lt;/a&gt;&lt;/strong&gt; using &lt;strong&gt;&lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt;&lt;/strong&gt; and have the &lt;a href="https://apiumhub.com/tech-blog-barcelona/top-typescript-advantages/"&gt;benefits of this language&lt;/a&gt; also in the backend.&lt;/p&gt;

&lt;h2&gt;
  
  
  ts-node-dev
&lt;/h2&gt;

&lt;p&gt;To transpile &lt;strong&gt;TypeScript&lt;/strong&gt; code to &lt;strong&gt;JavaScript&lt;/strong&gt;, we will use &lt;strong&gt;&lt;a href="https://www.npmjs.com/package/ts-node-dev"&gt;ts-node-dev&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It provides an executable that we will use instead of Node to run TypeScript code. Behind the scenes it will transform TypeScript into JavaScript and execute it using Node itself.&lt;/p&gt;

&lt;p&gt;Another nice thing about ts-node-dev is that it also replaces &lt;strong&gt;&lt;a href="https://www.npmjs.com/package/nodemon"&gt;nodemon&lt;/a&gt;&lt;/strong&gt;, so whenever we change a .ts file it will reload the application to reflect the changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;We will need &lt;strong&gt;ts-node-dev&lt;/strong&gt; and the &lt;strong&gt;typescript&lt;/strong&gt; itself as development dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; ts-node-dev typescript
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We will also need a config file for the TypeScript compiler. We can generate a default configuration with the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npx tsc &lt;span class="nt"&gt;--init&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It will create a &lt;code&gt;tsconfig.json&lt;/code&gt; at the root of the application. You can customize the options, but the default will work for us.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing the code
&lt;/h2&gt;

&lt;p&gt;With this setup we can now write the application code using .ts files and all TypeScript functionality.&lt;/p&gt;

&lt;p&gt;As an example, let’s create a “Hello World” with &lt;strong&gt;&lt;a href="https://expressjs.com/"&gt;Express.js&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We will need to install &lt;strong&gt;express&lt;/strong&gt; itself, and also the type definitions for it. Note that &lt;strong&gt;express&lt;/strong&gt; is an application dependency, while type definitions are development dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i express
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; @types/express
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Some libraries already provide their own type definitions, so this second installation is not necessary. You will find out if a lib needs it when you try to import it into the code and the editor complains that the type definitions are missing.&lt;/p&gt;

&lt;p&gt;For our “Hello, World” I will write this code in an &lt;code&gt;index.ts&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;,&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;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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="nx"&gt;use&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="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&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;request&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="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="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, TypeScript!&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🚀 Server started on http://localhost:3000&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;Note that we can use &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import"&gt;ES Modules&lt;/a&gt;&lt;/strong&gt; (import … from …).&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the application
&lt;/h2&gt;

&lt;p&gt;To run the application, let’s add this &lt;code&gt;start&lt;/code&gt; script, in &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ts-node-dev --transpileOnly --ignore-watch node_modules index.ts"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I’ve added some options to make the transpilation process quicker:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--transpileOnly&lt;/code&gt; will tell it to just transpile, without doing type checking. This checking can be done in the editor, pointing the errors directly in our code.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--ignore-watch node_modules&lt;/code&gt; is saying to ignore &lt;code&gt;node_modules&lt;/code&gt; files, as we are not going to tamper with these files and hope they are already in JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Production
&lt;/h2&gt;

&lt;p&gt;In production, as we want maximum performance, we will use Node directly with the code transpiled in JavaScript. For that we can add a build script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tsc"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It will use the TypeScript compiler to transpile all the .ts code and save the corresponding .js files to disk.&lt;/p&gt;

&lt;h2&gt;
  
  
  Concluding
&lt;/h2&gt;

&lt;p&gt;The final code for this example is here: &lt;a href="https://github.com/doug2k1/node-typescript"&gt;https://github.com/doug2k1/node-typescript&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;TypeScript has many advantages, and the integration with other tools is becoming more mature every day. It is easier to adopt, either on the frontend or backend, and is an interesting option for most projects.&lt;/p&gt;

</description>
      <category>node</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Git on Windows and GitHub: How to Install and Configure</title>
      <dc:creator>Douglas Matoso</dc:creator>
      <pubDate>Fri, 03 Apr 2020 12:58:14 +0000</pubDate>
      <link>https://dev.to/doug2k1/git-on-windows-and-github-how-to-install-and-configure-3gi6</link>
      <guid>https://dev.to/doug2k1/git-on-windows-and-github-how-to-install-and-configure-3gi6</guid>
      <description>&lt;p&gt;In this post I will make a simple tutorial on how to use &lt;a href="http://git-scm.com/"&gt;&lt;strong&gt;Git&lt;/strong&gt;&lt;/a&gt; on Windows and commit your code to &lt;a href="http://www.github.com/"&gt;&lt;strong&gt;GitHub&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1) Install Git on Windows
&lt;/h2&gt;

&lt;p&gt;On the official &lt;strong&gt;Git&lt;/strong&gt; website (&lt;a href="http://git-scm.com/"&gt;http://git-scm.com/&lt;/a&gt;) click on “ &lt;strong&gt;Downloads for Windows&lt;/strong&gt; ”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--F_onsHJD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/09/git-windows-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--F_onsHJD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/09/git-windows-1.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run the downloaded file and go “ &lt;strong&gt;Next&lt;/strong&gt; ” to the “ &lt;strong&gt;Select Components&lt;/strong&gt; ” screen. In this screen I choose the options as in the image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pjGGvvGu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/09/git-windows-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pjGGvvGu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/09/git-windows-2.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In particular I check the options under “ &lt;strong&gt;Windows Explorer integration&lt;/strong&gt; ”, so I can open the Git command prompt (&lt;strong&gt;&lt;a href="https://www.webdevdrops.com/git-bash-como-instalar-usar/"&gt;Git Bash&lt;/a&gt;&lt;/strong&gt;) in any folder, just right click and “ &lt;strong&gt;Git Bash Here&lt;/strong&gt; ”. The last option is also interesting, because it installs a better font for the command prompt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; : Git for Windows comes with its own command prompt (&lt;strong&gt;&lt;a href="https://www.webdevdrops.com/git-bash-como-instalar-usar/"&gt;Git Bash&lt;/a&gt;&lt;/strong&gt;), which in addition to git commands also provides some Unix commands that can be quite useful (in addition to being much nicer than the standard Windows command prompt) .&lt;/p&gt;

&lt;p&gt;On the next screen, I choose the option: “ &lt;strong&gt;Use Git from the Windows Command Prompt&lt;/strong&gt; “.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--013fvlcc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/09/git-windows-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--013fvlcc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/09/git-windows-3.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This option allows you to use the &lt;code&gt;git&lt;/code&gt; command both in Git Bash and in the standard Windows terminal.&lt;/p&gt;

&lt;p&gt;The third option adds Unix commands to the Windows terminal, in addition to the git command itself, but some Windows commands will be replaced by Unix commands that have the same name (such as find and sort).&lt;/p&gt;

&lt;p&gt;Another important configuration: &lt;strong&gt;line endings&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gj9RLaNw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/09/git-windows-4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gj9RLaNw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/09/git-windows-4.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you may know Windows and Unix systems (Linux, Mac) have different line breaks in text files. If you write code with line breaks in Windows format, someone else may have problems opening the same file on Linux, and vice versa. This option allows you to normalize this.&lt;/p&gt;

&lt;p&gt;The first option converts files to Windows standard when you pull the files, and converts them to Unix format when you commit them to the repository. The second option does not do any conversion when the files arrive, but converts to Unix format when you commit. The third option does not convert at all.&lt;/p&gt;

&lt;p&gt;I choose the second one, because I prefer to keep everything in the Unix format (since any good code editor can read files in the Unix standard even if they are on Windows).&lt;/p&gt;

&lt;p&gt;That done, “ &lt;strong&gt;Next&lt;/strong&gt; “, “ &lt;strong&gt;Finish&lt;/strong&gt; ” and Git is installed.&lt;/p&gt;

&lt;h2&gt;
  
  
  2) Create a local Git repository and commit your first changes
&lt;/h2&gt;

&lt;p&gt;Let’s test it? Create a folder on your computer, right click it and “ &lt;strong&gt;Git Bash Here&lt;/strong&gt; ”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CfIK3Gjm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/09/git-windows-5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CfIK3Gjm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/09/git-windows-5.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First of all, inform Git your name and e-mail, which will identify your commits. Enter the commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git config --global user.name "Your Name"   
git config --global user.email "your_email@email.com"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt; : to copy and paste commands in Git Bash, right click on the terminal screen.&lt;/p&gt;

&lt;p&gt;Now we are going to initialize a Git repository in this folder we are in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git init
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--brgnIjWH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/09/git-windows-6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--brgnIjWH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/09/git-windows-6.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Did you see this &lt;code&gt;(master)&lt;/code&gt; text that appeared on the command line? It indicates that you are in a Git repository, on the master branch. Nice, huh?&lt;/p&gt;

&lt;p&gt;Let’s add an empty file to this repository and commit it. See the sequence of commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch test.txt   
git add .   
git commit -m "First commit"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;First we create an empty &lt;strong&gt;test.txt&lt;/strong&gt; file. Then we add all the new files (in this case, just test.txt) to the index of the repository, and finally we commit all the files that are in the index and have been modified.&lt;/p&gt;

&lt;h2&gt;
  
  
  3) Push to GitHub
&lt;/h2&gt;

&lt;p&gt;Cool, you have a Git repository on your machine, but how about sharing your codes on GitHub and enjoying all that this community has to offer?&lt;/p&gt;

&lt;h3&gt;
  
  
  3.1) Initial preparation
&lt;/h3&gt;

&lt;p&gt;Go to &lt;a href="https://github.com/"&gt;https://github.com/&lt;/a&gt; and click on “ &lt;strong&gt;Sign Up&lt;/strong&gt; ” to create your free account.&lt;/p&gt;

&lt;p&gt;Having registered and logged into your account, you now need an &lt;strong&gt;SSH key&lt;/strong&gt; to start committing. In Git Bash type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh-keygen -t rsa -C "your_email@email.com"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Enter your e-mail address registered on &lt;strong&gt;GitHub&lt;/strong&gt;. Hit Enter on the next question (about the file to be created – let’s leave the defaults).&lt;/p&gt;

&lt;p&gt;The next question will ask you for a &lt;strong&gt;passphrase&lt;/strong&gt;. Create a password and enter it. He will ask for confirmation. Type the password again and Enter. Type now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;notepad ~/.ssh/id_rsa.pub
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;to open the file that was created in Notepad.&lt;/p&gt;

&lt;p&gt;Now on &lt;strong&gt;GitHub&lt;/strong&gt; , go to “ &lt;strong&gt;Settings&lt;/strong&gt; ” and then “ &lt;strong&gt;SSH and GPG Keys&lt;/strong&gt; “. Click “ &lt;strong&gt;New SSH key&lt;/strong&gt; ”. Enter a title to identify the computer where the key was generated and in the “ &lt;strong&gt;Key&lt;/strong&gt; ” field, paste all the contents of the file &lt;strong&gt;id_rsa.pub&lt;/strong&gt; (which you opened in Notepad)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TPbHP0m5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/09/git-windows-7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TPbHP0m5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/09/git-windows-7.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Be careful to copy and paste the entire contents of the file, starting with “ssh-rsa…” and including your email (as in the image). Click on “ &lt;strong&gt;Add Key&lt;/strong&gt; “.&lt;/p&gt;

&lt;p&gt;Let’s test to see if it worked. In Git Bash type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh -T git@github.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It will ask if you are sure you want to connect (yes / no). Type &lt;strong&gt;yes&lt;/strong&gt; and Enter. In the next question (Enter passphrase …) enter your password (the one you chose when creating the SSH key).&lt;/p&gt;

&lt;p&gt;If you receive a message like:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Hi doug2k1! You’ve successfully authenticated, but GitHub does not provide shell access.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So everything worked out!&lt;/p&gt;

&lt;h3&gt;
  
  
  3.2) Create the remote repository
&lt;/h3&gt;

&lt;p&gt;On &lt;strong&gt;GitHub&lt;/strong&gt; we will create a new repository (“ &lt;strong&gt;New Repository&lt;/strong&gt; ” button on your dashboard). Enter a name without spaces and special characters. The other options do not need to change.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lbywjoSC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/09/git-windows-8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lbywjoSC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/09/git-windows-8.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will be taken to the page of your repository, which has no files yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important!&lt;/strong&gt; If the email informed to Git at the beginning of &lt;strong&gt;step 2&lt;/strong&gt; is not the one used to register with &lt;strong&gt;GitHub&lt;/strong&gt; , redo the command informing the registered email. That way, &lt;strong&gt;GitHub&lt;/strong&gt; will be able to link the commits to your account.&lt;/p&gt;

&lt;p&gt;In Git Bash (in your local repository folder) type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git remote add origin git@github.com:login/repository.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note that login / repository must be entered as it appears in the URL of your repository, in the example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/doug2k1/projeto-tutorial"&gt;https://github.com/doug2k1/projeto-tutorial&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now to update &lt;strong&gt;GitHub&lt;/strong&gt; with the contents in your local repository, type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git push -u origin master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Enter your password (for the SSH key) when prompted.&lt;/p&gt;

&lt;p&gt;Reload your repository page and now, instead of the initial message, you will see your commits and files.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3gfdTnGO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/09/git-windows-9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3gfdTnGO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/09/git-windows-9.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4) Conclusion
&lt;/h2&gt;

&lt;p&gt;Even though &lt;strong&gt;Git&lt;/strong&gt; originated on &lt;strong&gt;Linux&lt;/strong&gt; (Did you know that Linus Torvalds created it?), &lt;strong&gt;Windows&lt;/strong&gt; users can also benefit from it, thanks to &lt;strong&gt;Git for Windows&lt;/strong&gt;. In addition to &lt;strong&gt;Git&lt;/strong&gt; itself being an excellent version control system, the open-source community that populates &lt;strong&gt;GitHub&lt;/strong&gt; is vibrant. It’s rewarding as finding a code that “saves your skin” and also being able to contribute to a project, make forks, share.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://git-scm.com/"&gt;Git  – Official Site&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://github.com/"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://try.github.io/"&gt;Resources to learn Git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/doug2k1"&gt;My GitHub page&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The post &lt;a href="https://www.webdevdrops.com/en/git-on-windows-github-install-configure/"&gt;Git on Windows and GitHub: How to Install and Configure&lt;/a&gt; first appeared in &lt;a href="https://www.webdevdrops.com/en"&gt;Web Dev Drops&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
    </item>
    <item>
      <title>Build a static site generator in 40 lines with Node.js </title>
      <dc:creator>Douglas Matoso</dc:creator>
      <pubDate>Thu, 02 Apr 2020 18:30:17 +0000</pubDate>
      <link>https://dev.to/doug2k1/build-a-static-site-generator-in-40-lines-with-node-js-4l92</link>
      <guid>https://dev.to/doug2k1/build-a-static-site-generator-in-40-lines-with-node-js-4l92</guid>
      <description>&lt;p&gt;There are excellent &lt;strong&gt;static site generators&lt;/strong&gt; out there, in different languages, with lots of features, but actually building your own is easier than you might think, and we learn some things in the process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zO5QxLlh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/10/static-site-generator-1024x682.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zO5QxLlh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/10/static-site-generator-1024x682.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why build your own?
&lt;/h2&gt;

&lt;p&gt;When I was planning to build my own personal website — a simple portfolio-like site, with few pages, with some info about myself, my skills and projects — I decided it should be static (it’s fast, no need to setup a backend and can be hosted anywhere). I had some experience with &lt;a href="https://jekyllrb.com/"&gt;&lt;strong&gt;Jekyll&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://gohugo.io/"&gt;&lt;strong&gt;Hugo&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://hexo.io/"&gt;&lt;strong&gt;Hexo&lt;/strong&gt;&lt;/a&gt;, but I think they have too many features for my simple project. So I thought it shouldn’t be that hard to build something small, with just the features I need.&lt;/p&gt;

&lt;h2&gt;
  
  
  The requirements
&lt;/h2&gt;

&lt;p&gt;The requirements this generator must satisfy are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate HTML files from &lt;a href="http://ejs.co/"&gt;&lt;strong&gt;EJS&lt;/strong&gt;&lt;/a&gt; templates&lt;/li&gt;
&lt;li&gt;Have a layout file, so all pages have the same header, footer, navigation, etc.&lt;/li&gt;
&lt;li&gt;Allow partials (blocks of reusable interface components)&lt;/li&gt;
&lt;li&gt;Read global site config from a file (site title, description, etc.)&lt;/li&gt;
&lt;li&gt;Read data from JSON files. For example: list of projects, so I can easily iterate and build the “Projects” page&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why EJS templates?&lt;/strong&gt;&lt;br&gt;
Because EJS is simple. There is no new template language to learn. It’s just JavaScript embedded in HTML.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Folder structure
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public/  
 src/  
   assets/  
   data/  
   pages/  
   partials/  
   layout.ejs  
 site.config.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;public:&lt;/strong&gt; where the generated site will be.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;src:&lt;/strong&gt; the source of the site contents.
&lt;strong&gt;src/assets:&lt;/strong&gt; contains CSS, JS, images, etc.
&lt;strong&gt;src/data:&lt;/strong&gt; contains JSON data.
&lt;strong&gt;src/pages:&lt;/strong&gt; are the templates that will be rendered to HTML. The directory structure found here will be replicated in the resulting site.
&lt;strong&gt;src/partials:&lt;/strong&gt; contains our reusable partials.
&lt;strong&gt;src/layout.ejs:&lt;/strong&gt; contains the common page structure, with a special placeholder, where the contents of each page will be inserted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;site.config.js&lt;/strong&gt;: it just exports an object that will be available in the page templates.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The generator
&lt;/h2&gt;

&lt;p&gt;The generator code is inside a single file, &lt;em&gt;scripts/build.js&lt;/em&gt;, that we can run with &lt;code&gt;npm run build&lt;/code&gt;, every time we want to rebuild the site, by adding the following script to our &lt;em&gt;package.json&lt;/em&gt;&lt;code&gt;scripts&lt;/code&gt; block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"build": "node ./scripts/build"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is the complete generator: &lt;br&gt;
(Below I explain each part of the code.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;fse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;fs-extra&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;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;path&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;promisify&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;util&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;ejsRenderFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;promisify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ejs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;renderFile&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;globP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;promisify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;glob&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;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;../site.config&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;srcPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;distPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// clear destination folder&lt;/span&gt;
&lt;span class="nx"&gt;fse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emptyDirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;distPath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// copy assets folder&lt;/span&gt;
&lt;span class="nx"&gt;fse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;copy&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="nx"&gt;srcPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/assets`&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="nx"&gt;distPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/assets`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// read page templates&lt;/span&gt;
&lt;span class="nx"&gt;globP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;**/*.ejs&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;cwd&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="nx"&gt;srcPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/pages`&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;files&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;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;file&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;fileData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&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;destPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;distPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fileData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="c1"&gt;// create destination directory&lt;/span&gt;
      &lt;span class="nx"&gt;fse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mkdirs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;destPath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;// render page&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ejsRenderFile&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="nx"&gt;srcPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/pages/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;file&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="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assign&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="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;pageContents&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;// render layout with page contents&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ejsRenderFile&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="nx"&gt;srcPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/layout.ejs`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assign&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pageContents&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;layoutContent&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;// save the html file&lt;/span&gt;
          &lt;span class="nx"&gt;fse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeFile&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="nx"&gt;destPath&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="nx"&gt;fileData&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="s2"&gt;.html`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;layoutContent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;
  
  
  Dependencies
&lt;/h3&gt;

&lt;p&gt;For this basic feature set we only need three dependencies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://ejs.co/"&gt;&lt;strong&gt;ejs&lt;/strong&gt;&lt;/a&gt;
Compile our templates to HTML.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/fs-extra"&gt;&lt;strong&gt;fs-extra&lt;/strong&gt;&lt;/a&gt;
Adds new functions to Node’s native file-system module (&lt;a href="https://nodejs.org/api/fs.html"&gt;&lt;strong&gt;fs&lt;/strong&gt;&lt;/a&gt;) and add promise support for the existing ones.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/glob"&gt;&lt;strong&gt;glob&lt;/strong&gt;&lt;/a&gt;
Recursively read a directory, returning an array with all files that match an specified pattern.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Promisify all the things!
&lt;/h3&gt;

&lt;p&gt;One thing to note in our code is that we use Node’s &lt;a href="https://nodejs.org/api/util.html#util_util_promisify_original"&gt;&lt;em&gt;util.promisify&lt;/em&gt;&lt;/a&gt; function to convert all callback-based functions to promise-based. It makes our code shorter, cleaner and easier to read.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;promisify&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;util&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;ejsRenderFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;promisify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ejs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;renderFile&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;globP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;promisify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;glob&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Load the config
&lt;/h3&gt;

&lt;p&gt;At the top we load the site config file, to later inject it in the templates rendering.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;../site.config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The site config file itself load the additional JSON data, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;projects&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;./src/data/projects&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;site&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;NanoGen&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Micro Static Site Generator in Node.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="nx"&gt;projects&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;
  
  
  Empty the public folder
&lt;/h3&gt;

&lt;p&gt;We use &lt;em&gt;emptyDirSync&lt;/em&gt; from &lt;strong&gt;fs-extra&lt;/strong&gt; to empty the public folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emptyDirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;distPath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Copy assets
&lt;/h3&gt;

&lt;p&gt;Here we use the &lt;em&gt;copy&lt;/em&gt; method from &lt;strong&gt;fs-extra&lt;/strong&gt;, that recursively copy a folder with contents.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;copy&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="nx"&gt;srcPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/assets`&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="nx"&gt;distPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/assets`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Compile the pages templates
&lt;/h3&gt;

&lt;p&gt;First we use &lt;strong&gt;glob&lt;/strong&gt; (our &lt;em&gt;promisified&lt;/em&gt; version) to recursively read the &lt;em&gt;src/pages&lt;/em&gt; folder looking for .ejs files. It will return an array with the paths of found files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;globP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;**/*.ejs&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;cwd&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="nx"&gt;srcPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/pages`&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;  
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;files&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;For each template file found we use the Node’s &lt;a href="https://nodejs.org/api/path.html"&gt;&lt;strong&gt;path&lt;/strong&gt;&lt;/a&gt;.parse function to separate the components of the file path (like dir, name and extension). Then we create a corresponding folder in the public directory with &lt;strong&gt;fs-extra&lt;/strong&gt; &lt;em&gt;mkdirs&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;file&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;fileData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&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;destPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;distPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fileData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

 &lt;span class="c1"&gt;// create destination directory  &lt;/span&gt;
  &lt;span class="nx"&gt;fse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mkdirs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;destPath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We then use &lt;strong&gt;EJS&lt;/strong&gt; to compile the file, passing the config data. Since we are using a &lt;em&gt;promisified&lt;/em&gt; version of &lt;em&gt;ejs.renderFile&lt;/em&gt;, we can return the call and handle the result in the next promise chain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="c1"&gt;// render page  &lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ejsRenderFile&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="nx"&gt;srcPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/pages/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;file&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="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assign&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="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the next &lt;em&gt;then&lt;/em&gt; block we have the compiled page template. Now we compile the layout file, passing the page contents as a &lt;code&gt;body&lt;/code&gt; attribute.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;pageContents&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;// render layout with page contents  &lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ejsRenderFile&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="nx"&gt;srcPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/layout.ejs`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assign&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pageContents&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;Finally we take the resulting compiled string (HTML of layout + page contents) and save to an HTML file, with the same path and name of the template.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;layoutContent&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;// save the html file  &lt;/span&gt;
  &lt;span class="nx"&gt;fse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeFile&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="nx"&gt;destPath&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="nx"&gt;fileData&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="s2"&gt;.html`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;layoutContent&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;
  
  
  Development server
&lt;/h2&gt;

&lt;p&gt;To make it easier to view the results, we add a simple development server, like the &lt;a href="https://www.npmjs.com/package/serve"&gt;serve&lt;/a&gt; module and the the following to our &lt;em&gt;package.json&lt;/em&gt;&lt;code&gt;scripts&lt;/code&gt; block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"serve": "serve ./public"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then run &lt;code&gt;npm run serve&lt;/code&gt; and go to &lt;a href="http://localhost:5000"&gt;http://localhost:5000&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Result
&lt;/h3&gt;

&lt;p&gt;The complete example at this stage can be found here: &lt;a href="https://github.com/doug2k1/nanogen/tree/legacy"&gt;https://github.com/doug2k1/nanogen/tree/legacy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Edit:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;after some time I decided to turn the project into a CLI module, to make it easier to use, which is in the&lt;/em&gt;&lt;code&gt;master&lt;/code&gt; &lt;em&gt;branch of the repository. The original code created at the end of this post is in the&lt;/em&gt;&lt;code&gt;legacy&lt;/code&gt; &lt;em&gt;branch (link above).&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus Feature 1: Markdown and front matter
&lt;/h2&gt;

&lt;p&gt;Most static site generators allow writing content in &lt;a href="https://en.wikipedia.org/wiki/Markdown"&gt;Markdown&lt;/a&gt; format. Also, most of them allow adding some metadata on top of each page (aka &lt;strong&gt;front matter&lt;/strong&gt;) in the &lt;a href="http://yaml.org/"&gt;YAML&lt;/a&gt; format, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;  
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Hello World&lt;/span&gt;  
&lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2013/7/13 20:46:25&lt;/span&gt;  
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With a few changes we could add the same features to our micro generator.&lt;/p&gt;

&lt;h3&gt;
  
  
  New dependencies
&lt;/h3&gt;

&lt;p&gt;We must add two more dependencies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/marked"&gt;&lt;strong&gt;marked&lt;/strong&gt;&lt;/a&gt;
Compile Markdown to HTML.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/front-matter"&gt;&lt;strong&gt;front-matter&lt;/strong&gt;&lt;/a&gt;
Extract meta data (front matter) from documents.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Include the new file types
&lt;/h3&gt;

&lt;p&gt;We change the &lt;strong&gt;glob&lt;/strong&gt; pattern to include .md files. We leave .ejs, to allow for more complex pages that could not be possible with Markdown, and we also include .html, in case we want to include some pure HTML pages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;globP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;**/*.@(md|ejs|html)&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;cwd&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="nx"&gt;srcPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/pages`&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Extract front matter
&lt;/h3&gt;

&lt;p&gt;Then, for each file path we have to actually load the file contents, so &lt;strong&gt;front-matter&lt;/strong&gt; can extract the meta data at the top.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="c1"&gt;// read page file  &lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readFile&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="nx"&gt;srcPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/pages/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;file&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf-8&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;We pass the loaded contents to &lt;strong&gt;front-matter&lt;/strong&gt;. It will return and object with the meta data in the &lt;code&gt;attributes&lt;/code&gt; property and the rest of the content in the &lt;code&gt;body&lt;/code&gt; property. We then augment the site config with this data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="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;// extract front matter  &lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pageData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;frontMatter&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;templateConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assign&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pageData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Compile files to HTML
&lt;/h3&gt;

&lt;p&gt;Now we compile the page content to HTML depending on the file extension. If is .md, we send to &lt;strong&gt;marked&lt;/strong&gt;, if .ejs we continue to use &lt;strong&gt;EJS&lt;/strong&gt;, else (is .html) there is no need to compile.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;pageContent&lt;/span&gt;  

&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.md&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
    &lt;span class="nx"&gt;pageContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;marked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pageData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="k"&gt;break&lt;/span&gt;  
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.ejs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
    &lt;span class="nx"&gt;pageContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ejs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pageData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;templateConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="k"&gt;break&lt;/span&gt;  
  &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
    &lt;span class="nx"&gt;pageContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pageData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, we render the layout, as before, sending the compiled page contents as &lt;code&gt;body&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One nice thing with front matter is that now we can set individual titles for each page, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;  
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Another Page&lt;/span&gt;  
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And have the layout dynamically render them like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;title&amp;gt;&amp;lt;%= page.title ? `${page.title} | ` : '' %&amp;gt;&amp;lt;%= site.title %&amp;gt;&amp;lt;/title&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Each page will have a unique &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; tag.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus Feature 2: Multiple layouts
&lt;/h2&gt;

&lt;p&gt;Another interesting feature is the ability to use a different layout in specific pages. Since our pages now can have front matter, we may use it to set a different layout than the default:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;  
&lt;span class="na"&gt;layout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;minimal&lt;/span&gt;  
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Separate the layout files
&lt;/h3&gt;

&lt;p&gt;We need to have separate layout files. I’ve put them in the &lt;em&gt;src/layouts&lt;/em&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/layouts/  
   default.ejs  
   mininal.ejs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Render the correct layout
&lt;/h3&gt;

&lt;p&gt;If the front matter &lt;code&gt;layout&lt;/code&gt; attribute is present, we render the layout file with the same name in the &lt;em&gt;layouts&lt;/em&gt; folder. If it is not set, we render the &lt;em&gt;default&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pageData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;layout&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ejsRenderFile&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="nx"&gt;srcPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/layouts/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.ejs`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="nx"&gt;templateConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pageContent&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;
  
  
  Result
&lt;/h3&gt;

&lt;p&gt;The complete code, with the extra features, can be found here: &lt;a href="https://github.com/doug2k1/nanogen/tree/v1"&gt;https://github.com/doug2k1/nanogen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even with the added features, the build script has about 60 lines. 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;If you want to go even further, some additional features that shouldn’t be difficult to add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dev server with live reloading&lt;/strong&gt;
You may use modules like &lt;a href="https://www.npmjs.com/package/live-server"&gt;&lt;strong&gt;live-server&lt;/strong&gt;&lt;/a&gt; (has auto reload built in) and &lt;a href="https://www.npmjs.com/package/chokidar"&gt;&lt;strong&gt;chokidar&lt;/strong&gt;&lt;/a&gt; (watch for file modifications to automatically trigger the build script).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic deploys&lt;/strong&gt;
Add scripts to deploy the site to common hosting services like &lt;a href="https://pages.github.com/"&gt;&lt;strong&gt;GitHub Pages&lt;/strong&gt;&lt;/a&gt;, or simply copy the files to your own server via SSH (with commands like &lt;a href="http://www.hypexr.org/linux_scp_help.php"&gt;scp&lt;/a&gt; or &lt;a href="https://rsync.samba.org/"&gt;rsync&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Support for CSS/JS preprocessors&lt;/strong&gt;
Add some preprocessing to your assets files (SASS to CSS, ES6 to ES5, etc) before copying to the public folder.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better console output&lt;/strong&gt;
Add some &lt;code&gt;console.log&lt;/code&gt; calls to better indicate what is going on. You could use a module like &lt;a href="https://www.npmjs.com/package/chalk"&gt;&lt;strong&gt;chalk&lt;/strong&gt;&lt;/a&gt; to make it even prettier.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feedback? Suggestions? Feel free to comment or contact me!&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.webdevdrops.com/en/build-static-site-generator-nodejs-8969ebe34b22/"&gt;Build a static site generator in 40 lines with Node.js&lt;/a&gt; first appeared in &lt;a href="https://www.webdevdrops.com"&gt;Web Dev Drops&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
    </item>
    <item>
      <title>Webpack sem Medo — Parte 1: Introdução </title>
      <dc:creator>Douglas Matoso</dc:creator>
      <pubDate>Thu, 02 Apr 2020 18:28:58 +0000</pubDate>
      <link>https://dev.to/doug2k1/webpack-sem-medo-parte-1-introducao-2bpk</link>
      <guid>https://dev.to/doug2k1/webpack-sem-medo-parte-1-introducao-2bpk</guid>
      <description>&lt;p&gt;Esta série tem o objetivo de apresentar as funcionalidades do &lt;a href="https://webpack.js.org/"&gt;&lt;strong&gt;webpack&lt;/strong&gt;&lt;/a&gt; de forma gradativa, explicando conceitos e mostrando exemplos.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Por que “sem medo”?&lt;/strong&gt;&lt;br&gt;
Conheço algumas pessoas (incluindo eu mesmo) que tiveram um primeiro contato com &lt;strong&gt;webpack&lt;/strong&gt;, não entenderam direito como usar, ficaram mais confusas ainda lendo a documentação e criaram uma aversão à ferramenta.&lt;br&gt;
Muitas dessas pessoas tiveram contato com a versão 1 do &lt;strong&gt;webpack&lt;/strong&gt;, que tinha uma configuração mais confusa e uma documentação menos organizada.&lt;br&gt;
A boa notícia é que a partir da versão 2 isso mudou radicalmente. A configuração ficou mais fácil de compreender, e a documentação foi completamente reescrita, com excelentes guias, explicações claras e completas.&lt;br&gt;
&lt;strong&gt;Se tinha medo do webpack, a hora de perder o medo é essa!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Mas o que é webpack?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WbjdsOtz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/10/webpack-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WbjdsOtz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/10/webpack-1.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;webpack&lt;/strong&gt; é um &lt;em&gt;module bundler&lt;/em&gt; (empacotador de módulos) para JavaScript, em outras palavras, ele junta os arquivos JS (e também outros formatos) da sua aplicação (seja arquivos seus ou dependências externas) em um arquivo só (ou mais de um), de forma otimizada. Os arquivos são unificados na ordem certa, sem duplicação e podem ser minificados para reduzir o tamanho.&lt;/p&gt;

&lt;p&gt;Um ponto forte do &lt;strong&gt;webpack&lt;/strong&gt; que ele é altamente configurável e extensível através de plugins. Isso permite fazer algumas coisas interessantes como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Utilizar &lt;strong&gt;outros sabores de JS&lt;/strong&gt;, como ES6+, TypeScript, JSX e fazer a transpilação (conversão para ES5) automaticamente no processo de empacotamento.&lt;/li&gt;
&lt;li&gt;Tratar e &lt;strong&gt;empacotar outros tipos de arquivos&lt;/strong&gt;, como CSS (e variações como SASS, LESS, Stylus), SVG, imagens, arquivos de templates (Pug, Handlebars).&lt;/li&gt;
&lt;li&gt;E muito mais, como veremos mais pra frente…&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Grafo de dependências
&lt;/h2&gt;

&lt;p&gt;Como o &lt;strong&gt;webpack&lt;/strong&gt; sabe quais arquivos incluir e em qual ordem? Ele monta um &lt;strong&gt;grafo de dependências&lt;/strong&gt;, que é uma estrutura mais ou menos assim:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JgcU6HSn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/10/webpack-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JgcU6HSn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/10/webpack-2.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Partindo de um arquivo inicial (entrada), ele verifica quais outros arquivos são importados por este, e os adiciona ao grafo. Para cada um desses ele também verifica quais eles importam, assim sucessivamente até que o grafo contenha todos os arquivos (módulos) necessários para a aplicação.&lt;/p&gt;

&lt;h2&gt;
  
  
  Módulos
&lt;/h2&gt;

&lt;p&gt;Para indicar que um arquivo JS depende de outro, ele precisa importá-lo. Ex.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;utils&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;./utils&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;No exemplo acima ele importa uma dependência externa (&lt;strong&gt;React&lt;/strong&gt;) e uma interna (o caminho começa com &lt;code&gt;./&lt;/code&gt;). Note também que não é necessário informar a extensão do arquivo se for JS.&lt;/p&gt;

&lt;p&gt;O arquivo que vai ser importado, em contrapartida, precisa indicar o que ele exporta. Ex.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;utils&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="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;utils&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Cada arquivo desses, que exporta algum dado ou funcionalidade, é chamado de &lt;strong&gt;módulo&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Dividir sua aplicação em módulos é uma boa prática, pelos seguintes benefícios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Manutenibilidade&lt;/strong&gt;: as funcionalidades ficam menos acopladas, é mais fácil alterar uma parte do código sem afetar o sistema inteiro.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Isolamento&lt;/strong&gt;: variáveis e funções declaradas dentro de um módulo são acessíveis apenas dentro dele (exceto aquilo que o módulo explicitamente exporta), evitando conflitos de variáveis e acesso desnecessário de uma parte do código a outra não relacionada.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reusabilidade&lt;/strong&gt;: um módulo com uma funcionalidade bem definida, é como uma peça de lego, pode ser reutilizada em outras partes do mesmo sistema, ou em outros sistemas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testabilidade&lt;/strong&gt;: com o código menos acoplado, fica mais fácil escrever testes unitários para validar cada funcionalidade.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A forma de fazer &lt;em&gt;import/export&lt;/em&gt; mostrada acima usa o padrão &lt;strong&gt;ES Modules&lt;/strong&gt;, que é o adotado a partir do ES6 nos navegadores. O Node.js atualmente usa o padrão &lt;strong&gt;CommonJS&lt;/strong&gt;, que muda um pouco a sintaxe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;utils&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Ambas as sintaxes são suportadas pelo webpack, mas aqui vamos usar &lt;strong&gt;ES Modules&lt;/strong&gt;, que é o padrão no navegador, e está caminhando para se tornar o padrão no Node.js (veja referência [8]).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Leitura importante&lt;/strong&gt;&lt;br&gt;
Recomendo se familiarizar com a sintaxe do &lt;strong&gt;ES Modules&lt;/strong&gt;, e as diferentes formas de import/export. Veja referências [5], [6] e [7] ao final do artigo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Os 4 conceitos fundamentais do webpack
&lt;/h2&gt;

&lt;p&gt;Antes de começar a colocar a mão na massa é importante compreender os &lt;strong&gt;4 *core concepts&lt;/strong&gt;* do webpack: &lt;strong&gt;entry&lt;/strong&gt;, &lt;strong&gt;output&lt;/strong&gt;, &lt;strong&gt;loaders&lt;/strong&gt; e &lt;strong&gt;plugins&lt;/strong&gt;. Tendo estes conceitos em mente fica mais fácil entender como o webpack trabalha.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rUxCl7iV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/10/webpack-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rUxCl7iV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/10/webpack-3.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nesta primeira parte vamos ver apenas os dois primeiros, que já serão suficientes para os primeiros exemplos. Veremos os outros quando forem necessários.&lt;/p&gt;

&lt;h3&gt;
  
  
  Entry (entrada)
&lt;/h3&gt;

&lt;p&gt;Lembra que eu falei lá em cima sobre o &lt;strong&gt;grafo de dependências&lt;/strong&gt;, e que para montá-lo o webpack parte de um &lt;strong&gt;arquivo inicial&lt;/strong&gt; e vai seguindo os &lt;em&gt;imports&lt;/em&gt;? Pois é, este arquivo inicial é o &lt;em&gt;entry point&lt;/em&gt; (ponto de entrada) da aplicação.&lt;/p&gt;

&lt;p&gt;Veremos que toda configuração de webpack possui pelo menos um &lt;em&gt;entry point&lt;/em&gt;. Pode ter mais de um (nesse caso serão gerados mais de um grafo de dependências), mas vamos ver esses casos mais avançados em outro momento.&lt;/p&gt;

&lt;h3&gt;
  
  
  Output (saída)
&lt;/h3&gt;

&lt;p&gt;Uma vez montado o grafo de dependências, o webpack precisa saber onde ele vai salvar o arquivo unificado, ou vários arquivos, dependendo da configuração.&lt;/p&gt;




&lt;h2&gt;
  
  
  Exemplo 1: Minificação de JS
&lt;/h2&gt;

&lt;p&gt;Vamos ver na prática o exemplo mais básico de um setup de webpack, com apenas uma entrada e uma saída. Vamos pegar uma aplicação divida em arquivos JS (módulos) e gerar um arquivo único.&lt;/p&gt;

&lt;p&gt;Este exemplo completo pode ser encontrado aqui: &lt;a href="https://github.com/doug2k1/webpack-scenarios/tree/master/1-basic"&gt;https://github.com/doug2k1/webpack-scenarios/tree/master/1-basic&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pré-requisitos
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Possuir &lt;a href="https://nodejs.org"&gt;Node.js&lt;/a&gt; instalado (de preferência uma versão recente)&lt;/li&gt;
&lt;li&gt;Conhecimento básico de terminal/linha de comando (saber navegar entre pastas e executar comandos simples)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Instalação
&lt;/h3&gt;

&lt;p&gt;Inicializar o arquivo &lt;em&gt;package.json&lt;/em&gt; para gerenciar dependências, caso sua aplicação ainda não possua. Rode no terminal, na raiz da aplicação:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;Instalar o webpack e o webpack-cli (que é o utilitário de linha de comando do webpack):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -D webpack webpack-cli
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Usamos &lt;code&gt;-D&lt;/code&gt; para salvar o webpack nas dependências de desenvolvimento (&lt;em&gt;devDependencies&lt;/em&gt;), já que ele só vai ser usado durante o desenvolvimento. Serão criadas as entradas abaixo no &lt;em&gt;package.json&lt;/em&gt; (a versão pode ser diferente, dependendo de qual versão é a mais recente quando você executar o comando):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"devDependencies"&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;"webpack"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^4.20.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"webpack-cli"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^3.1.2"&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;A estrutura de pastas vai ficar assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|-- node_modules  
|-- package.json  
|-- package-lock.json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Explicando: &lt;em&gt;node_modules&lt;/em&gt; é a pasta que guarda todos os arquivos baixados das dependências instaladas, &lt;em&gt;package.json&lt;/em&gt; é onde listamos as dependências e versões (entre outras informações da aplicação) e &lt;em&gt;package-lock.json&lt;/em&gt; é um arquivo que “trava” as versões das dependências. Quando outros desenvolvedores executarem &lt;code&gt;npm i&lt;/code&gt; para baixar as dependências, este arquivo garante que serão instaladas as mesmas versões para todo mundo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Zero Config
&lt;/h3&gt;

&lt;p&gt;Vou mostrar daqui a pouco como configurar o webpack usando um arquivo de configuração, mas para este exemplo simples você nem vai precisar deste arquivo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Arquivos da aplicação
&lt;/h3&gt;

&lt;p&gt;Por enquanto o projeto ainda não tem nenhum arquivo da aplicação em si. Uma prática comum é colocar o código-fonte da aplicação em uma pasta &lt;code&gt;src&lt;/code&gt;. Primeiro vamos criar um &lt;code&gt;index.js&lt;/code&gt; nesta pasta como nosso ponto de entrada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|-- src  
  |-- index.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Com o conteúdo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;cow&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;./cow&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;  

&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#box&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;say&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Webpack is great!&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;Este arquivo importa outro arquivo que está na mesma pasta, o &lt;em&gt;cow.js&lt;/em&gt; (&lt;code&gt;./&lt;/code&gt; significa “mesma pasta do arquivo atual”). Vamos agora criar este outro arquivo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|-- src  
  |-- index.js  
  |-- cow.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Com o conteúdo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;cowsay&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;cowsay-browser&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="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;say&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&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;cowsay&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;say&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;str&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;Veja que este arquivo já importa uma dependência externa (nome da dependência, sem &lt;code&gt;./&lt;/code&gt;). Precisamos usar o NPM para instalá-la:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -S cowsay-browser
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Aqui usamos &lt;code&gt;-S&lt;/code&gt; para salvar a dependência no &lt;em&gt;package.json&lt;/em&gt; como dependência normal, isto é, que será usada pela aplicação final. Vai ser adicionada esta entrada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"dependencies"&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;"cowsay-browser"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^1.1.8"&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;
  
  
  Arquivo HTML
&lt;/h3&gt;

&lt;p&gt;Para ver o resultado no navegador, vamos precisar de um arquivo HTML. Vamos criar então um &lt;code&gt;index.html&lt;/code&gt; na raiz da aplicação, com este conteúdo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!doctype html&amp;gt;  
&amp;lt;html&amp;gt;  
&amp;lt;head&amp;gt;  
  &amp;lt;title&amp;gt;Webpack&amp;lt;/title&amp;gt;  
&amp;lt;/head&amp;gt;  
&amp;lt;body&amp;gt;  
  &amp;lt;pre id="box"&amp;gt;  
  &amp;lt;script src="dist/main.js"&amp;gt;&amp;lt;/script&amp;gt;  
&amp;lt;/body&amp;gt;  
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Veja que carrega um arquivo &lt;code&gt;dist/main.js&lt;/code&gt; que ainda não temos. Este é o arquivo que o webpack vai gerar a partir de nossos fontes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configurando o webpack
&lt;/h3&gt;

&lt;p&gt;Por default, o webpack considera como ponto de entrada (&lt;strong&gt;&lt;em&gt;entry point&lt;/em&gt;&lt;/strong&gt;) o arquivo &lt;code&gt;src/index.js&lt;/code&gt; e como arquivo de saída (&lt;strong&gt;&lt;em&gt;output&lt;/em&gt;&lt;/strong&gt;) &lt;code&gt;dist/main.js&lt;/code&gt;. Por isto este primeiro exemplo não precisa de um arquivo de configuração.&lt;/p&gt;

&lt;p&gt;Mas, se quiséssemos alterar o &lt;strong&gt;&lt;em&gt;entry point&lt;/em&gt;&lt;/strong&gt; ou o &lt;strong&gt;&lt;em&gt;output&lt;/em&gt;&lt;/strong&gt;, poderíamos criar um arquivo &lt;code&gt;webpack.config.js&lt;/code&gt; na raiz da aplicação com o conteúdo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;path&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;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/index.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  
    &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;main.js&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;Veja que este arquivo é um módulo, que exporta um objeto. Aqui devemos usar o padrão &lt;strong&gt;CommonJS&lt;/strong&gt;, pois este arquivo vai executar no Node.js, quando o webpack for acionado.&lt;/p&gt;

&lt;p&gt;O primeiro item, &lt;strong&gt;entry&lt;/strong&gt;, é o nosso ponto de entrada.&lt;/p&gt;

&lt;p&gt;O segundo, &lt;strong&gt;output&lt;/strong&gt;, é onde o webpack vai salvar o &lt;em&gt;bundle&lt;/em&gt; gerado. Esta configuração pede o caminho da pasta (&lt;strong&gt;path&lt;/strong&gt;) e o nome do arquivo (&lt;strong&gt;filename&lt;/strong&gt;) separados. O caminho da pasta deve ser absoluto, por isso usamos a função &lt;a href="https://nodejs.org/api/path.html#path_path_resolve_paths"&gt;&lt;em&gt;path.resolve&lt;/em&gt;&lt;/a&gt; do Node para gerar um caminho absoluto a partir de um relativo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gerando o bundle (Fazendo a magia acontecer)
&lt;/h3&gt;

&lt;p&gt;Agora que o circo está montado, vamos gerar esse tal &lt;em&gt;main.js&lt;/em&gt;! Para isso, vamos adicionar uma entrada no nosso &lt;em&gt;package.json&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webpack"&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;Com isso, basta executar no terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run build
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Este comando irá executar o webpack (através do webpack-cli), que vai percorrer o &lt;strong&gt;grafo de dependências&lt;/strong&gt;, partindo do &lt;strong&gt;&lt;em&gt;entry point&lt;/em&gt;&lt;/strong&gt;, e gerar o &lt;em&gt;main.js&lt;/em&gt;, que contém todo o código da aplicação e das dependências.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BiEoM4cp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/10/webpack-5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BiEoM4cp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/10/webpack-5.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Você pode abrir o &lt;em&gt;index.html&lt;/em&gt; no navegador e ver o resultado.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--42RiAo-t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/10/webpack-4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--42RiAo-t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/10/webpack-4.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Modos: desenvolvimento e produção
&lt;/h3&gt;

&lt;p&gt;Se você olhar o arquivo main.js gerado vai ver que ele está minificado (sem identação e quebras de linhas, com os nomes de variáveis alterados e com tamanho bem menor que os arquivos originais). Isso acontece porque o webpack, por padrão, roda em modo &lt;strong&gt;produção&lt;/strong&gt; (&lt;strong&gt;&lt;em&gt;production&lt;/em&gt;&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;O modo &lt;strong&gt;&lt;em&gt;production&lt;/em&gt;&lt;/strong&gt; faz duas coisas por baixo dos panos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ativa o plugin &lt;a href="https://webpack.js.org/plugins/uglifyjs-webpack-plugin/"&gt;&lt;strong&gt;UglifyJS&lt;/strong&gt;&lt;/a&gt; para minificar o bundle. O UglifyJS faz uma minificação agressiva. Além de remover espaços, quebras de linha e comentários, ele renomeia variáveis e faz transformações no código para deixar o mais curto possível.&lt;/li&gt;
&lt;li&gt;Seta a variável &lt;code&gt;process.env.NODE_ENV="production"&lt;/code&gt;. Algumas bibliotecas olham esta variável, e se estiver com o valor “production” ativam algumas otimizações para produção.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O outro modo, &lt;strong&gt;desenvolvimento&lt;/strong&gt; (&lt;strong&gt;&lt;em&gt;development&lt;/em&gt;&lt;/strong&gt;), não minifica o código, mas ele roda mais rápido. Ideal (como o nome diz) para usar enquanto ainda está desenvolvendo o código.&lt;/p&gt;

&lt;p&gt;Para escolher o modo, basta passar a opção &lt;code&gt;--mode&lt;/code&gt; para o webpack-cli:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;webpack --mode development
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Opção watch
&lt;/h3&gt;

&lt;p&gt;Legal, mas toda vez que alterar um JS vou precisar rodar este comando manualmente?&lt;/p&gt;

&lt;p&gt;Não, jovem! Para isso tem a opção &lt;em&gt;watch&lt;/em&gt;, onde o webpack vai ficar monitorando os arquivos e a cada alteração ele vai reconstruir o arquivo final.&lt;/p&gt;

&lt;p&gt;Para isso basta passar a flag &lt;code&gt;-w&lt;/code&gt; para o cli:&lt;br&gt;
&lt;/p&gt;

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



&lt;p&gt;Com isso, para deixar o &lt;em&gt;workflow&lt;/em&gt; mais versátil você pode definir dois scripts no &lt;em&gt;package.json&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"build:watch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webpack -w --mode development"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"build:prod"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webpack --mode production"&lt;/span&gt;&lt;span class="w"&gt;  
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Assim, durante o desenvolvimento você usa &lt;code&gt;npm run build:watch&lt;/code&gt; para rodar em modo &lt;strong&gt;&lt;em&gt;development&lt;/em&gt;&lt;/strong&gt; com a opção &lt;em&gt;watch&lt;/em&gt;, e para mandar o código para produção você usa &lt;code&gt;npm run build:prod&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  O que vem pela frente
&lt;/h2&gt;

&lt;p&gt;Nos próximos artigos da série vamos falar de &lt;strong&gt;loaders&lt;/strong&gt;, para tratar outros formatos de arquivos, &lt;strong&gt;plugins&lt;/strong&gt;, para realizar diferentes tarefas e apresentar cenários mais avançados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feedbacks?
&lt;/h2&gt;

&lt;p&gt;Qualquer crítica ou sugestão, comente ou entre em contato.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[1] &lt;a href="https://webpack.js.org/"&gt;https://webpack.js.org/&lt;/a&gt; — Site oficial do webpack (inglês). Toda a documentação, com excelentes guias. Sua melhor referência, se não tiver problemas com inglês.&lt;/li&gt;
&lt;li&gt;[2] &lt;a href="https://www.udemy.com/webpack-2-the-complete-developers-guide/learn/v4/overview"&gt;https://www.udemy.com/webpack-2-the-complete-developers-guide/learn/v4/overview&lt;/a&gt; — Curso de webpack (inglês) na Udemy, com o excelente instrutor Stephen Grider. Geralmente rola promoção e este curso sai por R$20 ou R$30.&lt;/li&gt;
&lt;li&gt;[3] &lt;a href="https://coderweb.com.br/webpack-e-complexo-mas-so-um-pouquinho/"&gt;https://coderweb.com.br/webpack-e-complexo-mas-so-um-pouquinho/&lt;/a&gt; — Artigo do Coder Web sobre webpack (offline).&lt;/li&gt;
&lt;li&gt;[4] &lt;a href="https://willianjusten.com.br/configurando-o-webpack-para-rodar-react-e-es6/"&gt;https://willianjusten.com.br/configurando-o-webpack-para-rodar-react-e-es6/&lt;/a&gt; — Artigo do Willian Justen sobre webpack com React e ES6.&lt;/li&gt;
&lt;li&gt;[5] &lt;a href="http://exploringjs.com/es6/ch_modules.html"&gt;http://exploringjs.com/es6/ch_modules.html&lt;/a&gt; — Capítulo sobre ES Modules do livro &lt;em&gt;Exploring ES6&lt;/em&gt; (inglês)&lt;/li&gt;
&lt;li&gt;[6] &lt;a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Statements/import"&gt;https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Statements/import&lt;/a&gt; — Referência na MDN sobre import.&lt;/li&gt;
&lt;li&gt;[7] &lt;a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Statements/export"&gt;https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Statements/export&lt;/a&gt; — Referência na MDN sobre export.&lt;/li&gt;
&lt;li&gt;[8] &lt;a href="https://blogs.windows.com/msedgedev/2017/08/10/es-modules-node-today/"&gt;https://blogs.windows.com/msedgedev/2017/08/10/es-modules-node-today/&lt;/a&gt; — Post sobre o uso de ES Modules no Node.js (inglês)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webpack</category>
    </item>
    <item>
      <title>5 Ferramentas de Produtividade Essenciais no Desenvolvimento Web</title>
      <dc:creator>Douglas Matoso</dc:creator>
      <pubDate>Thu, 02 Apr 2020 02:07:08 +0000</pubDate>
      <link>https://dev.to/doug2k1/5-ferramentas-de-produtividade-essenciais-no-desenvolvimento-web-1ec</link>
      <guid>https://dev.to/doug2k1/5-ferramentas-de-produtividade-essenciais-no-desenvolvimento-web-1ec</guid>
      <description>&lt;p&gt;Neste post vou mostrar 5 ferramentas essenciais para aumentar sua produtividade no desenvolvimento web e programação em geral.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. &lt;a href="https://emmet.io/"&gt;Emmet&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--87w71qjq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2020/04/emmet-banner-1024x384.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--87w71qjq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2020/04/emmet-banner-1024x384.png" alt="Logo do Emmet"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O &lt;strong&gt;&lt;a href="https://emmet.io/"&gt;Emmet&lt;/a&gt;&lt;/strong&gt; acelera a escrita de &lt;strong&gt;HTML&lt;/strong&gt; e &lt;strong&gt;CSS&lt;/strong&gt; (também funciona com outros formatos como &lt;strong&gt;JSX&lt;/strong&gt; e &lt;strong&gt;SASS&lt;/strong&gt; ) através de abreviações no editor.&lt;/p&gt;

&lt;h3&gt;
  
  
  HTML
&lt;/h3&gt;

&lt;p&gt;No &lt;strong&gt;HTML&lt;/strong&gt; , por exemplo, se você digita o nome de uma tag e aperta Tab ou Enter, ele completa a tag, com abertura fechamento e atributos. Inclusive colocando o cursor nos pontos de edição.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;p → &amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;
a → &amp;lt;a href=""&amp;gt;&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Você também pode usar seletores CSS para criar blocos maiores.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#conteudo&amp;gt;ul.links&amp;gt;li*3

↓

&amp;lt;div id="conteudo"&amp;gt;
  &amp;lt;ul class="links"&amp;gt;
    &amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;
    &amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;
    &amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;
  &amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Outro exemplo, com pseudo seletores:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;form&amp;gt;input:text+input:submit

↓

&amp;lt;form action=""&amp;gt;
  &amp;lt;input type="text" name="" id=""&amp;gt;
  &amp;lt;input type="submit" value=""&amp;gt;
&amp;lt;/form&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;E o mais legal é este: para criar toda a estrutura inicial de um documento HTML, basta usar &lt;code&gt;!&lt;/code&gt;. Veja:&lt;/p&gt;



&lt;h3&gt;
  
  
  CSS
&lt;/h3&gt;

&lt;p&gt;No &lt;strong&gt;CSS&lt;/strong&gt; também ele agiliza um monte! Você pode escrever propriedade e valores em uma tacada só. Veja:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.seletor {
  /* básico */
  df → display: flex;
  dib → display: inline-block;
  ffa → font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
  bt → border-top: 1px solid #000;

  /* com valores */
  m10 → margin: 10px;
  bt2e → border-top: 2em;
  p2px4px → padding: 2px 4px;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;No início demora até ir decorando as abreviações, mas como o tempo você vai ficando cada vez mais produtivo e economiza alguns milhares de toques no teclado no seu dia-a-dia.&lt;/p&gt;

&lt;p&gt;🔥 Para facilitar a sua vida, aqui tem um cheat sheet oficial com todas as abreviações: &lt;a href="https://docs.emmet.io/cheat-sheet/"&gt;https://docs.emmet.io/cheat-sheet/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vale lembrar que o &lt;strong&gt;Emmet&lt;/strong&gt; possui plugins para quase todos os editores.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. &lt;a href="https://prettier.io/"&gt;Prettier&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FE_b6K7X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2020/04/Screen-Shot-2020-04-01-at-15.07.48-1024x397.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FE_b6K7X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2020/04/Screen-Shot-2020-04-01-at-15.07.48-1024x397.png" alt="Logo do Prettier"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lembra quando a gente perdia tempo formatando o código na mão pra ficar legível? Alinha indentação, adiciona umas quebras de linha, ajusta o espaçamento, troca o tipo de aspas pra ficar consistente…&lt;/p&gt;

&lt;p&gt;Aí, depois de todo esse esforço, você fazia um pull e vinha o código do coleguinha todo mal formatado! 🤬&lt;/p&gt;

&lt;p&gt;Todo esse sofrimento pode acabar, bastando usar um formatador automático de código, como o &lt;strong&gt;&lt;a href="https://prettier.io/"&gt;Prettier&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Ele se integra ao seu editor e formata seu código assim que você salva. Simples assim. Pode escrever tudo embolado, do jeito que sair da sua cabeça. Salvou. Tá formatado.&lt;/p&gt;



&lt;p&gt;Ele tem suporte oficial para várias linguagens como &lt;strong&gt;HTML&lt;/strong&gt; , &lt;strong&gt;CSS&lt;/strong&gt; , &lt;strong&gt;JS&lt;/strong&gt; (e derivadas como &lt;strong&gt;JSX&lt;/strong&gt; , &lt;strong&gt;SASS&lt;/strong&gt; e &lt;strong&gt;TypeScript&lt;/strong&gt; ), e através de plugins suporta também &lt;strong&gt;Java&lt;/strong&gt; , &lt;strong&gt;PHP&lt;/strong&gt; , &lt;strong&gt;SQL&lt;/strong&gt; , &lt;strong&gt;Ruby&lt;/strong&gt; , &lt;strong&gt;Swift&lt;/strong&gt; , entre outras.&lt;/p&gt;

&lt;p&gt;Você pode customizar as regras de formatação, se quiser, ou usar o padrão dele com &lt;em&gt;zero config&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Além de configurar o editor para formatar no save, é interessante também adicionar um &lt;em&gt;&lt;a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks"&gt;git hook&lt;/a&gt;&lt;/em&gt; para formatar no &lt;em&gt;commit&lt;/em&gt;. Assim garante que nenhum código 💩(mal formatado) passe. Aumenta a produtividade e reduz desavenças. Olha aí, que beleza!&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Live reload
&lt;/h2&gt;

&lt;p&gt;Aqui não é uma ferramenta específica, mas uma técnica de desenvolver uma página web tendo feedback instantâneo das alterações que você faz no código.&lt;/p&gt;

&lt;p&gt;Se você usa &lt;strong&gt;&lt;a href="https://webpack.js.org/"&gt;webpack&lt;/a&gt;&lt;/strong&gt;, você pode ativar o &lt;em&gt;live reload&lt;/em&gt; com o &lt;strong&gt;webpack-dev-server&lt;/strong&gt;. Inclusive tem um artigo aqui no blog onde mostro como usar: &lt;a href="https://www.webdevdrops.com/webpack-sem-medo-parte-3-plugins-e-dev-server-86b6e003657c/"&gt;&lt;strong&gt;Webpack sem Medo — Parte 3: Plugins e Dev Server&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Outra alternativa fácil, sem &lt;strong&gt;webpack&lt;/strong&gt; , é usar o &lt;strong&gt;&lt;a href="https://www.npmjs.com/package/live-server"&gt;live-server&lt;/a&gt;&lt;/strong&gt;. Você só precisa ter o &lt;strong&gt;&lt;a href="https://nodejs.org/"&gt;Node.js&lt;/a&gt;&lt;/strong&gt; com &lt;strong&gt;NPM&lt;/strong&gt; instalado e rodar este comando no terminal, na pasta onde está seu arquivo &lt;strong&gt;HTML&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx live-server
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Ele vai subir um servidor local e abrir sua página com o &lt;em&gt;live reload&lt;/em&gt; ativado. A partir daí, cada alteração nos arquivos é refletida instantaneamente na página aberta.&lt;/p&gt;

&lt;p&gt;E se você tem dois monitores, ou tem espaço suficiente para abrir o editor e o navegador lado a lado, a coisa flui ainda melhor.&lt;/p&gt;



&lt;h2&gt;
  
  
  4. &lt;strong&gt;&lt;a href="https://devdocs.io/"&gt;DevDocs&lt;/a&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Quando estamos codando, gastamos boa parte do tempo consultando documentações, não é mesmo? Então o ideal é que este processo seja o mais fluído possível. Uma ferramenta que ajuda muito aqui é o &lt;strong&gt;&lt;a href="https://devdocs.io/"&gt;DevDocs&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Ele possui uma busca rápida, que busca ao mesmo tempo em várias documentações. Você pode habilitar ou desabilitar documentações específicas e até habilitar a busca offline!&lt;/p&gt;

&lt;p&gt;Você pode até buscar direto na barra de endereço do &lt;strong&gt;Chrome&lt;/strong&gt;. Basta começar a digitar o endereço do site, e quando o &lt;strong&gt;Chrome&lt;/strong&gt; sugerir, aperte Tab e digite seu termo de busca.&lt;/p&gt;



&lt;h3&gt;
  
  
  Mac e Alfred
&lt;/h3&gt;

&lt;p&gt;Com o app &lt;strong&gt;&lt;a href="https://www.alfredapp.com/"&gt;Alfred&lt;/a&gt;&lt;/strong&gt;, para &lt;strong&gt;Mac&lt;/strong&gt; , dá pra buscar no &lt;strong&gt;DevDocs&lt;/strong&gt; através de um atalho global, sem precisar nem abrir o browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--d309bcXc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2020/04/alfred-devdocs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d309bcXc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2020/04/alfred-devdocs.png" alt="Alfred com DevDocs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Você vai precisar da versão paga do app e deste addon: &lt;a href="https://github.com/yannickglt/alfred-devdocs"&gt;https://github.com/yannickglt/alfred-devdocs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Certamente deve ter alguma alternativa parecida no &lt;strong&gt;Windows&lt;/strong&gt; e &lt;strong&gt;Linux&lt;/strong&gt;. Se alguém souber, comenta aí!&lt;/p&gt;

&lt;h2&gt;
  
  
  5. &lt;a href="https://code.visualstudio.com/"&gt;VS Code&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Para fechar, vou deixar algumas dicas de produtividade para o ótimo editor de códigos &lt;strong&gt;&lt;a href="https://code.visualstudio.com/"&gt;VS Code&lt;/a&gt;&lt;/strong&gt;. Se você usa outro editor, provavelmente ele possui estas mesmas funcionalidades, talvez com atalhos diferentes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Edição múltipla
&lt;/h3&gt;

&lt;p&gt;Uma das funcionalidades mais úteis nos editores modernos é a possibilidade de ter mais de um cursor e poder editar mais de um ponto ao mesmo tempo.&lt;/p&gt;

&lt;p&gt;No &lt;strong&gt;VS Code&lt;/strong&gt; você pode adicionar mais cursores clicando em diferentes pontos enquanto segura Alt.&lt;/p&gt;

&lt;p&gt;Outra forma é selecionando uma parte do código e apertando &lt;strong&gt;Cmd+D&lt;/strong&gt; para selecionar a próxima ocorrência do mesmo texto. Cada vez que o atalho é pressionado ele procura pela próxima ocorrência e adiciona à seleção, mantendo um cursor em cada ocorrência. Depois você pode alterar todas de uma vez.&lt;/p&gt;



&lt;h3&gt;
  
  
  Go to file
&lt;/h3&gt;

&lt;p&gt;Outra funcionalidade que salva muito tempo, principalmente em projetos com muitos arquivos, é ir direto para um arquivo específico, sem precisar procurá-lo na estrutura de pastas.&lt;/p&gt;

&lt;p&gt;Se você sabe o nome, ou parte dele, é só usar o &lt;strong&gt;Go to File&lt;/strong&gt; (Cmd+P no Mac) e começar a digitar parte do nome. Ele faz uma &lt;a href="https://en.wikipedia.org/wiki/Approximate_string_matching"&gt;busca fuzzy&lt;/a&gt;, portanto, mesmo você não digitando exatamente o nome, ele traz os arquivos que mais se aproximam. Depois é só dar Enter para abrir o arquivo.&lt;/p&gt;



&lt;h3&gt;
  
  
  Find and replace
&lt;/h3&gt;

&lt;p&gt;Buscar e substituir um texto em um arquivo já é útil, agora buscar e substituir em todo o projeto é uma tremenda mão na roda!&lt;/p&gt;

&lt;p&gt;No &lt;strong&gt;VS Code&lt;/strong&gt; basta usar a busca na barra lateral (Cmd+Shift+F) para buscar em todo o projeto, e se você expandir a setinha na lateral ele abre o campo de substituição e até mostra uma prévia do que vai ser substituído, pra você ter certeza.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ltvxirjk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2020/04/vscode-search-replace-1024x555.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ltvxirjk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2020/04/vscode-search-replace-1024x555.png" alt="Busca e substituição no VS Code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Split editor
&lt;/h3&gt;

&lt;p&gt;Por fim, muito útil para editar arquivos relacionados, é a opção de dividir o editor para mostrar diferentes arquivos ao mesmo tempo. É legal, por exemplo, para fazer &lt;a href="https://www.devmedia.com.br/test-driven-development-tdd-simples-e-pratico/18533"&gt;TDD&lt;/a&gt; e ficar chaveando entre o arquivo de teste e o arquivo da funcionalidade em si.&lt;/p&gt;

&lt;p&gt;No &lt;strong&gt;VS Code&lt;/strong&gt; dá pra dividir na horizontal, vertical, de várias maneiras diferentes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SKSiiEpg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2020/04/vscode-split-editor-1024x674.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SKSiiEpg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2020/04/vscode-split-editor-1024x674.png" alt="Split editor no VS Code"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Estas foram algumas dicas que, pra mim, ajudam muito na produtividade. Algumas coisas são muito pessoais, mas a ideia é procurar sempre melhorar seu workflow.&lt;/p&gt;

&lt;p&gt;Tem outras dicas legais para melhorar a produtividade? Comenta aí!&lt;/p&gt;

&lt;p&gt;[]’s&lt;/p&gt;

&lt;p&gt;O post &lt;a href="https://www.webdevdrops.com/5-ferramentas-produtividade-desenvolvimento-web/"&gt;5 Ferramentas de Produtividade Essenciais no Desenvolvimento Web&lt;/a&gt; apareceu primeiro em &lt;a href="https://www.webdevdrops.com"&gt;Web Dev Drops&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>posts</category>
      <category>dicas</category>
      <category>produtividade</category>
    </item>
    <item>
      <title>Curso Pacote Full-Stack Danki Code é bom? Vale a pena?</title>
      <dc:creator>Douglas Matoso</dc:creator>
      <pubDate>Fri, 18 Oct 2019 01:34:42 +0000</pubDate>
      <link>https://dev.to/doug2k1/curso-pacote-full-stack-danki-code-e-bom-vale-a-pena-5gm1</link>
      <guid>https://dev.to/doug2k1/curso-pacote-full-stack-danki-code-e-bom-vale-a-pena-5gm1</guid>
      <description>&lt;p&gt;Muita gente está me perguntando se o curso &lt;a href="https://www.webdevdrops.com/pacote-full-stack?src=postdevto"&gt;Pacote Full-Stack&lt;/a&gt; &lt;strong&gt;Danki Code&lt;/strong&gt; é bom mesmo. Será que vale a pena?&lt;/p&gt;

&lt;p&gt;Veja minha análise completa neste post.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.webdevdrops.com/pacote-full-stack?src=postdevto"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yzNuC6xs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/10/pacote-full-stack-1024x615.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é o Pacote Full-Stack?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;O curso Pacote Full-Stack da Danki Code é, na verdade um pacote de cursos que engloba toda a formação de Desenvolvedor Web, incluindo backend, frontend e web design.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conteúdo
&lt;/h2&gt;

&lt;p&gt;O pacote, que vai desde o iniciante até o avançado, é composto pelos cursos:&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Front-End Completo&lt;/strong&gt; : vai desde os conceitos básicos, HTML, CSS, design responsivo, JavaScript e lógica de programação, frameworks JS, ES6, Sass, Less.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Desenvolvimento Web Completo&lt;/strong&gt; : este é focado no backend em PHP. Vai desde configuração do servidor, hospedagem, lógica de programação e algoritmos, banco de dados, SEO, analytics, MVC, segurança e muito mais.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Web Design Express&lt;/strong&gt; : focado em design, Photoshop, UI, UX.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;PHP Jedi&lt;/strong&gt; : aqui vem a parte mais avançada de PHP, incluíndo PHP 7+ e projetos mais desafiadores.&lt;/p&gt;

&lt;p&gt;✅ Além de outros &lt;strong&gt;bônus&lt;/strong&gt; para complementar o aprendizado.&lt;/p&gt;

&lt;p&gt;Você pode conferir mais detalhes das grades do cursos e dos bônus visitando o &lt;a href="https://www.webdevdrops.com/pacote-full-stack?src=postdevto"&gt;site oficial aqui&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Atualizações vitalícias
&lt;/h2&gt;

&lt;p&gt;Os cursos são  &lt;strong&gt;atualizados frequentemente&lt;/strong&gt;  para cobrir novas tecnologias. E o melhor de tudo é que você paga uma vez e tem  &lt;strong&gt;acesso vitalício&lt;/strong&gt; , incluindo todas as futuras atualizações.&lt;/p&gt;

&lt;h2&gt;
  
  
  Projetos desenvolvidos
&lt;/h2&gt;

&lt;p&gt;Um grande diferencial do pacote é que ele une bem teoria e prática. Durante os cursos você irá desenvolver  &lt;strong&gt;mais de 100 projetos práticos&lt;/strong&gt; , o que reforça o aprendizado e já constrói um respeitável portfólio de projetos para atrair clientes (caso queira ser um freelancer) e recrutadores (caso queira seguir carreira em empresas).&lt;/p&gt;

&lt;h2&gt;
  
  
  Garantia
&lt;/h2&gt;

&lt;p&gt;A Danki Code oferece uma garantia de  &lt;strong&gt;30 dias&lt;/strong&gt;. Se não gostar do curso, por qualquer motivo, eles devolvem 100% do valor pago.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preço
&lt;/h2&gt;

&lt;p&gt;Com todo esse conteúdo, bônus, atualizações, e o quanto ele vai transformar sua carreira de desenvolvedor web full-stack, o preço é irrisório. Atualmente sai a &lt;strong&gt;menos de 1 Real por dia!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;O primeiro projeto que você pegar como freelancer ou o próximo emprego que você conseguir com essas habilidades já paga o curso com folga!&lt;/p&gt;

&lt;p&gt;⚠️ &lt;strong&gt;Atenção!&lt;/strong&gt; O pessoal da &lt;strong&gt;Danki Code&lt;/strong&gt; está para aumentar o preço em breve devido a tantas atualizações! Recomendo ir lá no &lt;a href="https://www.webdevdrops.com/pacote-full-stack?src=postdevto"&gt;site oficial&lt;/a&gt; e garantir logo sua vaga com o preço atual.&lt;/p&gt;

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

&lt;p&gt;A  &lt;strong&gt;Danki Code&lt;/strong&gt;  é referência em cursos de TI, possui atualmente mais de 25.000 alunos matriculados e tem nota máxima nas plataformas de cursos online.&lt;/p&gt;

&lt;p&gt;Um curso  &lt;strong&gt;bem estruturado&lt;/strong&gt;  faz muita diferença na sua carreira. Muitos desenvolvedores ficam “correndo atrás do rabo”, buscando conteúdos gratuitos fragmentados e, muitas vezes, de qualidade duvidosa, e acabam estagnados e frustrados.&lt;/p&gt;

&lt;p&gt;O &lt;a href="https://www.webdevdrops.com/pacote-full-stack?src=postdevto"&gt;Pacote Full-Stack&lt;/a&gt; é um excelente investimento atualmente, tanto para quem quer começar quanto para o profissional que quer dar um upgrade na carreira de  &lt;strong&gt;desenvolvedor web&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;🔥 &lt;strong&gt;Atualização&lt;/strong&gt; :&lt;br&gt;&lt;br&gt;
A Danki Code liberou algumas  &lt;strong&gt;aulas grátis&lt;/strong&gt;  do  &lt;strong&gt;Pacote Full-Stack&lt;/strong&gt;!&lt;br&gt;&lt;br&gt;
Veja como acessar no post: &lt;a href="https://www.webdevdrops.com/aulas-gratis-curso-pacote-full-stack-danki-code/"&gt;Aulas Grátis do Curso Pacote Full-Stack da Danki Code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.webdevdrops.com/pacote-full-stack?src=postwdd"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yzNuC6xs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webdevdrops.com/wp-content/uploads/2019/10/pacote-full-stack-1024x615.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O post &lt;a href="https://www.webdevdrops.com/curso-pacote-full-stack-danki-code-bom-vale-pena/"&gt;Curso Pacote Full-Stack Danki Code é bom? Vale a pena?&lt;/a&gt; apareceu primeiro em &lt;a href="https://www.webdevdrops.com"&gt;Web Dev Drops&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>cursos</category>
      <category>fullstack</category>
    </item>
  </channel>
</rss>
