<?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: Preet Shihn</title>
    <description>The latest articles on DEV Community by Preet Shihn (@shihn).</description>
    <link>https://dev.to/shihn</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%2F67854%2Faa2e6a48-1562-4d5c-a84f-ef89aedd05fd.png</url>
      <title>DEV Community: Preet Shihn</title>
      <link>https://dev.to/shihn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shihn"/>
    <language>en</language>
    <item>
      <title>Autoplaying back-to-back videos on the web using a Media Pool</title>
      <dc:creator>Preet Shihn</dc:creator>
      <pubDate>Fri, 14 Aug 2020 18:09:19 +0000</pubDate>
      <link>https://dev.to/shihn/autoplaying-back-to-back-videos-on-the-web-using-a-media-pool-c6n</link>
      <guid>https://dev.to/shihn/autoplaying-back-to-back-videos-on-the-web-using-a-media-pool-c6n</guid>
      <description>&lt;p&gt;No one likes it when you go to a web page and it automatically starts playing a video loudly. Browsers have changed their auto-play policies to let JavaScript auto-play a video only if it's inline and muted. (See posts for &lt;a href="https://webkit.org/blog/6784/new-video-policies-for-ios/"&gt;Safari&lt;/a&gt; and &lt;a href="https://developers.google.com/web/updates/2017/09/autoplay-policy-changes"&gt;Chrome&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FHrT_Ow_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/imrloyodfrcdudeonwe4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FHrT_Ow_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/imrloyodfrcdudeonwe4.jpg" alt="Meme saying: One does not simply autoplay videos, and I will find you and I will pause you"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem: Playing a video queue
&lt;/h2&gt;

&lt;p&gt;This change in policy is great, but it may restrict some use cases. Say, you have created a queue of videos (or audios). You'd want the next one to play as soon as the first one finishes. Instagram/Snapchat like stories is a good example for this. &lt;/p&gt;

&lt;p&gt;Normally one would implement this by listening to your video's progress and as soon as it ends, call &lt;code&gt;play&lt;/code&gt; on the next video. But, if the video is not muted, it will not play according to the browser's media policy. &lt;/p&gt;

&lt;p&gt;Unmuted videos can be played if they were triggered by a user action. But, when playing one video after another, asking the user to tap to play again doesn't feel like a great user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reusing the media element
&lt;/h2&gt;

&lt;p&gt;Once a media element (&lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;audio&amp;gt;&lt;/code&gt;) has been triggered by a user action, it gets &lt;strong&gt;cleared&lt;/strong&gt; by the browser for future use. i.e. Later on, some script can play the video unmuted.&lt;/p&gt;

&lt;p&gt;With that in mind, the very basic solution is to create a single media element, and re-use it for every video. This, however, may not be a great user experience. Loading the next video may take time, so transitioning from one video to another will not be a smooth one. &lt;/p&gt;

&lt;h2&gt;
  
  
  Media Pool
&lt;/h2&gt;

&lt;p&gt;In an ideal world where resources and browser limitations do not exist, one could load every video in memory. But it's not good practice, and some browsers (like iOS Safari) limit the number of media elements in memory. &lt;/p&gt;

&lt;p&gt;So we create a &lt;strong&gt;Media Pool&lt;/strong&gt;. This is similar to &lt;em&gt;thread pools&lt;/em&gt; in multi-threaded languages where you allocate a thread to a task and when the task is done, the thread is released to be used by another task. &lt;/p&gt;

&lt;p&gt;Applying this model to media elements, we can keep a few videos in memory for a smooth experience, and release them back to the pool when they are done playing. As new videos get queued up to play, they request a media element from the pool. The pool will provide an unused or a recycled media element. &lt;/p&gt;

&lt;p&gt;In the following diagram, we have a pool of seven media elements &lt;span&gt;♦&lt;/span&gt;. We keep the last video in memory, and preload the next one. So there are only 3 allocated media elements at a time. As the videos leave this three-video-window, the media element is released back into the pool.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TBOeSeEu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0x4mfe3po37vayg797xq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TBOeSeEu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0x4mfe3po37vayg797xq.png" alt="Diagram showing 3 allocated media elements in a media pool"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When video-3 finishes, video-4 starts playing. video-2 is outside the window so it releases the media element back into the queue. video5 gets a new element allocated from the queue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oRLGiPwD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ex43nrwnc1y099mesren.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oRLGiPwD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ex43nrwnc1y099mesren.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Blessing the Media
&lt;/h2&gt;

