<?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: Maroun Baydoun</title>
    <description>The latest articles on DEV Community by Maroun Baydoun (@maroun_baydoun).</description>
    <link>https://dev.to/maroun_baydoun</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%2F11496%2Fe75fd70e-c6cc-4dbf-9963-15191009b9c0.jpg</url>
      <title>DEV Community: Maroun Baydoun</title>
      <link>https://dev.to/maroun_baydoun</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maroun_baydoun"/>
    <language>en</language>
    <item>
      <title>Migrating a React codebase to web components</title>
      <dc:creator>Maroun Baydoun</dc:creator>
      <pubDate>Mon, 02 Aug 2021 17:05:08 +0000</pubDate>
      <link>https://dev.to/maroun_baydoun/migrating-a-react-codebase-to-web-components-3d8m</link>
      <guid>https://dev.to/maroun_baydoun/migrating-a-react-codebase-to-web-components-3d8m</guid>
      <description>&lt;p&gt;I recently migrated a browser extension from React to web components. This post describes my observations, learnings and pain points. Anything mentioned applies to native web components only. Third-party libraries such as &lt;a href="https://stenciljs.com/" rel="noopener noreferrer"&gt;stencil&lt;/a&gt; and &lt;a href="https://lit.dev/" rel="noopener noreferrer"&gt;lit&lt;/a&gt; offer a different set of solutions. &lt;/p&gt;

&lt;h3&gt;
  
  
  What does the extension do?
&lt;/h3&gt;

&lt;p&gt;The extension controls the playback of Youtube™ videos from any tab in the browser. The user can assign shortcuts to play/pause videos even when the browser is in the background. &lt;/p&gt;

&lt;p&gt;You can &lt;a href="https://chrome.google.com/webstore/detail/youtube-controller/poalplpedjpddipkghmlhkmgbcnmecop" rel="noopener noreferrer"&gt;install the extension&lt;/a&gt; on Chrome and &lt;a href="https://github.com/maroun-baydoun/youtube-controller-extension" rel="noopener noreferrer"&gt;check the code&lt;/a&gt; on Github.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why did I migrate?
&lt;/h3&gt;

&lt;p&gt;The extension was originally written using vanilla JavaScript in 2015. As the codebase grew in complexity, it became difficult to maintain the UI. I wanted a tiny framework to help me organise the interface into components. I chose &lt;a href="https://github.com/jorgebucaran/hyperapp" rel="noopener noreferrer"&gt;hyperapp&lt;/a&gt; for its small bundle size and seemingly easy API. It wasn’t that straightforward to learn after all and the documentation was lacking at the time. &lt;/p&gt;

&lt;p&gt;A few months later, I migrated to React. I wanted a familiar library that I didn’t need to relearn from scratch. I was finally happy with the quality of the code. The more I thought about it, however, the more I realised I was over-engineering my solution. &lt;/p&gt;

&lt;p&gt;Do I really need to ship two rather large packages, &lt;code&gt;react&lt;/code&gt; and &lt;code&gt;react-dom&lt;/code&gt;? The answer was no, even though extensions are loaded locally and package size is not a major concern. The other problem was minification. While minified code is not prohibited, it could &lt;a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/What_next_#your_development_environment" rel="noopener noreferrer"&gt;delay the review process&lt;/a&gt; on some platforms. &lt;/p&gt;

&lt;p&gt;I needed a light-weight solution that doesn’t rely on external libraries. Enter web components.&lt;/p&gt;

&lt;h3&gt;
  
  
  Overview of web components
&lt;/h3&gt;

&lt;p&gt;Web components are a set of four standards that have very good &lt;a href="https://caniuse.com/?search=web%20components" rel="noopener noreferrer"&gt;browser support&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom HTML elements&lt;/li&gt;
&lt;li&gt;Shadow DOM&lt;/li&gt;
&lt;li&gt;Templates&lt;/li&gt;
&lt;li&gt;EJS modules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read more about the &lt;a href="https://www.webcomponents.org/specs" rel="noopener noreferrer"&gt;specs&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Comparing web components to React
&lt;/h3&gt;

