<?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: Mate Boer </title>
    <description>The latest articles on DEV Community by Mate Boer  (@bmz1).</description>
    <link>https://dev.to/bmz1</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%2F126432%2Fb2200781-8e18-4ac6-a6fd-f5df4b725f61.jpeg</url>
      <title>DEV Community: Mate Boer </title>
      <link>https://dev.to/bmz1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bmz1"/>
    <language>en</language>
    <item>
      <title>Generating PDF from HTML with Node.js and Puppeteer</title>
      <dc:creator>Mate Boer </dc:creator>
      <pubDate>Tue, 05 Feb 2019 17:26:04 +0000</pubDate>
      <link>https://dev.to/bmz1/generating-pdf-from-html-with-nodejs-and-puppeteer-5ln</link>
      <guid>https://dev.to/bmz1/generating-pdf-from-html-with-nodejs-and-puppeteer-5ln</guid>
      <description>&lt;p&gt;&lt;i&gt;Originally published at &lt;a href="https://blog.risingstack.com/pdf-from-html-node-js-puppeteer/"&gt;blog.risingstack.com&lt;/a&gt; on February 5, 2019.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In this article I’m going to show how you can generate a PDF document from a heavily styled React page using Node.js, Puppeteer, headless Chrome &amp;amp; Docker.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Background: A few months ago one of the clients of &lt;a href="https://risingstack.com/"&gt;RisingStack&lt;/a&gt; asked us to develop a feature where the user would be able to request a React page in PDF format. That page is basically a report/result for patients with data visualization, containing a lot of SVGs. Furthermore, there were some special requests to manipulate the layout and make some rearrangements of the HTML elements. So the PDF should have different styling and additions compared to the original React page. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;As the assignment was a bit more complex than what could have been solved with simple CSS rules, we first explored possible implementations. Essentially we found 3 main solutions. This blogpost will walk you through on these possibilities and the final implementations.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;A personal comment before we get started: it’s quite a hassle, so buckle up! &lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Table of Contents:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Client side or Backend side?&lt;/li&gt;
&lt;li&gt;Option 1: Making a Screenshot from the DOM&lt;/li&gt;
&lt;li&gt;Option 2: Use only a PDF library&lt;/li&gt;
&lt;li&gt;
Final option 3: Puppeteer, headless Chrome with Node.js

&lt;ul&gt;
&lt;li&gt;Style manipulation&lt;/li&gt;
&lt;li&gt;Send file to the client and save it&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Using Puppeteer with Docker&lt;/li&gt;
&lt;li&gt;Option 3 +1: CSS print rules&lt;/li&gt;
&lt;li&gt;
Summary


&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Client side or Server side?
&lt;/h2&gt;

&lt;p&gt;It is possible to generate a PDF file both on the client-side and on the server-side. However, it probably makes more sense to let the backend handle it, as you don’t want to use up all the resources the user’s browser can offer. &lt;br&gt;
Even so, I’ll still show solutions for both methods. &lt;/p&gt;




&lt;h2&gt;
  
  
  Option 1: Make a Screenshot from the DOM
&lt;/h2&gt;

&lt;p&gt;At first sight, this solution seemed to be the simplest, and it turned out to be true, but it has its own limitations. If you don’t have special needs, like selectable or searchable text in the PDF, it is a good and simple way to generate one.&lt;/p&gt;

&lt;p&gt;This method is plain and simple: create a screenshot from the page, and put it in a PDF file. Pretty straightforward. We used two packages for this approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://html2canvas.hertzen.com/"&gt;Html2canvas&lt;/a&gt;, to make a screenshot from the DOM&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/MrRio/jsPDF"&gt;jsPdf&lt;/a&gt;, a library to generate PDF&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s start coding.&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;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="nx"&gt;html2canvas&lt;/span&gt; &lt;span class="nx"&gt;jspdf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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;html2canvas&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;html2canvas&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;jsPdf&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;jspdf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;printPDF&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;domElement&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="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your-id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;html2canvas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;domElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;onclone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&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="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;print-button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;visibility&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hidden&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;canvas&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;img&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="nx"&gt;toDataURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pdf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;jsPdf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imgData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;JPEG&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your-filename.pdf&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;And that’s it! &lt;/p&gt;