&lt;p&gt;A media pool sounds like a great way to reuse video elements but we have not addressed the original problem - playing unmuted videos automatically. I discovered that Google's AMP project had the &lt;a href="https://github.com/ampproject/amphtml/blob/master/extensions/amp-story/1.0/media-pool.md"&gt;same problem&lt;/a&gt; as this, and they use a term called &lt;em&gt;&lt;strong&gt;blessing&lt;/strong&gt;&lt;/em&gt; a video element. &lt;/p&gt;

&lt;p&gt;When the user takes their first action to unmute a video or to start an unmuted video; in the same event handler, the media-pool will &lt;em&gt;unmute&lt;/em&gt; all the videos in the pool (allocated, unallocated, and released ones). It will then mute the ones that are not active right away. By doing this, all videos have been &lt;strong&gt;cleared&lt;/strong&gt; by the browser. If we use AMP's terminology, these videos have now been &lt;em&gt;&lt;strong&gt;blessed&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V7hlPej2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bqlb5htxpqmjkpolzqas.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V7hlPej2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bqlb5htxpqmjkpolzqas.png" alt="How to bless a video"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As one video finishes, the script can now call &lt;code&gt;play&lt;/code&gt; on a blessed video element to start playing it even when it's unmuted. &lt;/p&gt;

&lt;p&gt;There are a couple of things to keep in mind when implementing a &lt;em&gt;blessing&lt;/em&gt; based media pool. Firstly, one cannot invoke operations like &lt;code&gt;mute&lt;/code&gt;, &lt;code&gt;unmute&lt;/code&gt;, &lt;code&gt;play&lt;/code&gt; on a media element if it doesn't have any media loaded. That's why the unallocated media-elements should be loaded with an empty video file. Secondly, in some browsers operations of media elements can be interrupted when invoked in a certain way, for example calling &lt;code&gt;load&lt;/code&gt; after calling &lt;code&gt;play&lt;/code&gt; can reject the &lt;code&gt;play&lt;/code&gt; promise. The AMP project creates a queue of operations per media element. I decided to do the same in my case. &lt;/p&gt;

&lt;h2&gt;
  
  
  Media Pool implementation
&lt;/h2&gt;

&lt;p&gt;I have created a small framework independent &lt;a href="https://github.com/pshihn/media-pool"&gt;media-pool implementation&lt;/a&gt; that you can use if you like, or feel free to look at the code to create a new one. AMP's version of media pool is &lt;a href="https://github.com/ampproject/amphtml/blob/master/extensions/amp-story/1.0/media-pool.js"&gt;available here&lt;/a&gt; but it may be a bit AMP specific. &lt;/p&gt;

&lt;p&gt;I have further optimized my &lt;a href="https://github.com/pshihn/media-pool"&gt;media-pool implementation&lt;/a&gt; so it lazy-releases a media-element; which means if the video is active again it can reuse its old media-element even though it was released. This prevents re-attaching to DOM and re-loading videos. In the case where the released media-element has been allocated to some other video player, the video player will get a new one from the pool. &lt;/p&gt;

</description>
      <category>media</category>
      <category>video</category>
      <category>autoplay</category>
    </item>
    <item>
      <title>Need for Seed: Taming Randomness in a Pseudorandom World</title>
      <dc:creator>Preet Shihn</dc:creator>
      <pubDate>Tue, 19 May 2020 20:39:54 +0000</pubDate>
      <link>https://dev.to/shihn/need-for-seed-taming-randomness-in-a-pseudorandom-world-4e66</link>
      <guid>https://dev.to/shihn/need-for-seed-taming-randomness-in-a-pseudorandom-world-4e66</guid>
      <description>&lt;p&gt;Computers are inherently not good at randomness. The thing is, you can program a machine to generate numbers which may be considered random, but the machine is at the mercy of its programming. You cannot really call something truly random if it follows an algorithm to generate the random numbers.&lt;/p&gt;

&lt;p&gt;Truly random numbers can be generated but they usually rely on unpredictable physical processes which are not defined by man-made patterns, e.g. based on thermal noise or nuclear decay of a particle. &lt;a href="https://www.random.org/"&gt;Random.org&lt;/a&gt;, for example, generates true random numbers from atmospheric noise. These are used in casino games, and lotteries to make them unpredictable. &lt;/p&gt;

