<?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: Damian Kajzer</title>
    <description>The latest articles on DEV Community by Damian Kajzer (@kraftdorian).</description>
    <link>https://dev.to/kraftdorian</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%2F609481%2F6da54249-c54a-43b2-b4f0-26af19352dbf.png</url>
      <title>DEV Community: Damian Kajzer</title>
      <link>https://dev.to/kraftdorian</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kraftdorian"/>
    <language>en</language>
    <item>
      <title>I built SSR in NGINX using njs. Here’s what I learned</title>
      <dc:creator>Damian Kajzer</dc:creator>
      <pubDate>Thu, 09 Apr 2026 07:45:30 +0000</pubDate>
      <link>https://dev.to/kraftdorian/i-built-ssr-in-nginx-using-njs-heres-what-i-learned-41h1</link>
      <guid>https://dev.to/kraftdorian/i-built-ssr-in-nginx-using-njs-heres-what-i-learned-41h1</guid>
      <description>&lt;p&gt;I built a minimal SSR runtime directly inside NGINX — and ended up using it in production.&lt;/p&gt;

&lt;p&gt;For some time, I’ve been using NGINX with njs for things like CSP nonce generation and request-level logic.&lt;/p&gt;

&lt;p&gt;This started as an extension of something I was already using in production (CSP handling in NGINX).&lt;/p&gt;

&lt;p&gt;At some point I asked myself a simple question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;can this go a bit further?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This started as a small experiment — but it ended up running in production on my personal website.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/kraftdorian/nginx-njs-ssr-starter" rel="noopener noreferrer"&gt;https://github.com/kraftdorian/nginx-njs-ssr-starter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A minimal SSR-like runtime using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NGINX&lt;/li&gt;
&lt;li&gt;njs (JavaScript inside NGINX)&lt;/li&gt;
&lt;li&gt;simple component rendering patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No Node.js. No Next.js. Just NGINX.&lt;/p&gt;

&lt;p&gt;The runtime is intentionally small and explicit — closer to a rendering utility than a framework.&lt;/p&gt;




&lt;h2&gt;
  
  
  How it works (high-level)
&lt;/h2&gt;

&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client → Node SSR → HTML
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I explored:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client → NGINX (njs) → HTML
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The idea is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;execute JavaScript during request handling (via njs)&lt;/li&gt;
&lt;li&gt;generate HTML on the fly&lt;/li&gt;
&lt;li&gt;return it directly from NGINX&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In practice, this is a string-first rendering model — HTML is built directly as strings using small helper functions, without a virtual DOM or template engine.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. I underestimated how far NGINX can go
&lt;/h3&gt;

&lt;p&gt;Before this, I treated NGINX mainly as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a reverse proxy&lt;/li&gt;
&lt;li&gt;a place for headers and routing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Working with njs changed that for me.&lt;/p&gt;

&lt;p&gt;I learned that it can also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;execute request-level logic&lt;/li&gt;
&lt;li&gt;generate dynamic responses&lt;/li&gt;
&lt;li&gt;act as a very lightweight rendering layer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s constrained — but that constraint is actually part of the value.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. SSR became much simpler once I stripped it down
&lt;/h3&gt;

&lt;p&gt;While building this, I kept coming back to a simple realization:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;SSR is just returning HTML from the server.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Everything else is layered on top.&lt;/p&gt;

&lt;p&gt;This project helped me separate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what SSR actually is&lt;/li&gt;
&lt;li&gt;how we usually implement it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That distinction alone made the whole topic much clearer for me.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Constraints shape the system more than features
&lt;/h3&gt;

&lt;p&gt;This project is intentionally limited:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;synchronous rendering only&lt;/li&gt;
&lt;li&gt;no external I/O&lt;/li&gt;
&lt;li&gt;no hidden state&lt;/li&gt;
&lt;li&gt;deterministic output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At first this felt restrictive.&lt;/p&gt;

&lt;p&gt;In practice, it made the system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;easier to reason about&lt;/li&gt;
&lt;li&gt;easier to debug&lt;/li&gt;
&lt;li&gt;more predictable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I learned that removing capabilities can improve clarity more than adding abstractions.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. The trade-offs are very different from typical SSR setups
&lt;/h3&gt;

&lt;p&gt;What I gained:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;no Node.js runtime&lt;/li&gt;
&lt;li&gt;very fast execution path&lt;/li&gt;
&lt;li&gt;minimal moving parts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What I lost:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;full JavaScript runtime&lt;/li&gt;
&lt;li&gt;ecosystem and tooling&lt;/li&gt;
&lt;li&gt;familiar debugging patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This shifted my thinking from “application-level design” to something closer to “infra-level design”.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. Rendering inside the infrastructure layer changes how concerns fit together
&lt;/h3&gt;

&lt;p&gt;One thing that stood out was how naturally this integrates with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CSP&lt;/li&gt;
&lt;li&gt;headers&lt;/li&gt;
&lt;li&gt;request validation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because everything happens inside NGINX, these concerns don’t need to be split across layers.&lt;/p&gt;

&lt;p&gt;That made the system feel more cohesive than I expected.&lt;/p&gt;




&lt;h3&gt;
  
  
  6. I learned how to coordinate between different types of AI tools
&lt;/h3&gt;

&lt;p&gt;An unexpected part of this project was the development workflow itself.&lt;/p&gt;

&lt;p&gt;I ended up coordinating between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a text-oriented model (ChatGPT) — for reasoning, structure, and constraints&lt;/li&gt;
&lt;li&gt;a code-oriented agent (Codex) — for implementation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The runtime itself was implemented with Codex, but always under explicit architectural constraints and iteration from my side.&lt;/p&gt;