&lt;p&gt;The following is a list of things I’ve learned during the migration.&lt;/p&gt;

&lt;h4&gt;
  
  
  Custom elements are classes
&lt;/h4&gt;

&lt;p&gt;Since the release of hooks, I have completely stopped writing class components in React. Custom elements can only be declared as classes however. They have specific methods to hook (no pun intended) into the lifecycle of the element. In that sense, they are quite similar to class components in React. One of the biggest differences is the lack of a render method. &lt;/p&gt;

&lt;h4&gt;
  
  
  Back to imperative programming
&lt;/h4&gt;

&lt;p&gt;Building React components boils down to describing the end result and letting the library take care of the rest. This is done in the render method of class components or as the returned result of functional ones. Custom elements, on the other hand, require direct DOM manipulation to achieve the same result. DOM Elements are queried, created, inserted and modified. &lt;/p&gt;

&lt;p&gt;React:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CapitalisedText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="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;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Web components:&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;class&lt;/span&gt; &lt;span class="nc"&gt;CapitalisedText&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;connectedCallback&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;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&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;div&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createTextNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;div&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;h4&gt;
  
  
  No binding in templates
&lt;/h4&gt;

&lt;p&gt;Templates are not equivalent to the rendering blocks of React components. It is not possible to pass and render JavaScript data. Nor is it possible to run conditions or loops. All of that has to happen in the custom element lifecycle methods. &lt;/p&gt;

&lt;p&gt;A template defined in the document:&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;template&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"capitalised-text-template"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The web component consumes the template but has to do the necessary DOM updates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CapitalisedText&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;connectedCallback&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;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#capitalised-text-template&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&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;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cloneNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&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;div&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createTextNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&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;h4&gt;
  
  
  Out of the box css scoping
&lt;/h4&gt;

&lt;p&gt;Many solutions exist to scope css in React components. CSS modules, different CSS-in-JS libraries etc. Using the shadow dom in custom elements comes with out-of-the-box support for that. Styles defined in the custom element don’t leak out to the rest of the document, and styles declared elsewhere in the document don’t leak into the custom element. It is a powerful feature when writing reusable components but can be restrictive in other scenarios. It is always possible to write custom elements without shadow DOM however.&lt;/p&gt;

&lt;p&gt;Using &lt;a href="https://github.com/css-modules/css-modules" rel="noopener noreferrer"&gt;css modules&lt;/a&gt; with React to avoid style collisions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styles&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;./stlyle.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CapitalisedText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&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;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the shadow DOM in the web component to encapsulate styles:&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;template&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"capitalised-text-template"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="nc"&gt;.text&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;600&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CapitalisedText&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shadowRoot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attachShadow&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;open&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;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#capitalised-text-template&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;shadowRoot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&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;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cloneNode&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="nf"&gt;connectedCallback&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;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&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;div&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shadowRoot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createTextNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&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;h4&gt;
  
  
  Custom elements remain in the DOM tree
&lt;/h4&gt;

&lt;p&gt;When React renders a component, it creates and appends DOM elements. The component itself is nowhere to be seen in the DOM tree. Custom elements are part of the DOM tree. This is important to note when considering querying and styling. &lt;/p&gt;

&lt;p&gt;React:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feg246qnlvq61rf0308pu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feg246qnlvq61rf0308pu.png" alt="Structure of the dom elements of a React component"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Web component:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft35l5rkybcn1tdgy356a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft35l5rkybcn1tdgy356a.png" alt="Structure of the dom elements of a web component"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Attributes vs. properties
&lt;/h4&gt;

&lt;p&gt;React components have props that can be of any data type. Custom elements, like any built-in html element, have attributes that can only contain strings. They also have properties that can contain any data type but can only be set using JavaScript. Learn more about &lt;a href="https://open-wc.org/guides/knowledge/attributes-and-properties/" rel="noopener noreferrer"&gt;attributes and properties&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Listening to attribute changes is opt-in
&lt;/h4&gt;