&lt;h2&gt;
  
  
  Pseudorandom numbers
&lt;/h2&gt;

&lt;p&gt;Programming languages and libraries provide procedures to generate what we call &lt;em&gt;pseudorandom numbers&lt;/em&gt;. These algorithms generate a sequence of numbers approximating a truly random sequence. For most applications, these pseudorandom number generators (&lt;strong&gt;PRNGs&lt;/strong&gt;) are good enough. &lt;/p&gt;

&lt;p&gt;Typically, a PRNG would start with a &lt;strong&gt;&lt;em&gt;seed&lt;/em&gt;&lt;/strong&gt; — a number that forms the starting point of the random sequence, and subsequent numbers are generated from there. So if you always start from the same seed, you will always get the same sequence of numbers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Auto seeding pseudorandom number generators
&lt;/h2&gt;

&lt;p&gt;Most libraries and languages will provide an interface for you to specify the seed to generate a sequence, but they will usually default to automatically selecting a seed.&lt;/p&gt;

&lt;p&gt;JavaScript for example, does not let you specify a seed for &lt;code&gt;Math.random()&lt;/code&gt; and &lt;code&gt;crypto.getRandomValues()&lt;/code&gt;. Each invocation of any of these methods produces a fresh unpredictable random number which is not reproducible across runs. This is great, right? Yes, but there are cases where controlling the seed is desirable. &lt;/p&gt;

&lt;h2&gt;
  
  
  Need for Seed 🏎
&lt;/h2&gt;

&lt;p&gt;Being able to specify a seed for a PRNG has several use cases, but they could be generally described as cases where the &lt;em&gt;state&lt;/em&gt; is tied to the random sequence. Here are some examples: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A generated graphics object or a data structure. There may be several cases where the object instance needs to be recreated (or repainted in the graphics world). You want the object to be the same every time the function is invoked for that instance. e.g. Consider this sketchy circle which is generated using a set or random points. If this instance of the circle is drawn on a canvas &lt;code&gt;n&lt;/code&gt; times, each rendering should look the same. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UU3b9yPS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hr73tbaj8um15t7sswer.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UU3b9yPS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hr73tbaj8um15t7sswer.png" alt="Sketchy circle"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Simulations &amp;amp; Testing frameworks — sometimes you want to replicate a test in different environments and you may want to replicate the exact test run in those environments. Same goes for simulations - simulating certain physics systems or processes repeatedly. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Gaming — The environment in a game (world/scene) is often generated with some randomness, be it terrain artifacts or locations of hidden gems. When a player returns to a game after saving it, you would want the generated world to be the same as when they left it. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Seeding in JavaScript
&lt;/h3&gt;

&lt;p&gt;When the language or the API does not give you a way to seed your random numbers, as in JavaScript, you need to create your own PRNG. There are many out there. Here's a very simple one, even though it may not be the best one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;SeededRandom&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;31&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="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;imul&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;48271&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;31&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;// To create a random seed:&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createNewSeed&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;31&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;There's a &lt;a href="https://github.com/tc39/proposal-seeded-random"&gt;TC39&lt;/a&gt; proposal to add seed based random number generation in JavaScript, but there doesn't seem to be much activity going on 🙁&lt;/p&gt;

&lt;h2&gt;
  
  
  Things to consider when using seeds
&lt;/h2&gt;

&lt;p&gt;When seeding, you are usually creating some artifacts using the generated random numbers. &lt;br&gt;
These artifacts should be the same for the same seed value. &lt;/p&gt;

&lt;h2&gt;
  
  
  Maintain the order
&lt;/h2&gt;

&lt;p&gt;Let's say you need to create three artifacts from a seed: &lt;code&gt;A&lt;/code&gt;, &lt;code&gt;B&lt;/code&gt;, &lt;code&gt;C&lt;/code&gt; and each requires two random numbers. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tPOXZZcy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/p3njp7mejqopfdmxfedw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tPOXZZcy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/p3njp7mejqopfdmxfedw.png" alt="random sequence in order"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The sequence of numbers will always be deterministic, so if the artifacts are generated in a different order, you will not maintain the consistency you need.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wqVB5Dna--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ojg9mk9vwabymsd5kf3o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wqVB5Dna--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ojg9mk9vwabymsd5kf3o.png" alt="random sequence out of order"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Constant bits and Dynamic bits
&lt;/h2&gt;