&lt;p&gt;In practice, this meant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;defining the shape of the system first&lt;/li&gt;
&lt;li&gt;using Codex to fill in implementation details&lt;/li&gt;
&lt;li&gt;validating everything against real runtime behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation turned out to be much more effective than trying to generate everything in one step.&lt;/p&gt;




&lt;h2&gt;
  
  
  When this approach makes sense (from my perspective)
&lt;/h2&gt;

&lt;p&gt;I would consider it for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;small or mostly static sites&lt;/li&gt;
&lt;li&gt;simple rendering layers&lt;/li&gt;
&lt;li&gt;cases where control over HTML and security matters&lt;/li&gt;
&lt;li&gt;infra-level experiments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wouldn’t use it for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;complex frontend applications&lt;/li&gt;
&lt;li&gt;heavy interactivity&lt;/li&gt;
&lt;li&gt;teams relying on a large ecosystem&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Setup (very simple)
&lt;/h2&gt;

&lt;p&gt;If you’ve configured NGINX before, this should feel familiar.&lt;/p&gt;

&lt;p&gt;This is intentionally close to a production-like setup.&lt;/p&gt;

&lt;p&gt;Basic steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install NGINX with njs&lt;/li&gt;
&lt;li&gt;Clone the repository&lt;/li&gt;
&lt;li&gt;Load the configuration&lt;/li&gt;
&lt;li&gt;Run&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Full instructions:&lt;br&gt;
👉 &lt;a href="https://github.com/kraftdorian/nginx-njs-ssr-starter" rel="noopener noreferrer"&gt;https://github.com/kraftdorian/nginx-njs-ssr-starter&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;This started as a small extension of something I was already using (CSP handling in NGINX).&lt;/p&gt;

&lt;p&gt;It turned into a useful way to better understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how far rendering can be pushed into infrastructure&lt;/li&gt;
&lt;li&gt;how constraints shape system design&lt;/li&gt;
&lt;li&gt;what we actually need from SSR in practice&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Building it — and running it in production on my own site — made those trade-offs much more concrete.&lt;/p&gt;

&lt;p&gt;It also changed how I think about where frontend actually ends — and where infrastructure begins.&lt;/p&gt;

&lt;p&gt;Sometimes removing layers teaches more than adding new ones.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>nginx</category>
      <category>javascript</category>
      <category>performance</category>
    </item>
    <item>
      <title>Configuring CSP nonce for nginx 1.28 on Ubuntu 24 LTS using NJS</title>
      <dc:creator>Damian Kajzer</dc:creator>
      <pubDate>Mon, 29 Dec 2025 17:12:33 +0000</pubDate>
      <link>https://dev.to/kraftdorian/configuring-csp-nonce-for-nginx-128-on-ubuntu-24-lts-using-njs-3pja</link>
      <guid>https://dev.to/kraftdorian/configuring-csp-nonce-for-nginx-128-on-ubuntu-24-lts-using-njs-3pja</guid>
      <description>&lt;h2&gt;
  
  
  Content Security Policy
&lt;/h2&gt;

&lt;p&gt;CSP is a way to tell a browser that only the provided locations and/or resources should be loaded.&lt;/p&gt;

&lt;p&gt;Learn more about &lt;a href="https://owasp.org/www-community/controls/Content_Security_Policy" rel="noopener noreferrer"&gt;CSP&lt;/a&gt; on OWASP.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nonce
&lt;/h2&gt;

&lt;p&gt;It is an expression of CSP's header fetch directive. Essentially, it's a way to tell the browser to only load styles and scripts that are having &lt;code&gt;nonce&lt;/code&gt; HTML attribute's value matching whatever is present in the CSP's header.&lt;/p&gt;

&lt;p&gt;Learn more about &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy#nonce-nonce_value" rel="noopener noreferrer"&gt;CSP's nonce expression syntax&lt;/a&gt; on MDN.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example nonce configuration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Server responds with headers:
...
Content-Security-Policy: script-src 'self' 'nonce-foo';
...

HTML page:
...
&amp;lt;script nonce="foo"&amp;gt;console.log('safe');&amp;lt;/script&amp;gt; &amp;lt;!-- safe, foo === foo  --&amp;gt;
&amp;lt;script nonce="bar"&amp;gt;console.log('unsafe');&amp;lt;/script&amp;gt; &amp;lt;!-- unsafe, foo !== bar --&amp;gt;
&amp;lt;script&amp;gt;console.log('unsafe');&amp;lt;/script&amp;gt; &amp;lt;!-- unsafe, no nonce value --&amp;gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Nginx
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://nginx.org/en/" rel="noopener noreferrer"&gt;Nginx&lt;/a&gt; is an opinionated HTTP web server, which we'll be using for educational purposes of this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  NJS
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://nginx.org/en/docs/njs/" rel="noopener noreferrer"&gt;NJS (Nginx JavaScript)&lt;/a&gt; is a dynamic module of nginx that allows its advanced configuration via JavaScript-like sources.&lt;/p&gt;

&lt;p&gt;It exposes useful APIs, such as &lt;a href="https://nginx.org/en/docs/njs/reference.html#crypto" rel="noopener noreferrer"&gt;Crypto&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The process
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Adding nginx official repo to apt sources
&lt;/h3&gt;

&lt;p&gt;Please follow &lt;a href="https://nginx.org/en/linux_packages.html#Ubuntu" rel="noopener noreferrer"&gt;nginx's linux packages instructions&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Installing nginx-module-njs
&lt;/h3&gt;

&lt;p&gt;Since we're now having nginx's repo in apt sources - let's install njs as dynamic nginx module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;nginx-module-njs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Configuration of nginx to load njs module
&lt;/h3&gt;