&lt;p&gt;Make sure you take a look at the &lt;code&gt;html2canvas&lt;/code&gt; &lt;code&gt;onclone&lt;/code&gt; method. It can prove to be handy when you quickly need to take a snapshot and manipulate the DOM (e.g. hide the print button) before taking the picture. I can see quite a lot of use cases for this package. Unfortunately, ours wasn’t one, as we needed to handle the PDF creation on the backend side.&lt;/p&gt;





&lt;h2&gt;
  
  
  Option 2: Use only a PDF Library
&lt;/h2&gt;

&lt;p&gt;There are several libraries out there on NPM for this purpose, like jsPDF (mentioned above) or &lt;a href="https://www.npmjs.com/package/pdfkit"&gt;PDFKit&lt;/a&gt;. The problem with them that I would have to recreate the page structure again if I wanted to use these libraries. That definitely hurts maintainability, as I would have needed to apply all subsequent changes to both the PDF template and the React page. &lt;br&gt;
Take a look at the code below. You need to create the PDF document yourself by hand. Now you could traverse the DOM and figure out how to translate each element to PDF ones, but that is a tedious job. There must be an easier way.&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;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;PDFDocument&lt;/span&gt;
&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createWriteStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;output.pdf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fonts/PalatinoBold.ttf&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;fontSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Some text with an embedded font!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&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/to/image.png&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;fit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
   &lt;span class="na"&gt;align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;valign&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Here is some vector graphics...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This snippet is from the PDFKit docs. However, it can be useful if your target is a PDF file straight away and not the conversion of an already existing (and ever-changing) HTML page.&lt;/p&gt;





&lt;h2&gt;
  
  
  Final Option 3: Puppeteer, Headless Chrome with Node.js
&lt;/h2&gt;

&lt;p&gt;What is &lt;a href="https://github.com/GoogleChrome/puppeteer"&gt;Puppeteer&lt;/a&gt;? The documentation says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the DevTools Protocol. Puppeteer runs headless by default, but can be configured to run full (non-headless) Chrome or Chromium.&lt;br&gt;
It’s basically a browser which you can run from Node.js. If you read the docs, the first thing it says about Puppeteer is that you can use it to &lt;strong&gt;Generate screenshots and PDFs of pages&lt;/strong&gt;’. Excellent! That’s what we were looking for. &lt;br&gt;
Let’s install Puppeteer with &lt;code&gt;npmi i puppeteer&lt;/code&gt;, and implement our use case.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&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;puppeteer&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;puppeteer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;printPDF&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;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puppeteer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;headless&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;newPage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;goto&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://blog.risingstack.com&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;waitUntil&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;networkidle0&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;pdf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;close&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;pdf&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is a simple function that navigates to a URL and generates a PDF file of the site.First, we launch the browser (PDF generation only supported in headless mode), then we open a new page, set the viewport, and navigate to the provided URL. &lt;/p&gt;

&lt;p&gt;Setting the &lt;code&gt;waitUntil: ‘networkidle0’&lt;/code&gt; option means that Puppeteer considers navigation to be finished when there are no network connections for at least 500 ms. (Check &lt;a href="https://github.com/GoogleChrome/puppeteer/blob/v1.11.0/docs/api.md"&gt;API docs&lt;/a&gt; for further information.) &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After that, we save the PDF to a variable, we close the browser and return the PDF.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Note: The &lt;code&gt;page.pdf&lt;/code&gt;method receives an &lt;code&gt;options&lt;/code&gt; object, where you can save the file to disk with the ‘path’  option as well. If path is not provided, the PDF won’t be saved to the disk, you’ll get a buffer instead. Later on, I discuss how you can handle it.)&lt;/p&gt;

&lt;p&gt;In case you need to log in first to generate a PDF from a protected page, first you need to navigate to the login page, inspect the form elements for ID or name, fill them in, then submit the form:&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;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PDF_USER&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PDF_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#submit&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;Always store login credentials in environment variables, do not hardcode them!&lt;/p&gt;





&lt;h3&gt;
  
  
  Style Manipulation
&lt;/h3&gt;

&lt;p&gt;Puppeteer has a solution for this style manipulation too. You can insert style tags before generating the PDF, and Puppeteer will generate a file with the modified styles.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;await&lt;/span&gt; &lt;span class="nt"&gt;page&lt;/span&gt;&lt;span class="nc"&gt;.addStyleTag&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;'.nav { display: none} .navbar { border: 0px} #print-button {display: none}'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;