&lt;p&gt;There are times when you use a seed to create an object, but the next time around you may want the same object but with slightly different attributes. This may sound vague, so let's look at a specific example: You use random points to create the edges of a polygon and fill the polygon with more random lines. Now you want to scale this shape up. When doing so, you can use the same seed to maintain the general shape of the polygon; but to maintain the density of the filled lines, you need more lines. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5iM_GRkQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rjl1ow6f29ii1jk1zp9x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5iM_GRkQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rjl1ow6f29ii1jk1zp9x.png" alt="random square"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The simple rule here is to figure out which bits of your object remain constant, and which ones don't. &lt;strong&gt;Always create the constant ones first&lt;/strong&gt; so you always use the same sequence of numbers for the constant bits. This scenario is not specific to graphic shapes of course. &lt;/p&gt;

&lt;p&gt;Back to the polygon example, consider a sequence of random numbers for a specified seed &lt;code&gt;N1, N2, N3, ....&lt;/code&gt;. Say you need &lt;code&gt;k&lt;/code&gt; random numbers to draw the outline of the shape. Then you use more numbers unti &lt;code&gt;Nl&lt;/code&gt; to fill the shape.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3W9QURmz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zt8iloty5v3b09n1tpfm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3W9QURmz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zt8iloty5v3b09n1tpfm.png" alt="Ordered shape sized l"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you scale this shape up, the value of &lt;code&gt;k&lt;/code&gt; remains constant, and you may now have to go upto &lt;code&gt;Nm&lt;/code&gt; to fill the larger shape. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R57HbFGk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5mzngyxfmg203ndl8p9c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R57HbFGk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5mzngyxfmg203ndl8p9c.png" alt="Ordered shape sized m"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sub-seeding
&lt;/h2&gt;

&lt;p&gt;Consider an object that needs to maintain two parallel sets of artifacts. &lt;code&gt;A1, B1, C1&lt;/code&gt; and &lt;code&gt;A2, B2, C2&lt;/code&gt;, each artifact requiring a random number. These can be generated in two ways. &lt;code&gt;A1, A2, B1, B2, C1, C2&lt;/code&gt; (interleaved method) or one segment at a time &lt;code&gt;A1, B1, C1, A2, B2, C2&lt;/code&gt; (sequential method). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f6wFeCFP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/80r3iwwo09ardcb6wi4a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f6wFeCFP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/80r3iwwo09ardcb6wi4a.png" alt="interleaved methods"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LVmpuE6O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ca3x6y1r8fy61qj2j4pd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LVmpuE6O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ca3x6y1r8fy61qj2j4pd.png" alt="sequential method"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both these methods will generate the same object every time because the assignment of the random numbers is fixed. But let's say you want to add a fourth artifact while maintaining the values of the previous artifacts. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--md7iQXjD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nvyntm50pv76kbcgly4p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--md7iQXjD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nvyntm50pv76kbcgly4p.png" alt="interleaved methods"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n8Bd-Mfp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/l6j69bmiq9fnl0abq1qk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n8Bd-Mfp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/l6j69bmiq9fnl0abq1qk.png" alt="sequential method"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Only the first method of interleaving parallel artifacts maintains the values of &lt;code&gt;A, B, C&lt;/code&gt; when &lt;code&gt;D&lt;/code&gt; is added. (&lt;em&gt;More specifically, notice that &lt;code&gt;A2&lt;/code&gt; is always associated with &lt;code&gt;n2&lt;/code&gt; in the interleaved method, and gets associated with &lt;code&gt;n4&lt;/code&gt;  or &lt;code&gt;n5&lt;/code&gt; in the sequential method&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;So you might say, always interleave in situations like this. Which is great, but there are cases where it may not be possible. Limitations of the design may lead to situations where computing &lt;code&gt;A2&lt;/code&gt; may not be possible before computing &lt;code&gt;A1, B1, C1, D1&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;One strategy for dealing with this is creating a new seed that is a deterministic value derived from the original seed. I'm going to call this method &lt;strong&gt;&lt;em&gt;sub-seeding&lt;/em&gt;&lt;/strong&gt;. With this new sub-seed, you create a new sequence of numbers that is still determined by the original seed. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PsscR-ki--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/b5zgj30pzx8j67fz6qeu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PsscR-ki--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/b5zgj30pzx8j67fz6qeu.png" alt="sub-seed method"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Creating a sub-seed could be a very simple function, e.g. &lt;code&gt;subSeed = seed + 1&lt;/code&gt;. Now you have two independent sequences of numbers determined by a single seed associated with the object. &lt;/p&gt;