&lt;p&gt;A react component re-renders when prop values change. Web components expose the &lt;code&gt;attributeChangedCallback&lt;/code&gt; that can be used to update the UI in response to changes in attributes. This callback doesn’t fire by default however. Every web component has to explicitly list the attributes it wants to listen to using the &lt;code&gt;observedAttributes&lt;/code&gt; static method.&lt;/p&gt;

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

&lt;p&gt;Conclusion&lt;br&gt;
Web components are surprisingly good at managing a code base using vanilla JavaScript. Some developers can perceive the current standards as bare-bones however. In fact, the term &lt;em&gt;components&lt;/em&gt; is somewhat misleading. It draws parallels with existing frameworks and libraries whose components have many more features.&lt;/p&gt;

&lt;p&gt;Overall, I'm satisfied with my decision to migrate to web components. I'll definitely use them again for other projects. &lt;/p&gt;

&lt;p&gt;What's your opinion on web components? Do you think they can replace tools such as React or Vue?&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Using media queries with JavaScript</title>
      <dc:creator>Maroun Baydoun</dc:creator>
      <pubDate>Tue, 30 Mar 2021 19:18:54 +0000</pubDate>
      <link>https://dev.to/maroun_baydoun/using-media-queries-with-javascript-4aeo</link>
      <guid>https://dev.to/maroun_baydoun/using-media-queries-with-javascript-4aeo</guid>
      <description>&lt;p&gt;Media queries are not limited to CSS. JavaScript can also react to them. This can be very useful when building applications.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;If you're looking for an existing solution for using media queries in JavaScript, checkout my small library &lt;a href="https://dev.maroun-baydoun.com/mediaq/"&gt;mediaq&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  The window.matchMedia API
&lt;/h1&gt;