&lt;p&gt;We need to load the module in &lt;code&gt;nginx.conf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;# /etc/nginx/nginx.conf
&lt;span class="gi"&gt;+ load_module modules/ngx_http_js_module.so;
+ load_module modules/ngx_stream_js_module.so;
&lt;/span&gt;&lt;span class="p"&gt;http {
&lt;/span&gt;&lt;span class="gi"&gt;+  js_path "/etc/nginx/njs/";
&lt;/span&gt;...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, it would be nice to either allow passing secret key for &lt;code&gt;nonce&lt;/code&gt; generation via docker's container env variable, or set it explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;# /etc/nginx/nginx.conf
&lt;span class="gi"&gt;+ env NONCE_SECRET_KEY;
&lt;/span&gt;&lt;span class="p"&gt;load_module modules/ngx_http_js_module.so;
load_module modules/ngx_stream_js_module.so;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Writing NJS script to generate nonce values
&lt;/h3&gt;

&lt;p&gt;This is an example of NJS script that leverages nginx's &lt;code&gt;request_id&lt;/code&gt; variable to create SHA1 HMAC hex string:&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;// /etc/nginx/njs/nonce.njs&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;crypto&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;crypto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&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;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHmac&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sha1&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;NONCE_SECRET_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request_id&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;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hex&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;export&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;nonce&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Setting CSP header using NJS
&lt;/h3&gt;

&lt;p&gt;Now, whenever we need to apply the CSP header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;# /etc/nginx/nginx.conf, /etc/nginx/sites-available/yoursite, ...
...
&lt;span class="gi"&gt;+ js_import main from nonce.njs;
+ js_set $csp_nonce main.nonce;
+ add_header Content-Security-Policy "script-src 'self' 'nonce-$csp_nonce'";
&lt;/span&gt;...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's reload nginx configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;service nginx reload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point we should see the header being set correctly in the response.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Setting nonce in HTML pages (OPTIONAL)
&lt;/h3&gt;

&lt;p&gt;Since we're now having the &lt;code&gt;csp_nonce&lt;/code&gt; variable in place, produced by NJS, let's use it in nginx's &lt;code&gt;sub_filter&lt;/code&gt; directive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;# /etc/nginx/nginx.conf, /etc/nginx/sites-available/yoursite, ...
...
&lt;span class="gi"&gt;+ sub_filter_once off;
+ sub_filter CSP_NONCE $csp_nonce;
&lt;/span&gt;...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's reload nginx configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;service nginx reload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, in HTML page we can reference it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;nonce=&lt;/span&gt;&lt;span class="s"&gt;"CSP_NONCE"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nonce works!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;We have successfully configured &lt;code&gt;Content Security Policy&lt;/code&gt; header in nginx, using nginx JavaScript dynamic module.&lt;/p&gt;

&lt;p&gt;Further enhancements and/or adjustments can be made to meet our particular needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cover image
&lt;/h3&gt;

&lt;p&gt;Cover image was generated using AI.&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>nginx</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Creating React TypeScript component library - Testing with Jest, Summary</title>
      <dc:creator>Damian Kajzer</dc:creator>
      <pubDate>Sun, 01 Aug 2021 22:03:27 +0000</pubDate>
      <link>https://dev.to/kraftdorian/creating-react-typescript-component-library-testing-with-jest-summary-3mpm</link>
      <guid>https://dev.to/kraftdorian/creating-react-typescript-component-library-testing-with-jest-summary-3mpm</guid>
      <description>&lt;h2&gt;
  
  
  Doin' it Right
&lt;/h2&gt;

&lt;p&gt;To be sure that our component(s) work as expected, we can test them with the Jest and React Testing Library.&lt;/p&gt;

&lt;p&gt;I used these references for purposes of this article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://testing-library.com/docs/react-testing-library/setup/" rel="noopener noreferrer"&gt;https://testing-library.com/docs/react-testing-library/setup/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jestjs.io/docs/getting-started" rel="noopener noreferrer"&gt;https://jestjs.io/docs/getting-started&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Firstly, we need to install these libraries, obviously:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;--save-dev&lt;/span&gt; jest ts-jest @types/jest @testing-library/react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then, we must add the Jest types to tsconfig.json:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"types"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"jest"&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;Finally, if we want, we can use the Jest configuration tool.&lt;br&gt;
If the first command doesn't work, you can use the second one:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jest &lt;span class="nt"&gt;--init&lt;/span&gt;
npx jest &lt;span class="nt"&gt;--init&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It will ask you a few questions:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frvgmqr7rq25i199dxewn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frvgmqr7rq25i199dxewn.png" alt="Jest config initialization questions" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Done! It created a lot of config options for us, but these ones will suffice for our purposes:&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;// @/jest.config.js&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;moduleDirectories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node_modules&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="s2"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;moduleFileExtensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;js&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="s2"&gt;ts&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="s2"&gt;tsx&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="s2"&gt;json&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="s2"&gt;node&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;roots&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;testEnvironment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jest-environment-jsdom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Use browser-like testing environment&lt;/span&gt;
  &lt;span class="na"&gt;testMatch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;**/__tests__/**/*.[jt]s?(x)&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="s2"&gt;**/?(*.)+(spec|test).[tj]s?(x)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;testPathIgnorePatterns&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="se"&gt;\\\\&lt;/span&gt;&lt;span class="s2"&gt;node_modules&lt;/span&gt;&lt;span class="se"&gt;\\\\&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^.+&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;.(ts|tsx)$&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="s2"&gt;ts-jest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;// That one tells Jest to use ts-jest when dealing with TypeScript files&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;
  
  
  Around the World (or the Project?)
&lt;/h2&gt;

&lt;p&gt;If we want to be able to access our basic setup of React Testing Library easily, we can make use of &lt;a href="https://www.typescriptlang.org/tsconfig#paths" rel="noopener noreferrer"&gt;TypeScript paths configuration&lt;/a&gt; in tsconfig.json:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"baseUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"paths"&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;"test-setup"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"test-setup"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In a separate file, we create a &lt;a href="https://testing-library.com/docs/react-testing-library/setup/#custom-render" rel="noopener noreferrer"&gt;custom render method&lt;/a&gt; that can include any stuff we need - store and theme providers, and more, to be used globally in our tests.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// @/src/test-setup.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ReactElement&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;RenderOptions&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Here we can set all providers for themes, stores and other stuff&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AllTheProviders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&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;children&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;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&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;customRender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReactElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nb"&gt;Omit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RenderOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wrapper&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AllTheProviders&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/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;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;customRender&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Voyager (through the component logic)
&lt;/h2&gt;

&lt;p&gt;As we have completed the configuration, we can write a test for the Component:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// @/src/index.test.tsx&lt;/span&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="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test-setup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Basic&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./index.stories&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;renders without crashing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&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;Component&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeTruthy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now, run test command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If everything is good, then that's what should appear:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyme5pk60q3fxx6qptzbd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyme5pk60q3fxx6qptzbd.png" alt="Jest test command result" width="319" height="209"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;This article concludes the "Creating React TypeScript component library with rollup.js from scratch" series.&lt;/p&gt;

&lt;p&gt;There are still a lot of things that could be made in our awesome component library, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;installing Styled Components,&lt;/li&gt;
&lt;li&gt;adding husky/yorkie with precommit git hook that uses lint-staged to format changed source files with prettier,&lt;/li&gt;
&lt;li&gt;exploring how we can publish our library to npm.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, I believe, now as we have our basic project, it's not a challenge for you.&lt;/p&gt;

&lt;p&gt;You can find the finished repository here, in case of any doubts:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/kraftdorian" rel="noopener noreferrer"&gt;
        kraftdorian
      &lt;/a&gt; / &lt;a href="https://github.com/kraftdorian/react-ts-rollup-starter-lib" rel="noopener noreferrer"&gt;
        react-ts-rollup-starter-lib
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      React TypeScript components library built with rollup.js from scratch.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Component library starter template&lt;/h1&gt;

&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Used libraries&lt;/h2&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://reactjs.org/" rel="nofollow noopener noreferrer"&gt;React.js v17&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/" rel="nofollow noopener noreferrer"&gt;TypeScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rollupjs.org/" rel="nofollow noopener noreferrer"&gt;Rollup.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://storybook.js.org/" rel="nofollow noopener noreferrer"&gt;Storybook&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Notes&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;This is a repository created for learning purposes,
specifically to use one of my articles which you can find
&lt;a href="https://dev.to/kraftdorian/creating-react-typescript-component-library-basic-rollup-js-setup-3k93" rel="nofollow"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/kraftdorian/react-ts-rollup-starter-lib" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


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

&lt;p&gt;Article cover photo by &lt;a href="https://unsplash.com/@lazycreekimages?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Michael Dziedzic&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Creating React TypeScript component library - Adding React and Storybook</title>
      <dc:creator>Damian Kajzer</dc:creator>
      <pubDate>Fri, 23 Jul 2021 22:31:48 +0000</pubDate>
      <link>https://dev.to/kraftdorian/creating-react-typescript-component-library-adding-react-and-storybook-1o7c</link>
      <guid>https://dev.to/kraftdorian/creating-react-typescript-component-library-adding-react-and-storybook-1o7c</guid>
      <description>&lt;h2&gt;
  
  
  The Core of the library
&lt;/h2&gt;

&lt;p&gt;This article deals with the installation of React and explains npm peer dependencies.&lt;br&gt;
In the end, we will be able to see our component in a browser.&lt;/p&gt;
&lt;h2&gt;
  
  
  Superheroes (React and friends)
&lt;/h2&gt;

&lt;p&gt;This part is very easy. Just install React, React DOM, and types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;--save-dev&lt;/span&gt; react react-dom @types/react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now, we need to add react and react-dom to package.json peerDependencies. Why?&lt;br&gt;
I recommend reading this great article that can be found on the npm blog: &lt;a href="https://nodejs.org/en/blog/npm/peer-dependencies" rel="noopener noreferrer"&gt;https://nodejs.org/en/blog/npm/peer-dependencies&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's just all about the fact, that we create some independent package:&lt;/p&gt;


&lt;blockquote&gt;
What we need is a way of expressing these "dependencies" between plugins and their host package.
&lt;/blockquote&gt;
—Domenic Denicola, &lt;cite&gt;Peer Dependencies&lt;/cite&gt;



&lt;p&gt;&lt;br&gt;So, you can add this above you devDependencies:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"peerDependencies"&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;"react"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=16.8.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"react-dom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=16.8.0"&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;Why 16.8.0? React Hooks were added in that version! :-)&lt;/p&gt;