</description>
      <category>randomness</category>
      <category>randomnumbers</category>
    </item>
    <item>
      <title>Announcing Wired-Elements 2.0</title>
      <dc:creator>Preet Shihn</dc:creator>
      <pubDate>Thu, 24 Oct 2019 20:36:55 +0000</pubDate>
      <link>https://dev.to/shihn/announcing-wired-elements-2-0-432i</link>
      <guid>https://dev.to/shihn/announcing-wired-elements-2-0-432i</guid>
      <description>&lt;p&gt;I'm happy to announce the 2.0 release of &lt;a href="https://wiredjs.com/" rel="noopener noreferrer"&gt;wired-elements&lt;/a&gt;. It started of, and still is, a fun project to work on. In this era of really slick and buttery smooth design systems, a brutal and rough beacon of light 😉&lt;/p&gt;

&lt;p&gt;In this release, the underlying base code for all components was refactored to create smaller and more efficient components. By more efficient, I mean fewer re-renders of the sketchy shapes. This was done mainly by not re-rendering shapes if the dimensions do not change, and also by utilizing the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver" rel="noopener noreferrer"&gt;Resize Observer&lt;/a&gt; where it's available.&lt;/p&gt;

&lt;p&gt;View all components in action in the &lt;a href="https://wiredjs.com/showcase.html" rel="noopener noreferrer"&gt;wired-elements showcase&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;New components in 2.0 👇&lt;/p&gt;

&lt;h2&gt;
  
  
  wired-calendar
&lt;/h2&gt;

&lt;p&gt;This is the first fully community contributed component. &lt;a href="https://github.com/elingerojo" rel="noopener noreferrer"&gt;Eduardo Martinez&lt;/a&gt; created this. The calendar is customizable in many ways, for details check out the &lt;a href="https://github.com/wiredjs/wired-elements/tree/master/packages/wired-calendar" rel="noopener noreferrer"&gt;wired-calendar readme&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fshihn.ca%2Fstuff%2Fposts%2Fwire-elements-2%2Fcalendar.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fshihn.ca%2Fstuff%2Fposts%2Fwire-elements-2%2Fcalendar.jpg" alt="wired-calendar example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  wired-video
&lt;/h2&gt;

&lt;p&gt;A simple video player that shows a sketchy progress and hand-drawn controls for play/pause and volume. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7r4k4opuhw36xjtbt9p9.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7r4k4opuhw36xjtbt9p9.png" alt="wired-video example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  wired-image
&lt;/h2&gt;

&lt;p&gt;An image component akin the the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag, but it frames the image in a hand-drawn box. The elevation of the box is configurable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fshihn.ca%2Fstuff%2Fposts%2Fwire-elements-2%2Fimage.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fshihn.ca%2Fstuff%2Fposts%2Fwire-elements-2%2Fimage.jpg" alt="wired-image example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  wired-dialog
&lt;/h2&gt;

&lt;p&gt;A modal dialog implementation. This contents of the dialog look like paper cutouts around a hand drawn box.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fht00p9a0mn01diahmayr.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fht00p9a0mn01diahmayr.png" alt="wired-dialog example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  wired-divider
&lt;/h2&gt;

&lt;p&gt;A hand-drawn horizontal line that can be used to divide two sections.&lt;/p&gt;

&lt;h2&gt;
  
  
  wired-link
&lt;/h2&gt;

&lt;p&gt;Akin to &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag, a link with href, and a sketchy underline.&lt;/p&gt;

&lt;h2&gt;
  
  
  wired-search
&lt;/h2&gt;

&lt;p&gt;A search input control&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fnkug8vg345rqw2ufwseo.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fnkug8vg345rqw2ufwseo.png" alt="wired-search example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  MORE
&lt;/h2&gt;

&lt;p&gt;Try wired-elements out on &lt;a href="https://glitch.com/edit/#!/wired-elements-vanilla" rel="noopener noreferrer"&gt;Glitch playground&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Checkout &lt;a href="https://wiredjs.com/" rel="noopener noreferrer"&gt;wiredjs.com&lt;/a&gt; for more.&lt;/p&gt;