&lt;h3&gt;
  
  
  Send file to the client and save it
&lt;/h3&gt;

&lt;p&gt;Okay, now you have generated a PDF file on the backend. What to do now?&lt;br&gt;
As I mentioned above, if you don’t save the file to disk, you’ll get a buffer. You just need to send that buffer with the proper content type to the front-end.&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;printPDF&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;pdf&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/pdf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Length&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now you can simply send a request to the server, to get the generated PDF.&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;function&lt;/span&gt; &lt;span class="nx"&gt;getPDF&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;axios&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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;API_URL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/your-pdf-endpoint`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;responseType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;arraybuffer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Accept&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/pdf&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;Once you’ve sent the request, the buffer should start downloading. Now the last step is to convert the buffer into a PDF file.&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;savePDF&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;openModal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;Loading&lt;/span&gt;&lt;span class="err"&gt;…’&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// open modal&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;getPDF&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// API call&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="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;blob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Blob&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/pdf&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;link&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="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createObjectURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;download&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`your-file-name.pdf`&lt;/span&gt;
       &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
       &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;closeModal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// close modal&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="cm"&gt;/** error handling **/&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;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;onClick=&lt;/span&gt;&lt;span class="s"&gt;{this.savePDF}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Save as PDF&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That was it! If you click on the save button, the PDF will be saved by the browser.&lt;/p&gt;





&lt;h2&gt;
  
  
  Using Puppeteer with Docker
&lt;/h2&gt;

&lt;p&gt;I think this is the trickiest part of the implementation - so let me save you a couple of hours of Googling. &lt;br&gt;
The official documentation states that &lt;em&gt;“getting headless Chrome up and running in Docker can be tricky”&lt;/em&gt;. The official docs have a &lt;a href="https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md#running-puppeteer-in-docker"&gt;Troubleshooting&lt;/a&gt; section, where at the time of writing you can find all the necessary information on installing puppeteer with Docker.&lt;br&gt;
If you install Puppeteer on the Alpine image, make sure you scroll down a bit to &lt;a href="https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md#running-on-alpine"&gt;this part of the page&lt;/a&gt;. Otherwise, you might gloss over the fact that you cannot run the latest Puppeteer version and you also need to disable shm usage, using a flag:&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;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puppeteer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;headless&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--disable-dev-shm-usage&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;Otherwise, the Puppeteer sub process might run out of memory before it even gets started properly. More info about that on the troubleshooting link above.&lt;/p&gt;





&lt;h2&gt;
  
  
  Option 3 + 1: CSS Print Rules
&lt;/h2&gt;

&lt;p&gt;One might think that simply using CSS print rules is easy from a developers standpoint. No NPM modules, just pure CSS. But how do they fare when it comes to cross-browser compatibility? &lt;br&gt;
When choosing CSS print rules, you have to test the outcome in every browser to make sure it provides the same layout, and it’s not 100% that it does.&lt;br&gt;
For example, inserting a break after a given element cannot be considered an esoteric use case, yet you might be surprised that you need to use workarounds &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/break-after#Browser_compatibility"&gt;to get that working in Firefox&lt;/a&gt;. &lt;br&gt;
Unless you are a battle-hardened CSS magician with a lot of experience in creating printable pages, this can be time-consuming.&lt;br&gt;
Print rules are great if you can keep the print stylesheets simple. &lt;br&gt;
Let’s see an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;.print-button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;.content&lt;/span&gt; &lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;break-after&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;always&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;This CSS above hides the print button, and inserts a page break after every &lt;code&gt;div&lt;/code&gt; with the class &lt;code&gt;content.&lt;/code&gt; There is a &lt;a href="https://www.smashingmagazine.com/2018/05/print-stylesheets-in-2018/"&gt;great article&lt;/a&gt; that summarizes what you can do with print rules, and what are the difficulties with them including browser compatibility. &lt;br&gt;
Taking everything into account, CSS print rules are great and effective if you want to make a PDF from a not so complex page.&lt;/p&gt;





&lt;h2&gt;
  
  
  Summary: PDF from HTML with Node.js and Puppeteer
&lt;/h2&gt;

&lt;p&gt;So let’s quickly go through the options we covered here for generating PDF files from HTML pages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Screenshot from the DOM&lt;/strong&gt;: This can be useful when you need to create snapshots from a page (for example to create a thumbnail), but falls short when you have a lot of data to handle.

&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use only a PDF library&lt;/strong&gt;: If you need to create PDF files programmatically from scratch, this is a perfect solution. Otherwise, you need to maintain the HTML and PDF templates which is definitely a no-go.

&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Puppeteer&lt;/strong&gt;:  Despite being relatively difficult to get it working on Docker, it provided the best result for our use case, and it was also the easiest to write the code with.

&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSS print rules&lt;/strong&gt;: If your users are educated enough to know how to print to a file and your pages are relatively simple, it can be the most painless solution. As you saw in our case, it wasn’t.
Happy printing!

&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>node</category>
      <category>pdf</category>
      <category>javascript</category>
      <category>html</category>
    </item>
    <item>
      <title>Want to Learn JavaScript for Free? Start Here!</title>
      <dc:creator>Mate Boer </dc:creator>
      <pubDate>Mon, 07 Jan 2019 17:08:31 +0000</pubDate>
      <link>https://dev.to/bmz1/want-to-learn-javascript-for-free-start-here-be5</link>
      <guid>https://dev.to/bmz1/want-to-learn-javascript-for-free-start-here-be5</guid>
      <description>&lt;p&gt;This is the first post of a series called ‘Learn JavaScript for Free’ - in these chapters you will find excellent materials and a roadmap for learning JS from scratch. As the JavaScript community is one of the best out there, the series will entirely rely on free JavaScript resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why learn JavaScript Now?
&lt;/h2&gt;

&lt;p&gt;JavaScript is almost everywhere: in your browser, web apps, mobile apps, cloud services, even IoT devices. It’s easy to get started with it as all you need is a plain text editor and a browser. It is a beginner friendly language, with an awesome community around it.&lt;/p&gt;

&lt;p&gt;You can code both frontend and backend with JavaScript, which makes it extremely useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  It’s hard to figure out where to Start
&lt;/h2&gt;

&lt;p&gt;To become a JavaScript Engineer, you have to acquire various skills. For beginners, finding an optimal learning path is not apparent, especially with zero background.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7x1yCC1U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.risingstack.com/content/images/2018/10/javascript-frameworks.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7x1yCC1U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.risingstack.com/content/images/2018/10/javascript-frameworks.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The depth of the trade seems to be infinite, so the question ‘Where to start?’ raised by beginners seems legit. There are other questions like&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;‘What skills do I need to learn JavaScript?’, &lt;/li&gt;
&lt;li&gt;‘How to get a job?’, &lt;/li&gt;
&lt;li&gt;‘How to prepare for interviews?’.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this series, I’ll attempt to answer these questions. &lt;/p&gt;

&lt;p&gt;One thing to mention: this is not a specific JavaScript tutorial. You will not learn how to code from this post. Instead, it is an overview/roadmap of the path ahead of you to become a developer on your own.&lt;/p&gt;

&lt;h2&gt;
  
  
  About my JavaScript Path
&lt;/h2&gt;

&lt;p&gt;To give some context, my relationship with development started in my teenage years. I’ve learned HTML and CSS just for fun and curiosity. After that, I built websites with content management systems like Wordpress, and that was it. I didn’t take it seriously: it was a hobby and nothing more.&lt;/p&gt;

&lt;p&gt;After graduation, I went to law school, worked for law offices, but after 5-6 years, I realized this is not the kind of career I imagined for myself. In retrospect, it was a useful experience, but I didn’t want to do it anymore. I needed something more creative. So I started learning JavaScript.&lt;/p&gt;

&lt;p&gt;Taking part in a programming school wasn’t an option: the basics are freely available on the internet, and I didn’t want someone to charge me for the same thing I can find in tutorials. I knew it wouldn’t be easy though, but I can say it was fun for me.&lt;/p&gt;

&lt;p&gt;I practiced at least 6-7 hours a day.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cRTOANQn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.risingstack.com/content/images/2018/10/javascript-learn-free-no-idea.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cRTOANQn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.risingstack.com/content/images/2018/10/javascript-learn-free-no-idea.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I worked on hobby projects with React, but after 3 months, I started to feel the limitations of self-learning. There was nobody to tell me the best coding practices: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“How do I structure an app?” &lt;/li&gt;
&lt;li&gt;“Which packages should I use?” &lt;/li&gt;
&lt;li&gt;“What makes sense learning and what is merely some glorified sugar coating?” &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Maybe I could have figured it out somehow by myself, but I realized that I need to work with people who already have many years of experience, so I can soak up the knowledge from them. The best way to be around people like that was to get hired, so I started sending my CV to companies. Many of them. Even for positions I was sure I wouldn’t be hired. Why not? If you can get through and be called in for an interview you can already learn from the questions you cannot answer or the coding challenges you cannot complete. &lt;/p&gt;

&lt;p&gt;After several attempts, my efforts paid off: I got hired by RisingStack as a junior developer which allowed me to develop my skills a lot faster compared to the time I spent with self-learning. During my first month  - like every new recruit - I had to finish the internal &lt;a href="https://github.com/RisingStack/risingstack-bootcamp"&gt;bootcamp&lt;/a&gt;, which prepared me to work on client projects.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But this series is about what to do before you get hired, so you can get hired.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Acquiring the Engineering Mindset
&lt;/h2&gt;

&lt;p&gt;In this section, I’ll cover the skills necessary to start learning JavaScript.&lt;/p&gt;

&lt;p&gt;At least you should have a basic interest in web technologies, programming or IT itself. It will be cumbersome without that, and anyway, why start learning something that you are not interested in? Learning how to write code just for the money isn’t a good idea either. &lt;/p&gt;

&lt;p&gt;If you are reading this post, I assume you have the curiosity I’m talking about. &lt;/p&gt;

&lt;p&gt;Basic interest is enough for learning the fundamentals and maybe even for getting hired, but if you want to make progress especially from an entry level, it requires extra dedication and effort. This is maybe the most crucial point about it.  &lt;/p&gt;

&lt;p&gt;Try to set reachable goals for yourself. Learn something new everyday. &lt;/p&gt;

&lt;p&gt;Beyond the efforts, the required mindset to be a successful developer is also worth mentioning.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MJBdEUOA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.risingstack.com/content/images/2018/10/the-javascript-developer-mindset.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MJBdEUOA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.risingstack.com/content/images/2018/10/the-javascript-developer-mindset.png" alt=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;i&gt;Source: &lt;a href="https://www.7pace.com/blog/become-a-better-programmer-skills-development"&gt;&lt;/a&gt;&lt;a href="https://www.7pace.com/blog/become-a-better-programmer-skills-development"&gt;https://www.7pace.com/blog/become-a-better-programmer-skills-development&lt;/a&gt;&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;These are skills you will have to pick up as the time passes.&lt;/p&gt;

&lt;p&gt;One of the other most important must-have skill is to know how to Google, a.k.a find solutions to a problem. I’ve seen a lot of people struggling to search for an obstacle that is so obvious to solve with a bit of inspection. There is an answer for the 99% of the problems that a beginner is going to face. &lt;/p&gt;

&lt;p&gt;You just have to find the solution and apply it. It’s that simple (at the beginning).  If you didn’t find the answer, probably you didn’t search the right way.  So start getting to know how to Google correctly, and make a ‘friendship’ with StackOverflow and &lt;a href="https://developer.mozilla.org/en-US/"&gt;MDN&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Do not fear making mistakes. It’s part of the learning process.  &lt;/p&gt;

&lt;p&gt;With respect to the subject above mentioned, let’s move on to the next section. &lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript Fundamentals
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Getting started with the web
&lt;/h3&gt;

&lt;p&gt;Before you start to learn JavaScript, it is highly advised to get familiar with &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web"&gt;HTML, CSS and how the web&lt;/a&gt; works. &lt;/p&gt;

&lt;p&gt;HTML and CSS can be picked up really fast. Build a simple static website, experiment a little bit. Once you are comfortable with the concepts of these technologies, you can move on..&lt;/p&gt;

&lt;h3&gt;
  
  
  Intro to Programming Basics
&lt;/h3&gt;

&lt;p&gt;As HTML and CSS are not programming languages, so it is time to get some theoretical knowledge about programming. There are some books that I recommend:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/getify/You-Dont-Know-JS/tree/master/up%20%26%20going"&gt;You Don't Know JS: Up &amp;amp; Going&lt;/a&gt;. (for beginning)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is a good introduction into programming and into JavaScript. &lt;a href="https://github.com/getify/You-Dont-Know-JS"&gt;YDKJS&lt;/a&gt; is a series of books diving deep into the core mechanisms of the JavaScript language.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://speakingjs.com/es5/index.html"&gt;Speaking JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://eloquentjavascript.net/"&gt;Eloquent JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide"&gt;MDN JS Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These books and tutorials should give you a basic understanding of the language. &lt;/p&gt;

&lt;h3&gt;
  
  
  Learn using the Command line
&lt;/h3&gt;

&lt;p&gt;Getting to know the command line is necessary. Learn the basic commands like how to enter/leave a directory, and edit/copy/move/remove files. You will use them a lot - so why not save time for yourself by learning them at the beginning?&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with vanilla JS, learn the frameworks and advanced concepts later.
&lt;/h2&gt;

&lt;p&gt;Forget these cool words like React, Vue, Angular, Node.js, OOP, Webpack, functional programming, etc. In my experience, until you don’t know the basics, it is absolutely unwanted to confuse your mind with these advanced concepts and frameworks. Be patient, you will get there soon. &lt;/p&gt;

&lt;p&gt;Get the &lt;a href="https://www.w3schools.com/js/"&gt;basics&lt;/a&gt; right first, and start coding ASAP with &lt;a href="https://stackoverflow.com/questions/20435653/what-is-vanillajs"&gt;Vanilla JS&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup IDE
&lt;/h3&gt;

&lt;p&gt;Setting up an IDE with a decent config will make your life easier. My personal favourite is VSCode, but there are other amazing IDE’s like Atom, WebStorm, Brackets or Sublime.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choose a project to build
&lt;/h3&gt;

&lt;p&gt;Your project can be a todo-app, a calculator or basically anything. Don’t choose very complex projects, it’s good to have a sense of achievement in the beginning. As you develop your project, you’ll have lot of questions. Use MDN, StackOverflow and Google. As I said above, there is an answer almost for all questions a beginner going to face. In case of you have no idea what kind of project to build, I provide some links below which maybe help with the decision.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.codementor.io/npostolovski/40-side-project-ideas-for-software-engineers-g8xckyxef"&gt;https://www.codementor.io/npostolovski/40-side-project-ideas-for-software-engineers-g8xckyxef&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://skillcrush.com/2018/06/18/projects-you-can-do-with-javascript/"&gt;https://skillcrush.com/2018/06/18/projects-you-can-do-with-javascript/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@GarrettLevine/5-projects-to-complete-when-starting-to-learn-front-end-web-development-48e8a1ce3178"&gt;https://medium.com/@GarrettLevine/5-projects-to-complete-when-starting-to-learn-front-end-web-development-48e8a1ce3178&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Learn from your mistakes
&lt;/h3&gt;

&lt;p&gt;Learning from mistakes is also an essential part of the process. Don’t be afraid to break the code. A failure is an opportunity to prevent future failures, and it makes you curious how to solve the problem.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Moving Forward
&lt;/h3&gt;

&lt;p&gt;I think you can get familiar with these things I outlined within 1-2 months if you do some exercise every day. Once you think you are confident with this knowledge, and made some hobby projects, and read the books, you can do a level up, and choose a framework and set Node.js in motion as well. &lt;/p&gt;

&lt;p&gt;In the meantime you should explore more stuff about JavaScript like articles, newsletters, podcasts, YouTube channels, and a lot of tutorials. &lt;/p&gt;

&lt;p&gt;If you have accomplished all of the above, you can start getting to know &lt;a href="https://docs.npmjs.com/getting-started/what-is-npm"&gt;NPM&lt;/a&gt;, the package manager of JavaScript and Node.js.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Summary and Next Up
&lt;/h2&gt;

&lt;p&gt;In the next chapter, I’ll continue with an overview of the JavaScript ecosystem, and a roadmap of frontend development (React, Vue.js, etc.), a backend roadmap for Node, and with some tips to get hired.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Originally published at &lt;a href="https://blog.risingstack.com/learn-javascript-for-free/"&gt;blog.risingstack.com&lt;/a&gt; on October 9, 2018.&lt;/i&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