&lt;p&gt;Do you remember rollup-plugin-peer-deps-external dependency we added before? It automatically excludes peer dependencies that we just set from the bundle.&lt;/p&gt;

&lt;p&gt;In case you missed that part or want to recall it, you can find it in my previous article:&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/kraftdorian/creating-react-typescript-component-library-basic-rollup-js-setup-3k93" class="crayons-story__hidden-navigation-link"&gt;Creating React TypeScript component library - basic rollup.js setup&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/kraftdorian" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F609481%2F6da54249-c54a-43b2-b4f0-26af19352dbf.png" alt="kraftdorian profile" class="crayons-avatar__image" width="800" height="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/kraftdorian" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Damian Kajzer
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Damian Kajzer
                
              
              &lt;div id="story-author-preview-content-761449" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/kraftdorian" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F609481%2F6da54249-c54a-43b2-b4f0-26af19352dbf.png" class="crayons-avatar__image" alt="" width="800" height="800"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Damian Kajzer&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/kraftdorian/creating-react-typescript-component-library-basic-rollup-js-setup-3k93" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 20 '21&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/kraftdorian/creating-react-typescript-component-library-basic-rollup-js-setup-3k93" id="article-link-761449"&gt;
          Creating React TypeScript component library - basic rollup.js setup
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/typescript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;typescript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/react"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;react&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/library"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;library&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/rollupjs"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;rollupjs&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/kraftdorian/creating-react-typescript-component-library-basic-rollup-js-setup-3k93" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;11&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/kraftdorian/creating-react-typescript-component-library-basic-rollup-js-setup-3k93#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;Next, as we have properly installed React, we can update our rollup.config.js, and change the index file extension:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- input: ["src/index.ts"]
&lt;/span&gt;&lt;span class="gi"&gt;+ input: ["src/index.tsx"]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we can update our component to use JSX:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// @/src/index.tsx&lt;/span&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;Component&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 view these changes in &lt;a href="https://github.com/kraftdorian/react-ts-rollup-starter-lib/tree/1.2.0" rel="noopener noreferrer"&gt;my GitHub repo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Face to Face (of our component)
&lt;/h2&gt;