</description>
      <category>sketchy</category>
      <category>handdrawn</category>
      <category>webcomponents</category>
    </item>
    <item>
      <title>Why I use Web Components - My use cases</title>
      <dc:creator>Preet Shihn</dc:creator>
      <pubDate>Fri, 21 Jun 2019 19:53:14 +0000</pubDate>
      <link>https://dev.to/shihn/why-i-use-web-components-my-use-cases-1nip</link>
      <guid>https://dev.to/shihn/why-i-use-web-components-my-use-cases-1nip</guid>
      <description>&lt;p&gt;First of all, I am not a blogger or advocate of any technology, or speak at events/conferences. So mind my first attempt at writing. I hope I am clear in expressing myself.&lt;/p&gt;

&lt;p&gt;I want to talk about some practical use cases and scenarios where I have found Web Components to be the best solution available.&lt;/p&gt;

&lt;p&gt;Whenever I have seen discourse on Web Components, it usually devolves to API design and comparison to frameworks. I will not defend the API as I did not write it. I will not criticize it, &lt;a href="https://dev.to/richharris/why-i-don-t-use-web-components-2cia"&gt;others have done a better job&lt;/a&gt; at it. &lt;/p&gt;

&lt;h2&gt;
  
  
  Solved Problem?
&lt;/h2&gt;

&lt;p&gt;It is often stated the components are a solved problem - look at all these frameworks with religious following!&lt;/p&gt;

&lt;p&gt;Now, if you're developing an app, say a book recommendation app - &lt;strong&gt;you should write this in any framework&lt;/strong&gt; you are comfortable with. Or write in only web components or write in HTML + Javascript circa 2000. All good. You should use whatever component system you want to, as long as it meets your goals.&lt;/p&gt;

&lt;p&gt;But, if you want to write a rich component that is truly shareable, there is no other model available. You cannot use React components in Svelte or Svelte modules in React or in Vue or in Nimbus3000.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Use Cases
&lt;/h2&gt;

&lt;p&gt;I'm going to talk about real scenarios where I think using WebComponents seems like the right choice. The central theme here is &lt;strong&gt;shareable&lt;/strong&gt; and &lt;strong&gt;cross-framework&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Embeddable Frontends (MicroFrontends?)
&lt;/h3&gt;

&lt;p&gt;I help lots of websites add engagement and all sorts of bells and whistles to their sites. These sites are not maintained by fancy developers - think bloggers, artists, content creators, small businesses. Some of them get huge amounts of traffic (100M pages per month). We have a data engine that scans and monitors data on their sites and feeds them to embeddable frontends that add engagement to sites. Some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real time search that is customized to the user&lt;/li&gt;
&lt;li&gt;Launch a dynamic game related to the content the user is interested in&lt;/li&gt;
&lt;li&gt;Infinite list of related content&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsbobvdgg7vwz9mq7qq4b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsbobvdgg7vwz9mq7qq4b.png" alt="Embeddable Frontend Example" width="800" height="674"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most of these sites are on WordPress, Squarespace, Framework rendered using React, Vue. Our frontends get injected as WebComponents.&lt;br&gt;
These publishers add the component wherever they want. No npm or fancy build process here.&lt;/p&gt;

&lt;p&gt;Being in a web component shields the content from whichever theme they are using or whichever other frameworks that are running on the system. Some of these components interact with other content on the host page. They have to be highly performant and small in size.&lt;/p&gt;

&lt;p&gt;These publishers usually have basic HTML knowledge and they add them to their content just like they would be adding images or videos. &lt;/p&gt;
&lt;h3&gt;
  
  
  2. Complex Widgets
&lt;/h3&gt;

&lt;p&gt;The above example was a very customized solution, but then there are developers who create general widgets.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/GoogleWebComponents/model-viewer" rel="noopener noreferrer"&gt;&lt;code&gt;&amp;lt;model-viewer&amp;gt;&lt;/code&gt;&lt;/a&gt; is a perfect example of this one. It's been used all over the place like in NASA, and Shopify. I have no clue what framework Shopify uses (and it's probably not the same as NASA), but with the model-viewer available as a Web Component, they had a solution.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1141363065901977601-189" src="https://platform.twitter.com/embed/Tweet.html?id=1141363065901977601"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1141363065901977601-189');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1141363065901977601&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Same applies to so called 'design systems'. &lt;a href="https://ionicframework.com/docs/components" rel="noopener noreferrer"&gt;Ionic's components&lt;/a&gt; for example, developed as Web Components and then also wrapped for different frameworks like React, Vue. &lt;/p&gt;