&lt;p&gt;Browsers expose the &lt;a href=""&gt;window.matchMedia&lt;/a&gt; method. It takes a media query as an argument and returns a &lt;code&gt;MediaQueryList&lt;/code&gt; object.&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;mediaQueryList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matchMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;only screen and (max-width: 600px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Checking if a media query matches
&lt;/h1&gt;

&lt;p&gt;Once created, a &lt;code&gt;MediaQueryList&lt;/code&gt; object has the boolean property &lt;code&gt;matches&lt;/code&gt;. Use that property to check, at any time, if the media query is 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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mediaQueryList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;It matches!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;It doesn't match.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Listening for updates
&lt;/h1&gt;

&lt;p&gt;Instead of checking if the &lt;code&gt;MediaQueryList&lt;/code&gt; object matches, you can attach an event listener to it. The listener will trigger whenever the media query matches or stops matching (the window is resized, the device orientation changes etc.).&lt;/p&gt;

&lt;p&gt;Since &lt;code&gt;MediaQueryList&lt;/code&gt; inherits &lt;code&gt;EventTarget&lt;/code&gt;, listening to the events it fires is very straightforward.&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;listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;It matches!&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;It doesn't match.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;mediaQueryList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Removing a listener is also as easy&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;mediaQueryList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Internet explorer and Safari &amp;lt; 14 handle those event listeners  differently. They use &lt;code&gt;addListener&lt;/code&gt;/&lt;code&gt;removeListener&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;To support those browsers as well, you can conditionally call the correct method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;It matches!&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;It doesn't match.&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mediaQueryList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;mediaQueryList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;mediaQueryList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="c1"&gt;// For removal&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;mediaQueryList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;mediaQueryList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;mediaQueryList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;listener&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;You can read more about &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList#browser_compatibility"&gt;browser compatibility&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why use media queries with JavaScript?
&lt;/h1&gt;

&lt;p&gt;When applied through CSS, media queries help create responsive layouts. They also allow hiding certain elements on the web page and loading higher/lower resolution background pictures. &lt;/p&gt;

&lt;p&gt;In some scenarios that is not enough. That's when JavaScript can be used to optimize the webpage further. &lt;/p&gt;

&lt;p&gt;Imagine a component of your webpage is computationally heavy and you decide you don't need it to display on smaller screens. In CSS, you can easily hide it, but it would still exist as part of your DOM and could still weigh down the performance of your web application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;480px&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nc"&gt;.component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* The component is hidden but is still part of the webpage.*/&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In JavaScript, on the other hand, you could decide whether or not to append the element to the document.&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;mediaQueryList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matchMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;only screen and (max-width: 480px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;mediaQueryList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matches&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/Append the element here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Another use case is loading certain scripts for certain screen sizes. If you application uses large graphing libraries, you can choose to include them only on desktop-size devices, where the graphs are being displayed.&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;mediaQueryList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matchMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;only screen and (min-width: 768px&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;mediaQueryList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matches&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;script&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;script&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path to JavaScript script&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;script&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;JavaScript can detect &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Screen"&gt;screen resolution&lt;/a&gt; without using media queries. This can work for one-time checks. Listening to updates with the &lt;code&gt;resize&lt;/code&gt; event on the window object can be expensive. Using media queries is much more efficient.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>css</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>What Github commits get wrong</title>
      <dc:creator>Maroun Baydoun</dc:creator>
      <pubDate>Thu, 18 Mar 2021 22:08:35 +0000</pubDate>
      <link>https://dev.to/maroun_baydoun/what-github-commits-get-wrong-ibf</link>
      <guid>https://dev.to/maroun_baydoun/what-github-commits-get-wrong-ibf</guid>
      <description>&lt;p&gt;If you see this UI, what would you expect to happen when you click the username and profile picture respectively? &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uO_q6p3f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a3pddva127yk932ntj09.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uO_q6p3f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a3pddva127yk932ntj09.png" alt="Github commit example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd expect to be shown the user profile in both cases. If not, then at least I'd expect those two elements to behave similarly. &lt;/p&gt;

&lt;p&gt;It turns out that clicking on the profile picture leads to the user's profile. While clicking on the username shows all commits by that user.&lt;/p&gt;

&lt;p&gt;To be fair, hovering the profile picture brings up a short preview of the user's profile.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GK27ck5P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gr9s1am8y3ollvnmq1sm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GK27ck5P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gr9s1am8y3ollvnmq1sm.png" alt="Github commit example with user profile"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hovering the username displays a helpful tooltip.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FrnXutWX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ypg02rxrerjweokcjzn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FrnXutWX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ypg02rxrerjweokcjzn.png" alt="Github commit example with tooltip"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, that doesn't justify using two different patterns for two UI elements that are so closely related. &lt;/p&gt;

&lt;p&gt;What do you think? Do you find it difficult to tell the difference? And how would you have designed it differently? &lt;/p&gt;

</description>
      <category>github</category>
      <category>design</category>
    </item>
    <item>
      <title>Scrum is not for humans</title>
      <dc:creator>Maroun Baydoun</dc:creator>
      <pubDate>Thu, 20 Aug 2020 18:59:33 +0000</pubDate>
      <link>https://dev.to/maroun_baydoun/scrum-is-not-for-humans-f7c</link>
      <guid>https://dev.to/maroun_baydoun/scrum-is-not-for-humans-f7c</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post was originally published on my &lt;a href="https://maroun-baydoun.com/blog/scrum-is-not-for-humans/"&gt;blog&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not a single workday goes by without hearing people praising the virtues of Agile. For many, Agile became synonymous with Scrum. In this article, I argue that Scrum is very hostile to developers. More generally, I will explain why Scrum is not designed for humans.&lt;/p&gt;

&lt;p&gt;I'm not planning on explaining what Scrum is. There are numerous resources that could do that better. The &lt;a href="https://www.scrumguides.org/"&gt;Scrum guide&lt;/a&gt; is a good place to start. In a nutshell, Scrum is a framework for product development with its sets of roles, artifacts and ceremonies. No, I’m not talking about a cult or a secret society. I’m talking about something that has become at the core of many people's work life.&lt;/p&gt;

&lt;h4&gt;
  
  
  Scrum is anti-developer
&lt;/h4&gt;

&lt;p&gt;In his book &lt;a href="https://daedtech.com/developer-hegemony-the-crazy-idea-that-software-developers-should-run-software-development/"&gt;Developer Hegemony&lt;/a&gt;, Erik Dietrich makes a very interesting observation. He notes that developers are a hot commodity nowadays. Companies are willing to shell high salaries and incentive packages to recruit the best talent. However, once those developers join a company, they are faced with impediments that stop them from reaching their true potential. Mountains of bureaucracy, layers of management and interfering with their daily work are just a few examples of that. Dietrich imagines a future where developers flip the table and take back control. We are not talking communist revolution and seizing the means of production. We are talking about being in charge of their destiny and actually delivering their full potential.&lt;/p&gt;

&lt;p&gt;Scrum is yet another red tape thrown at developers. Instead of allowing developers to self-organise, someone high in their lofty tower decides how the team should be working. Funny enough, the Agile bug seems to only infect developers. The remaining parts of the organisation are unphased. The same people forcing Scrum down developer’s throats would not be even there if the organisation were truly agile.&lt;/p&gt;

&lt;p&gt;I dislike Scrum because it makes a few wrong assumptions. First, that developers are lazy and need to be micro-managed to deliver. While many developers can be underperforming, putting them under the spotlight will only make the problem worse. Second, that the process of software creation is indistinguishable from any industrial manufacturing process. Claiming that uncertainty and unpredictability are not inherent parts of software engineering is as good as relying on the planets' positions to determine one’s destiny.&lt;/p&gt;

&lt;p&gt;It is true that not all developers are exemplary employees, but more often than not they want to give their best and be proud about the products they deliver. When things go wrong in the development team, people are quick to jump to the conclusion that developers have to be micromanaged to extract every ounce of productivity from them. However, the problem is often somewhere else in the chain.&lt;/p&gt;

&lt;h4&gt;
  
  
  A game of poker
&lt;/h4&gt;

&lt;p&gt;Scrum advocates estimation as a way of managing the team's workload. At first glance, that seems to be a very developer-friendly measure. Who wouldn't want to achieve a constant pace of delivery that keeps the users happy and saves the development team from burndown?&lt;br&gt;
In practice though, estimations end up being yet another pressure mechanism.&lt;/p&gt;

&lt;p&gt;Humans work in different ways, at different speeds and at different times. The myth of a constant pace of delivery does not reflect the reality of working in software development. Developers have good days and bad days. They exist outside the realm of their roles at work. They get sick, go on holidays, lose motivation etc.&lt;/p&gt;

&lt;p&gt;Uncertainty and unpredictability are hallmarks of software creation. That by itself is enough to invalidate the need for estimations. Pushing them on a team is a game of dishonesty and lack of trust. Everybody involved knows that those numbers carry little value. The time wasted making predictions and false promises should be used to bring real value to users instead.&lt;/p&gt;

&lt;p&gt;Developers are not stupid. When they can't change the system, they start to game it. They will use estimations to advance their own agenda. They will overestimate and deliver less. They will underestimate to make sure something they feel passionate about is picked up for development.&lt;/p&gt;

&lt;h4&gt;
  
  
  What do you stand for?
&lt;/h4&gt;

&lt;p&gt;The Scrum guide defines the daily stand-up as a short meeting for the development team to discuss their progress and impediments. In theory, I see some value in that. However, it makes the misinformed assumption that a team needs a specific ceremony to talk. In practice, team mates should and do exchange ideas all the time.&lt;/p&gt;

&lt;p&gt;What happens more often than not is the liberal reinterpretation of the daily stand-up. Managers and product owners attend and turn this ceremony into a status update meeting. Developers are &lt;del&gt;forced&lt;/del&gt; encouraged to share the teeny tiny details of their work with people who probably have little knowledge of and no interest in what is being said.&lt;/p&gt;

&lt;p&gt;Worse still, many companies use the daily stand-up as a sneaky way to get everyone in the office by a certain hour. This hinders any prospects for flexible working hours or remote work. Attending the daily stand-up becomes the number one reason why people show up at work, not the work itself.&lt;/p&gt;

&lt;h4&gt;
  
  
  Build it and they'll come
&lt;/h4&gt;

&lt;p&gt;Scrum is a great masquerade for agility. True agility requires no ceremonies and no artifacts. True agility is a cross-organisation mindset that doesn’t apply to the development team only.&lt;/p&gt;

&lt;p&gt;By adopting Scrum and following its guide, either to the letter or not, people believe they will magically become agile. The belief is that a time-delimited sprint ensures the ability to change course. That having retrospective meetings will enable the team to iron out issues in their process. That estimating and measuring the team’s velocity will make people more productive. In reality, none of that is true.&lt;/p&gt;

&lt;p&gt;Scrum has become a perfect example of cargo cult agile. Everyone is waiting for the benefits to come raining down. In reality, the sky is blue with no clouds in sight even though the team has been doing its rain dance for weeks.&lt;/p&gt;

&lt;p&gt;Scrum often hides the fact that true impediments are not in the development team itself, but further up in the hierarchy. The “follow the Scrum guide” commandment is a great mirror and smoke show for denying true change elsewhere in the organisation. The narrative is often flipped to suggest that the team problems stem from not applying Scrum strictly enough, for being too lenient in estimations and too ineffective in their retrospective. They are encouraged to dive deeper into Scrum while the rest of the organisation remains unchanged.&lt;/p&gt;

&lt;h4&gt;
  
  
  Going clear
&lt;/h4&gt;

&lt;p&gt;Some teams can and will use Scrum. A prepackaged workflow could work under certain circumstances, but it achieves nothing in terms of agility. Agility is the antithesis of process and ceremonies. Agility is giving a development team trust to self-organise. Agility transcends all layers of an organisation. In fact, a truly agile organisation does away with most of its layers.&lt;/p&gt;

&lt;p&gt;Be careful anytime you buy into a methodology with inflated claims, rigid rules and unintuitive workflows. An ecosystem backed by certifications and “coaches” will create a feedback loop that perpetuates its shortcomings and hinders true progress.&lt;/p&gt;

&lt;p&gt;Any team can and should decide its own workflow. Processes are discovered, adopted and improved along the way. If you are a developer, make sure you are part of that conversation. By deferring those decisions to the “wise” men and women of the organisation, you give up the agency to determine your own fate. Any process in place should be there to serve you and not the other way around.&lt;/p&gt;

</description>
      <category>agile</category>
      <category>career</category>
      <category>healthydebate</category>
    </item>
    <item>
      <title>Don't start with React</title>
      <dc:creator>Maroun Baydoun</dc:creator>
      <pubDate>Mon, 27 Jan 2020 22:12:53 +0000</pubDate>
      <link>https://dev.to/maroun_baydoun/don-t-start-with-react-11nm</link>
      <guid>https://dev.to/maroun_baydoun/don-t-start-with-react-11nm</guid>
      <description>&lt;p&gt;If you are getting started in web development, it is tempting to learn the most used technologies early on. More and more junior developers are investing in React through self learning or coding bootcamps. &lt;/p&gt;

&lt;h4&gt;
  
  
  The problem?
&lt;/h4&gt;

&lt;p&gt;While React is a great choice for building many types of applications, it is important to understand that there are alternatives. More crucially, React exists to solve a set of problems that developers face. Understand those problems first, and learn React next. &lt;/p&gt;

&lt;h4&gt;
  
  
  A little bit of history
&lt;/h4&gt;

&lt;p&gt;People doing web development from the mid 90s till the mid 2000s experienced the dominance of Internet Explorer, incompatibilities between browser engines, slow advancements in the web and a lack of good practices to organise code. &lt;/p&gt;

&lt;p&gt;Creating anything using JavaScript meant worrying about problems such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Having the DOM reflect the application's state.&lt;/li&gt;
&lt;li&gt;Organising the code and splitting it into different files.&lt;/li&gt;
&lt;li&gt;Adding and removing event listener.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Several solutions to these problems were introduced. jQuery made it easier to manipulate the DOM. RequireJs gave developers a way to break down applications into multiple files and load them in the browser. Tools such as Gulp, Grunt and later Webpack improved the build experience even further. Frameworks such as BackboneJs, Ember and later AngularJs offered a way to structure applications and organise the code.  &lt;/p&gt;

&lt;h4&gt;
  
  
  Enter React
&lt;/h4&gt;

&lt;p&gt;At first glance, React looks like a step backwards. React focuses on the View layer instead of embracing the full MVC architecture. Unlike its predecessors and some of its peers, React offers no out-of-the-box solutions for common needs such as routing, state management or styling. The distinction gives React the status of a library and not a framework.&lt;/p&gt;

&lt;h5&gt;
  
  
  So what problems is react solving?
&lt;/h5&gt;

&lt;h6&gt;
  
  
  Having the UI reflect the app state
&lt;/h6&gt;

&lt;p&gt;React’s goal is eliminating manual manipulation of the DOM. Instead of querying a certain node to update its attributes or children, you would describe the end result you want and React will take care of the rest.&lt;/p&gt;

&lt;p&gt;To achieve that, React dumps the common paradigm of separating HTML and JavaScript. Your JavaScript code is no longer there to manipulate the UI created by HTML. &lt;strong&gt;Your JavaScript IS THE UI&lt;/strong&gt;. (React still permits direct DOM manipulation using &lt;a href="https://reactjs.org/docs/refs-and-the-dom.html"&gt;refs&lt;/a&gt;)&lt;/p&gt;

&lt;h6&gt;
  
  
  DOM updates are expensive
&lt;/h6&gt;

&lt;p&gt;React makes updates to the DOM less expensive by comparing what the browser is rendering with what your UI is describing. This should improve the user experience in the browser. &lt;/p&gt;

&lt;h6&gt;
  
  
  Event management is messy
&lt;/h6&gt;

&lt;p&gt;React simplifies event management by adding a single event listener to the root of the document. This should reduce memory leaks introduced by complex event listeners in an application.  &lt;/p&gt;

&lt;h6&gt;
  
  
  Code is unorganised
&lt;/h6&gt;

&lt;p&gt;React offers a way to organise code by breaking it down into components. This encourages the application to be broken down into simple units respecting the &lt;a href="https://en.wikipedia.org/wiki/Single_responsibility_principle"&gt;single responsibility principle&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  The best of both worlds
&lt;/h4&gt;

&lt;p&gt;Understanding how the DOM works, its limitations and bottlenecks is an essential skill to create client-side web applications. Learning libraries and frameworks early on masks those complexities. It deprives you from understanding what is going on in the browser. &lt;/p&gt;

&lt;p&gt;Those libraries and frameworks are just syntaxic sugar around what the browser can natively do. It all boils down to what the JavaScript engine is doing and how the DOM is updated. This knowledge is essential to catch bugs and avoid performance issues. &lt;/p&gt;

&lt;p&gt;Learn how to create an application using nothing more than HTML, JavaScript and CSS. Feel the pain of managing state, events and DOM updates manually. Understand the common pitfalls, the performance bottlenecks and memory leaks. Transition to an MVC framework. Understand that your front-end code can be organised and architected. Pick an &lt;em&gt;old&lt;/em&gt; framework and give it a test drive. &lt;a href="https://backbonejs.org/"&gt;Backbone.JS&lt;/a&gt; is a great introduction to application frameworks. Finally, &lt;br&gt;
learn React.&lt;/p&gt;

&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;Don’t limit yourself to a certain library or framework. Eventually, the next big thing will come and sweep them off. Focus instead on what changes slowly. React will disappear but the browser will not. &lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>advice</category>
    </item>
  </channel>
</rss>