&lt;p&gt;Now, how we are able to see our component in action?&lt;br&gt;
Browsing many solutions available, a nice choice is to use the &lt;a href="https://storybook.js.org" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt;.&lt;br&gt;
It's a great tool for UI development, so it's perfect for our case.&lt;/p&gt;

&lt;p&gt;To install it, just run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx sb init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it asks for permission to install sb package then it's fine, you can just confirm that.&lt;br&gt;
This will create src/stories directory with some examples, you can delete them.&lt;br&gt;
Also, you will find some new scripts in package.json.&lt;/p&gt;

&lt;p&gt;Let's go ahead and create a story for our component!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// @/src/index.stories.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;PropsWithChildren&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Story&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Component&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;./index&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// This is meta information about our component&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Meta&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PropsWithChildren&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&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;My Component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// What title to display in component story page&lt;/span&gt;
  &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// This one is obvious :-)&lt;/span&gt;
  &lt;span class="na"&gt;argTypes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  &lt;span class="c1"&gt;// Here we can specify configuration for our component's props&lt;/span&gt;
    &lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="p"&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;Content or elements to be rendered inside the Component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;control&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;text&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="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Create one template for our component's story to use in some custom variants&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Story&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PropsWithChildren&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Basic variant of our component&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Basic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;
&lt;span class="nx"&gt;Basic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Basic&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;Now, to run Storybook in watch mode, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run storybook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should open your browser at localhost with a 6006 default port.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl73na3quj1a8n0vpfjqg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl73na3quj1a8n0vpfjqg.png" alt="Storybook default screen in watch mode" width="800" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also view these changes in &lt;a href="https://github.com/kraftdorian/react-ts-rollup-starter-lib/tree/1.3.0" rel="noopener noreferrer"&gt;my GitHub repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In any case, that's it for this article.&lt;br&gt;
Thanks for reading!&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@lazycreekimages?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Michael Dziedzic&lt;/a&gt; on &lt;a href="https://unsplash.com/@lazycreekimages?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Creating React TypeScript component library - basic rollup.js setup</title>
      <dc:creator>Damian Kajzer</dc:creator>
      <pubDate>Tue, 20 Jul 2021 10:00:02 +0000</pubDate>
      <link>https://dev.to/kraftdorian/creating-react-typescript-component-library-basic-rollup-js-setup-3k93</link>
      <guid>https://dev.to/kraftdorian/creating-react-typescript-component-library-basic-rollup-js-setup-3k93</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;I have worked on several custom front-end projects and often thought about using the same styles and/or components, so other developers could use consistent UI.&lt;/p&gt;

&lt;p&gt;Too long I was afraid of creating a separate library, so usually, I was ending up including the components directly in the project files.&lt;/p&gt;

&lt;p&gt;That's not the case here!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is it about?
&lt;/h2&gt;

&lt;p&gt;This is the first article I have created in a series "Creating React TypeScript component library with rollup.js from scratch".&lt;br&gt;
Hopefully, the title explains the article's contents.&lt;/p&gt;

&lt;p&gt;It's all about configuration and installing proper libraries. I won't give it too much attention, just quickly explain what is necessary and why.&lt;/p&gt;

&lt;p&gt;If you want to see the whole code as it is at the end of this tutorial, just feel free to visit &lt;a href="https://github.com/kraftdorian/react-ts-rollup-starter-lib/tree/1.1.0" rel="noopener noreferrer"&gt;this repo&lt;/a&gt; at my GitHub account.&lt;br&gt;
Also, give it a star if you want!&lt;/p&gt;
&lt;h3&gt;
  
  
  Important note
&lt;/h3&gt;

&lt;p&gt;This article is based on these sources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.harveydelaney.com/creating-your-own-react-component-library" rel="noopener noreferrer"&gt;https://blog.harveydelaney.com/creating-your-own-react-component-library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/a-tarasyuk/rollup-typescript-babel" rel="noopener noreferrer"&gt;https://github.com/a-tarasyuk/rollup-typescript-babel&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  A few words about the versions
&lt;/h2&gt;

&lt;p&gt;As I am writing this article I'm using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;node v14.17.0&lt;/li&gt;
&lt;li&gt;npm v6.14.10&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Let's start!
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Armory
&lt;/h3&gt;

&lt;p&gt;Obviously, we need some new directory for our library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;my-ui-library
&lt;span class="nb"&gt;cd &lt;/span&gt;my-ui-library
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we initialize it (you will be prompted to type some stuff. If you don't want to be that specific, then you can use default values by constantly pressing ENTER):&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;In the end, make sure you set this file as your main script in package.json (it doesn't exist now, but we will build it!):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist/index.js"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2021-11-24 UPDATE - TypeScript compiler only
&lt;/h3&gt;