&lt;h3&gt;
  
  
  3. Evolving HTML
&lt;/h3&gt;

&lt;p&gt;HTML5 added all sorts of new tags to the spec like &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt;. Will it never add any new tags? One argument is that DOM sucks and all new elements should be defined a completely new component format. Or more realistically, it will probably add more tags - people know how to use tags already. &lt;/p&gt;

&lt;p&gt;One of the new tags being considered is a &lt;em&gt;switch&lt;/em&gt;. To test out possible implementations, Chrome is shipping it as web component &lt;code&gt;&amp;lt;std-switch&amp;gt;&lt;/code&gt;, because it essentially extends the built in elements. When not on Chrome, the web component could be loaded as a fallback module. Extending existing underlying element model has its values. &lt;/p&gt;

&lt;p&gt;Personal story in this category: A friend of mine in grad school was trying to use MathML on some web page. (They are NOT a developer.) Chrome does not support MathML at the moment. They could have used some sort of library to render it. I implemented &lt;a href="https://github.com/pshihn/math-ml" rel="noopener noreferrer"&gt;MathML as web components&lt;/a&gt; as a fun project, and they could use it in chrome with minimal changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl3chiqj1139tjjg913ry.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl3chiqj1139tjjg913ry.png" alt="MathML example" width="408" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Styling
&lt;/h2&gt;

&lt;p&gt;In some ways there is no such thing as Web Components in the platform. There are a few separate specs, like Custom Elements, and ShadowDom, being the main ones. More under development for importing CSS, HTML, JSON. &lt;/p&gt;

&lt;p&gt;All of these individual spec have merit on their own, and their own design flaws, in the eyes of the developer. These can be used individually without being all &lt;em&gt;web componenty&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Parts of the component that are not inside a ShadowDOM can be styled using your global stylesheet, where parts inside the ShadowDOM are isolated. This is particularly useful in the shareable component case which I focus on. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx6ep21g50tp9fpdnjjbk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx6ep21g50tp9fpdnjjbk.jpg" alt="Shadow DOM" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Developer Experience
&lt;/h2&gt;

&lt;p&gt;A common complaint people have with WCs is that they are too verbose to code. It doesn't have bindings, or whatever. Like I said earlier, I'm not going to debate the merits and faults of the existing API and DX. &lt;/p&gt;

&lt;p&gt;I do think that it is fair to use frameworks and libraries if you want to. I mean, you already do and you even &lt;em&gt;compile&lt;/em&gt; at times. Some believe they should use no external libs at all, and that is a fine goal to strive for. But the reality is that it is much easier for most devs to use libs. So stop comparing DOM api to a framework API which could be compiled to DOM api. I think helper libraries are excellent. We already use it for so many other web tech like Web RTC, Workers, etc. &lt;/p&gt;

&lt;p&gt;There are some great helper libs that will help you with WCs should you wish to. A few: &lt;a href="https://lit-element.polymer-project.org/" rel="noopener noreferrer"&gt;Lit Element&lt;/a&gt;, &lt;a href="https://stenciljs.com/" rel="noopener noreferrer"&gt;Stencil&lt;/a&gt;, &lt;a href="https://github.com/matthewp/haunted" rel="noopener noreferrer"&gt;Haunted&lt;/a&gt; if you like hooks.&lt;/p&gt;

&lt;p&gt;Example using LitElement:&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="nd"&gt;customElement&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-counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;LitElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;property&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="nb"&gt;Number&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;render&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;html&lt;/span&gt;&lt;span class="s2"&gt;`
      &amp;lt;div&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/div&amp;gt;
      &amp;lt;button @click="&lt;/span&gt;&lt;span class="p"&gt;${()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;count&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;Increment&amp;lt;/button&amp;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example using Haunted:&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;function&lt;/span&gt; &lt;span class="nf"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`
      &amp;lt;div id="count"&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/div&amp;gt;
      &amp;lt;button type="button" @click=&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;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&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="s2"&gt;&amp;gt;Increment&amp;lt;/button&amp;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;customElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&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-counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Not your use case
&lt;/h2&gt;

&lt;p&gt;My use case is not your use case. This may all mean nothing to you, but I thought you may be interested in hearing about a point of view from a different plane. &lt;/p&gt;

</description>
      <category>html</category>
      <category>webcomponents</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