&lt;p&gt;If you want to use TypeScript compiler only, please have a look at this &lt;a href="https://github.com/kraftdorian/react-ts-rollup-starter-lib/blob/master/rollup.config.js" rel="noopener noreferrer"&gt;rollup.config.js&lt;/a&gt; instead, as well as the updated &lt;a href="https://github.com/kraftdorian/react-ts-rollup-starter-lib/blob/master/package.json" rel="noopener noreferrer"&gt;package.json&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Don't forget to create &lt;a href="https://github.com/kraftdorian/react-ts-rollup-starter-lib/blob/master/tsconfig.json" rel="noopener noreferrer"&gt;tsconfig.json&lt;/a&gt; as well.&lt;/p&gt;

&lt;p&gt;Then, feel free to jump straight to the Finale section.&lt;/p&gt;

&lt;p&gt;More details about the original issue are available &lt;a href="https://github.com/kraftdorian/react-ts-rollup-starter-lib/issues/3" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Arrival (of dev dependencies!) - compile with babel &lt;em&gt;(legacy section)&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;We will compile our TypeScript components with Babel.&lt;br&gt;
Types will be generated with TypeScript's compiler.&lt;/p&gt;

&lt;p&gt;It's important to save these deps in dev dependencies - the project where we will put our library doesn't need to have them!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;--save-dev&lt;/span&gt; rollup rollup-plugin-peer-deps-external @rollup/plugin-node-resolve @rollup/plugin-babel @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript @babel/plugin-transform-runtime @babel/runtime @babel/plugin-proposal-class-properties typescript tslib rimraf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Grid (where we will work)
&lt;/h3&gt;

&lt;p&gt;How we are able to build our library? Just specify the &lt;em&gt;build&lt;/em&gt; script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"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;"rimraf dist &amp;amp;&amp;amp; tsc --emitDeclarationOnly &amp;amp;&amp;amp; rollup --config"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"tsc"&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;If you're stuck here, feel free to check this &lt;a href="https://github.com/kraftdorian/react-ts-rollup-starter-lib/blob/1.1.0/package.json" rel="noopener noreferrer"&gt;package.json&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;At this point, we need to somehow run &lt;em&gt;tsc&lt;/em&gt; to initialize our TypeScript config. If for some reason &lt;em&gt;tsc&lt;/em&gt; is not available for you, try adding it to package.json scripts.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;We don't need all the config options that &lt;em&gt;tsc&lt;/em&gt; has created.&lt;br&gt;
You can go ahead and grab the ones I prepared in this &lt;a href="https://github.com/kraftdorian/react-ts-rollup-starter-lib/blob/master/tsconfig.json" rel="noopener noreferrer"&gt;tsconfig.json&lt;/a&gt;.&lt;br&gt;
You can read more about tsconfig &lt;a href="https://www.typescriptlang.org/tsconfig" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The important thing above is, we want to include our TypeScript files, but exclude node_modules and our built files directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"src/**/*.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"src/**/*.tsx"&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;span class="nl"&gt;"exclude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"node_modules"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"dist"&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;As for Babel, we need to configure it in the babel.config.json file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"presets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"@babel/preset-env"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"@babel/preset-typescript"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"@babel/preset-react"&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;"plugins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"@babel/proposal-class-properties"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"@babel/proposal-object-rest-spread"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Arena (rollup.js vs TypeScript)
&lt;/h3&gt;

&lt;p&gt;Simply place this configuration in your rollup.config.js at the project root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;babel&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;@rollup/plugin-babel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;resolve&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;@rollup/plugin-node-resolve&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;peerDepsExternal&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;rollup-plugin-peer-deps-external&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;pkg&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;./package.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Array of extensions to be handled by babel&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;EXTENSIONS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.ts&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="s2"&gt;.tsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Excluded dependencies - dev dependencies&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;EXTERNAL&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="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;devDependencies&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="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src/index.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  &lt;span class="c1"&gt;// What files we build?&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;dir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Directory where rollup.js will put the built files&lt;/span&gt;
    &lt;span class="na"&gt;sourcemap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// We want a source map to trace the original code&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="s2"&gt;esm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Built files will follow ES Module format&lt;/span&gt;
    &lt;span class="na"&gt;preserveModules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;  &lt;span class="c1"&gt;// This one is important for treeshaking features of our library&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;peerDepsExternal&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;  &lt;span class="c1"&gt;// https://rollupjs.org/guide/en/#peer-dependencies&lt;/span&gt;
    &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;  &lt;span class="c1"&gt;// Resolves node modules&lt;/span&gt;
    &lt;span class="nf"&gt;babel&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;extensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EXTENSIONS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Compile our TypeScript files&lt;/span&gt;
      &lt;span class="na"&gt;babelHelpers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;runtime&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// EDIT(2021-11-18): "inline" is not recommended. Please see the details in https://github.com/kraftdorian/react-ts-rollup-starter-lib/issues/1&lt;/span&gt;
      &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EXTENSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`src/**/*&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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@babel/plugin-transform-runtime&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="na"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EXTERNAL&lt;/span&gt;  &lt;span class="c1"&gt;// https://rollupjs.org/guide/en/#peer-dependencies&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create some simple TypeScript file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// @/src/index.ts&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Finale
&lt;/h3&gt;

&lt;p&gt;Congrats, you've made it to this place!&lt;br&gt;
Now, simply run this npm script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything is good, you will see:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjyvrcwwo389eey5hhtrb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjyvrcwwo389eey5hhtrb.png" alt="Console output after build" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These files will appear in the &lt;em&gt;dist&lt;/em&gt; directory:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhj2vtnxsqwkksvmqf7h9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhj2vtnxsqwkksvmqf7h9.png" alt="dist directory contents" width="246" height="89"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;We have just created a basic project that allows us to compile TypeScript to JavaScript with Babel, and the types are generated by the TypeScript compiler.&lt;/p&gt;

&lt;p&gt;For further reference, all files I have presented here you can find in my repository:&lt;br&gt;
&lt;a href="https://github.com/kraftdorian/react-ts-rollup-starter-lib/tree/1.1.0" rel="noopener noreferrer"&gt;https://github.com/kraftdorian/react-ts-rollup-starter-lib/tree/1.1.0&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2021-11-18 UPDATE
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Changed
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Use "runtime" instead of "inline" in rollup.config.js as the "inline" helpers are not recommended.
Please visit &lt;a href="https://github.com/kraftdorian/react-ts-rollup-starter-lib/issues/1" rel="noopener noreferrer"&gt;https://github.com/kraftdorian/react-ts-rollup-starter-lib/issues/1&lt;/a&gt; for more details.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Article cover photo: &lt;a href="https://unsplash.com/photos/-LFxVNhopfs" rel="noopener noreferrer"&gt;https://unsplash.com/photos/-LFxVNhopfs&lt;/a&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>react</category>
      <category>library</category>
      <category>rollupjs</category>
    </item>
    <item>
      <title>Thoughts on expression matching in JavaScript</title>
      <dc:creator>Damian Kajzer</dc:creator>
      <pubDate>Tue, 04 May 2021 17:00:35 +0000</pubDate>
      <link>https://dev.to/kraftdorian/thoughts-on-expression-matching-in-javascript-36ji</link>
      <guid>https://dev.to/kraftdorian/thoughts-on-expression-matching-in-javascript-36ji</guid>
      <description>&lt;h2&gt;
  
  
  Context
&lt;/h2&gt;

&lt;p&gt;Just one word - curiosity. It stays with me through the whole learning process of programming.&lt;/p&gt;

&lt;p&gt;When I met Erlang's built-in mechanism of expression matching I couldn't stay inert and immediately started comparing it to what I know in JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does JavaScript offer
&lt;/h2&gt;

&lt;p&gt;Let's consider these examples when it comes to matching some expressions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 1 - if
&lt;/h3&gt;

&lt;p&gt;What are we doing here is we describe how our expected value should look like, not to provide something to match.&lt;/p&gt;

&lt;p&gt;For me, it also lacks readability because conditions are mostly used to express the logic and perform various value checks, not to directly deal with the data.&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;else&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="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&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="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;data&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;conditionN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example 2 - switch/true
&lt;/h3&gt;

&lt;p&gt;Similar to the conditions listed above we still describe the value we want to match.&lt;br&gt;
However, for me, it is more readable.&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;case&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="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;conditionN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;break&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;
  
  
  Example 3 - switch
&lt;/h3&gt;

&lt;p&gt;Here, things start to get more interesting.&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;};&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;response&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="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}:&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;matched!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;break&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 &lt;em&gt;won't work&lt;/em&gt; because of the way JavaScript compares the values.&lt;br&gt;
I don't want to list all scenarios below, but you can &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is" rel="noopener noreferrer"&gt;learn more here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&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;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is&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;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example 4 - RegExp
&lt;/h3&gt;

&lt;p&gt;Let's give it a try. It's the closest solution I can think of in terms of expression matching.&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="sr"&gt;/^{"data":&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;}$/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// ["{"data":"foo"}", ""foo"", ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's nice but has some cons. How about a tailored solution?&lt;/p&gt;

&lt;h2&gt;
  
  
  What does Erlang offer?
&lt;/h2&gt;

&lt;p&gt;Let's just have a look at this code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erlang"&gt;&lt;code&gt;&lt;span class="nv"&gt;Response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;}}.&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nv"&gt;Response&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
  &lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;fwrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"matched!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&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="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;fwrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"matched &lt;/span&gt;&lt;span class="si"&gt;~p&lt;/span&gt;&lt;span class="s"&gt;!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;fwrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;fwrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"default match"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="c"&gt;% matched!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We don't even know some values in the match expression but Erlang is still able to find them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Experimenting with JavaScript implementation
&lt;/h2&gt;

&lt;p&gt;After a couple of days where I couldn't write anything worth sharing, I have some POC, that you can find &lt;a href="https://github.com/kraftdorian/js-expr-poc" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="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;Error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;some_dynamic_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;&amp;lt;expr@Status&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&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;&amp;lt;&amp;lt;expr@Message&amp;gt;&amp;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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;&amp;lt;expr@DynamicKey&amp;gt;&amp;gt;&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="s2"&gt;&amp;lt;&amp;lt;expr@DynamicKeyValue&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;match_val&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;template&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// [true, [false, 'Error', 'some_dynamic_key', null]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Overall, I think that an expression matching mechanism in JavaScript would be nice to have for specific use-cases as we have in functional programming.&lt;/p&gt;

&lt;p&gt;Also, it's always nice to learn new things and how they could have been implemented.&lt;/p&gt;

&lt;h6&gt;
  
  
  Article cover photo by &lt;a href="https://unsplash.com/photos/gEN5Btvf2Eg" rel="noopener noreferrer"&gt;Michael Dziedzic&lt;/a&gt;
&lt;/h6&gt;

</description>
      <category>javascript</category>
      <category>erlang</category>
    </item>
    <item>
      <title>Prolog-ic JavaScript</title>
      <dc:creator>Damian Kajzer</dc:creator>
      <pubDate>Tue, 06 Apr 2021 13:54:28 +0000</pubDate>
      <link>https://dev.to/kraftdorian/prolog-ic-javascript-1jek</link>
      <guid>https://dev.to/kraftdorian/prolog-ic-javascript-1jek</guid>
      <description>&lt;h2&gt;
  
  
  Firstly, a context
&lt;/h2&gt;

&lt;p&gt;Recently, I've started learning programming languages present in amazing &lt;em&gt;&lt;a href="https://pragprog.com/titles/btlang/seven-languages-in-seven-weeks/" rel="noopener noreferrer"&gt;Seven Languages in Seven Weeks&lt;/a&gt;&lt;/em&gt; book by Bruce Tate.&lt;/p&gt;

&lt;p&gt;I discovered a very special one - &lt;em&gt;&lt;a href="https://www.swi-prolog.org/" rel="noopener noreferrer"&gt;Prolog&lt;/a&gt;&lt;/em&gt; - as it is a declarative language.&lt;/p&gt;

&lt;p&gt;It means, that the &lt;strong&gt;programmer does not provide ready implementation, but gives instructions on how to solve the problem&lt;/strong&gt; and &lt;em&gt;Prolog&lt;/em&gt; tries to figure it out.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does it apply to imperative JavaScript?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A typical Prolog use cases are things like processing the natural language, specific expert systems, and even AI.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We use various JavaScript and TypeScript frameworks to specify how an application works and looks like.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, what do these have in common?&lt;br&gt;
&lt;em&gt;We need to know, what we are trying to achieve.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Prolog is just giving us a lesson on how to ask questions efficiently, not to answer them.&lt;/p&gt;
&lt;h2&gt;
  
  
  A practical example
&lt;/h2&gt;

&lt;p&gt;My very first thoughts of writing Prolog-based JavaScript algorithms appeared as a result of curiosity.&lt;br&gt;
How do you even translate facts and rules to something that works for JS?&lt;/p&gt;

&lt;p&gt;Let's have a look at an example - how &lt;em&gt;&lt;a href="https://github.com/kraftdorian/7languages7weeks/blob/master/prolog/src/day2/reverse.pl" rel="noopener noreferrer"&gt;list reverse algorithm&lt;/a&gt;&lt;/em&gt; written in Prolog is similar to a &lt;em&gt;&lt;a href="https://gist.github.com/kraftdorian/8b31ac73fed314ba6e014f486b454125" rel="noopener noreferrer"&gt;JavaScript one&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Making the question
&lt;/h2&gt;

&lt;p&gt;When we are asking Prolog for a solution, we need to think about what the definition of the reversed list might look like.&lt;/p&gt;

&lt;p&gt;One of the most used ideas when you are dealing with lists there&lt;br&gt;
is to use the idea of &lt;em&gt;accumulator&lt;/em&gt; - something, that will store the things we already know.&lt;/p&gt;

&lt;p&gt;So, our first fact would be that reversing an empty list will result in.. empty list.&lt;/p&gt;

&lt;p&gt;However, when we will deal with non-empty lists - we don't know their size.&lt;br&gt;
In such scenarios, recursion is the way to process them.&lt;/p&gt;

&lt;p&gt;Therefore, the refined &lt;strong&gt;first fact will be that reversing an empty list will result in some list and accumulator will be the same list&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight prolog"&gt;&lt;code&gt;&lt;span class="ss"&gt;list_reverse_state&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt; &lt;span class="nv"&gt;List&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;List&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next step is to actually define our expectations for non-empty lists.&lt;br&gt;
It's important to know here that Prolog uses tail recursion, so things can look confusing and out of order, but they actually work.&lt;br&gt;
It sometimes takes a while to understand it, so I placed appropriate comments in the code.&lt;/p&gt;

&lt;p&gt;Now we describe a rule, that the &lt;strong&gt;current list element needs to be placed before the accumulator&lt;/strong&gt; (remember when I wrote - the things we already know?), as the original list is slowly going to be emptied.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight prolog"&gt;&lt;code&gt;&lt;span class="ss"&gt;list_reverse_state&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nv"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;Tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;OutputList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;ListStack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;
  &lt;span class="ss"&gt;list_reverse_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;OutputList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;ListStack&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When it will become empty, the first fact will be met so the output will be the same as the &lt;em&gt;accumulator&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;... and that's it for Prolog!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight prolog"&gt;&lt;code&gt;&lt;span class="ss"&gt;list_reverse_state&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt; &lt;span class="nv"&gt;List&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;List&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;span class="ss"&gt;list_reverse_state&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nv"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;Tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;OutputList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;ListStack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;
  &lt;span class="ss"&gt;list_reverse_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;OutputList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;ListStack&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Translation to JavaScript
&lt;/h2&gt;

&lt;p&gt;When we review our final question to Prolog above, the things are getting clear - we exactly know what we want to do.&lt;/p&gt;

&lt;p&gt;It was a great experience for me, figuring out that the only work needed to be done in JS was to follow the same behavior as described in our question.&lt;/p&gt;

&lt;p&gt;It can be actually simplified because the second argument is not needed at all, added it just to show the similarities.&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;usePrologStyleList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&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;head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;array&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="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tail&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;listReverseState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reversedList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;acc&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;head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;usePrologStyleList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// list_reverse_state([], List, List).&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;head&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;reversedList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// (...) :- list_reverse_state(Tail, OutputList, [Head|ListStack])&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;listReverseState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reversedList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;acc&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;listReverse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;listReverseState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&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;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Hopefully, you will discover how appropriate problem descriptions written in declarative language can boost your imperative language skills.&lt;/p&gt;

&lt;h6&gt;
  
  
  Article cover photo by &lt;a href="https://unsplash.com/photos/qDG7XKJLKbs" rel="noopener noreferrer"&gt;Michael Dziedzic&lt;/a&gt;
&lt;/h6&gt;

</description>
      <category>javascript</category>
      <category>prolog</category>
    </item>
  </channel>
</rss>
