<?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: Matt Levy</title>
    <description>The latest articles on DEV Community by Matt Levy (@ducksoupdev).</description>
    <link>https://dev.to/ducksoupdev</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%2F484213%2Fa3d4ff26-fcfc-43e7-8de0-97698da1141f.jpeg</url>
      <title>DEV Community: Matt Levy</title>
      <link>https://dev.to/ducksoupdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ducksoupdev"/>
    <language>en</language>
    <item>
      <title>Model web component behaviour with XState</title>
      <dc:creator>Matt Levy</dc:creator>
      <pubDate>Wed, 20 Jul 2022 14:42:40 +0000</pubDate>
      <link>https://dev.to/ficusjs/model-web-component-behaviour-with-xstate-2ll7</link>
      <guid>https://dev.to/ficusjs/model-web-component-behaviour-with-xstate-2ll7</guid>
      <description>&lt;p&gt;&lt;a href="https://xstate.js.org/" rel="noopener noreferrer"&gt;XState&lt;/a&gt; is a library for creating, interpreting, and executing finite state machines and statecharts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Finite-state_machine" rel="noopener noreferrer"&gt;Finite state machines&lt;/a&gt; (or 'state machines' for short) and &lt;a href="https://statecharts.dev/" rel="noopener noreferrer"&gt;statecharts&lt;/a&gt; are a visual language used to describe the states in a process. You may have used similar diagrams in the past to design user flows, plan databases or map application architecture. They are perfect for modelling web component behaviour.&lt;/p&gt;

&lt;p&gt;State machines and statecharts provide a visual way of using boxes and arrows to represent behaviour. These flows are also executable code that can be used to control the logic in your application and that makes it more predicable and testable.&lt;/p&gt;

&lt;p&gt;In this post, we're going to look at how to model behaviour in web components using state machines and statecharts in &lt;a href="https://docs.ficusjs.org/" rel="noopener noreferrer"&gt;FicusJS&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  State machines vs statecharts
&lt;/h2&gt;

&lt;p&gt;What is the difference between state machines and statecharts? Understanding state machines is almost the same as understanding statecharts. Statecharts are the “bigger brother” of state machines and is essentially a state machine that allows any state to include more machines, in a hierarchical fashion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of using state machines
&lt;/h2&gt;

&lt;p&gt;There are many benefits to using state machines or statecharts, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The behaviour (when things happen) is decoupled from the actual component (what happens).&lt;/li&gt;
&lt;li&gt;They produce lower bug counts than traditional code.&lt;/li&gt;
&lt;li&gt;As the complexity of your program grows, statecharts scale well.&lt;/li&gt;
&lt;li&gt;You explore all the possible states of your program.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Designing state machines
&lt;/h2&gt;

&lt;p&gt;The first step in designing state machines is to use a whiteboard or pen and paper and write down the possible states of the component you want to create. This is an important part of the process and should involve UX designers, product owners and developers. Talking through the behaviour of the component and writing down all the states helps to identify all the possibilities up-front.&lt;/p&gt;

&lt;p&gt;Once you have a list of identified states, create a &lt;a href="https://stately.ai/viz" rel="noopener noreferrer"&gt;visual state machine&lt;/a&gt; to check that the behaviour works. Using a visual tool helps all stakeholders to understand the state machine and the behaviour of the component.&lt;/p&gt;

&lt;h3&gt;
  
  
  An example
&lt;/h3&gt;

&lt;p&gt;We are going to create a visual depiction of a simple state machine. It is a model of a simple on/off switch.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy1qu9qrr6w584qyfppkg.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%2Fy1qu9qrr6w584qyfppkg.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To view the visual model and interact with it visit &lt;a href="https://stately.ai/viz/04fcf47e-df9f-4f78-b3b9-4826c24b2df9" rel="noopener noreferrer"&gt;https://stately.ai/viz/04fcf47e-df9f-4f78-b3b9-4826c24b2df9&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The visual model is a simulation which helps to refine the behaviour through defining the states and transitions of the state machine.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It consists of two states, “on” and “off”. This machine can therefore be in exactly one of the two states at any point in time. In other words, the transitions between states are instantaneous.&lt;/li&gt;
&lt;li&gt;The “flick” event causes it to transition between states.&lt;/li&gt;
&lt;li&gt;When the machine enters the “on” state, a side effect occurs. A light is turned on.&lt;/li&gt;
&lt;li&gt;When the machine exits the “on” state, another side effect occurs. A light is turned off.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The definition of the machine is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;switch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;initial&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;states&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;off&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;FLICK&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;on&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turnLightOn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;FLICK&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turnLightOff&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating a state machine
&lt;/h2&gt;

&lt;p&gt;In order to create a state machine, you import the &lt;code&gt;createMachine&lt;/code&gt; function and pass it a machine definition object.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;FicusJS decorates the &lt;a href="https://xstate.js.org/docs/packages/xstate-fsm/" rel="noopener noreferrer"&gt;@xstate/fsm&lt;/a&gt; package to provide additional features like extended state getters. You can also use the full XState library with FicusJS, See &lt;a href="https://docs.ficusjs.org/state-machines/" rel="noopener noreferrer"&gt;the state machine docs&lt;/a&gt; for more information.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createMachine&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://cdn.skypack.dev/@ficusjs/state@3/xstate-service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;machine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createMachine&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;switch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;bulb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;initial&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;states&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;off&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;FLICK&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;on&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turnLightOn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;FLICK&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turnLightOff&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating side effects
&lt;/h2&gt;

&lt;p&gt;Our state machine has two side effects. These are actions that are invoked when a transition is received.&lt;/p&gt;

&lt;p&gt;Actions are passed as options to the &lt;code&gt;createMachine&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createMachine&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://cdn.skypack.dev/@ficusjs/state@3/xstate-service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;definition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;switch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;bulb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;initial&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;states&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;off&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;FLICK&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;on&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turnLightOn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;FLICK&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turnLightOff&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;turnLightOn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;bulb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;on&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="na"&gt;turnLightOff&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;bulb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;machine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createMachine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Interpreted state machines
&lt;/h2&gt;

&lt;p&gt;We can use an interpreted state machine to keep track of the state for us. To create an interpreted state machine, pass the machine created with &lt;code&gt;createMachine&lt;/code&gt; into the &lt;code&gt;interpret&lt;/code&gt; function. The result of the &lt;code&gt;interpret&lt;/code&gt; function is called a service (a running instance of the machine).&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;machine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createMachine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;interpret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;machine&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Component usage
&lt;/h2&gt;

&lt;p&gt;The service created with &lt;code&gt;interpret&lt;/code&gt; can then be passed to a web component for it to react to state changes and therefore allow you to render UI based on the current state.&lt;/p&gt;

&lt;p&gt;To pass the service to the component, use the &lt;code&gt;withXStateService&lt;/code&gt; component extension.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;renderer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://cdn.skypack.dev/@ficusjs/renderers@5/uhtml&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createCustomElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;withXStateService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://cdn.skypack.dev/ficusjs@5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nf"&gt;createCustomElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;switch-state-machine&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;withXStateService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;onChange &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;fsm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FLICK&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="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="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The result
&lt;/h2&gt;

&lt;p&gt;The following &lt;a href="https://codepen.io/ducksoupdev/pen/GRxWXQm" rel="noopener noreferrer"&gt;Codepen&lt;/a&gt; is an implementation example of the switch state machine used to turn on/off a light bulb.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/ducksoupdev/embed/GRxWXQm?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

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

&lt;p&gt;State machines and statecharts reduce complexity, bugs and inconsistencies in UI development by helping you define components using a behaviour-driven model. This ensures that what is designed through the visual model, is the same output that components provide through the implementation of XState.&lt;/p&gt;

&lt;p&gt;State machines are a great fit if you need to control the application’s flow carefully. If you start using XState, it does not mean that everything will have to live inside the state machine. Some things need to be controlled on a local level inside a component rather than on a global level inside a state machine. That goes for both the state and the side effects.&lt;/p&gt;

&lt;p&gt;Make smaller state machines rather than one enormous state machine. Programming is about composability, making larger things from smaller things — and state machines compose well.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webcomponents</category>
      <category>xstate</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Breakpoint rendering in web components</title>
      <dc:creator>Matt Levy</dc:creator>
      <pubDate>Wed, 01 Dec 2021 21:31:54 +0000</pubDate>
      <link>https://dev.to/ficusjs/breakpoint-rendering-in-web-components-5813</link>
      <guid>https://dev.to/ficusjs/breakpoint-rendering-in-web-components-5813</guid>
      <description>&lt;p&gt;Tailoring a user experience for different devices can get complicated. There are many approaches to rendering a different view for mobile, tablet and desktop users.&lt;/p&gt;

&lt;p&gt;This post presents a way to offer a tailored render for different breakpoints in the same component.&lt;/p&gt;

&lt;p&gt;The benefit of this approach is useful when you need to render the same content components in an app and have them render a specific set of HTML based on viewport size.&lt;/p&gt;

&lt;h2&gt;
  
  
  Define the breakpoints
&lt;/h2&gt;

&lt;p&gt;Firstly, the breakpoints need defining. This sets the viewport widths and the render function to use at this breakpoint.&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;breakpointConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;breakpoints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="mi"&gt;992&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;renderTablet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="mi"&gt;768&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;renderMobile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="mi"&gt;1200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;renderDesktop&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;reactive&lt;/code&gt; property will make the component automatically re-render when the viewport width changes - this is optional.&lt;/p&gt;

&lt;p&gt;Each breakpoint has a number key for the width followed by an object containing a &lt;code&gt;method&lt;/code&gt; to use at that viewport breakpoint.&lt;/p&gt;

&lt;p&gt;The above config results in the following media query list.&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="nt"&gt;only&lt;/span&gt; &lt;span class="nt"&gt;screen&lt;/span&gt; &lt;span class="nt"&gt;and&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;max-width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;768&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nt"&gt;only&lt;/span&gt; &lt;span class="nt"&gt;screen&lt;/span&gt; &lt;span class="nt"&gt;and&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;min-width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;769&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;and&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;max-width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;992&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nt"&gt;only&lt;/span&gt; &lt;span class="nt"&gt;screen&lt;/span&gt; &lt;span class="nt"&gt;and&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;min-width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;1201&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Component usage
&lt;/h2&gt;

&lt;p&gt;Using the above breakpoint config, a component can be created with render methods for each breakpoint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createCustomElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;withBreakpointRender&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://cdn.skypack.dev/ficusjs@3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;renderer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://cdn.skypack.dev/@ficusjs/renderers@3/uhtml&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nx"&gt;createCustomElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;breakpoint-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;withBreakpointRender&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;breakpointConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;renderTablet&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;span&amp;gt;Breakpoint render tablet&amp;lt;/span&amp;gt;`&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;renderMobile&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;span&amp;gt;Breakpoint render mobile&amp;lt;/span&amp;gt;`&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;renderDesktop&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;span&amp;gt;Breakpoint render desktop&amp;lt;/span&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;To view the component in action see this Codepen - &lt;a href="https://codepen.io/ducksoupdev/pen/WNZbWbq?editors=1010"&gt;https://codepen.io/ducksoupdev/pen/WNZbWbq?editors=1010&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Try resizing the Codepen panel!&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;Conditionally rendering HTML based on the viewport width can be a powerful way to offer a tailored user experience.&lt;/p&gt;

&lt;p&gt;Some examples of using this approach are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Render a table on desktop and list view on mobile&lt;/li&gt;
&lt;li&gt;Conditionally hide functionality on smaller screens&lt;/li&gt;
&lt;li&gt;Show tabbed navigation on mobile and sidebar on desktop&lt;/li&gt;
&lt;li&gt;Maintain state within a component presented in different ways&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For more documentation visit &lt;a href="https://docs.ficusjs.org/extending-components/with-breakpoint-render/"&gt;https://docs.ficusjs.org/extending-components/with-breakpoint-render/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try it in your next project!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>webcomponents</category>
    </item>
    <item>
      <title>JSX for web components</title>
      <dc:creator>Matt Levy</dc:creator>
      <pubDate>Sat, 21 Aug 2021 05:40:44 +0000</pubDate>
      <link>https://dev.to/ficusjs/jsx-for-web-components-4cdc</link>
      <guid>https://dev.to/ficusjs/jsx-for-web-components-4cdc</guid>
      <description>&lt;p&gt;Love it or hate it, JSX is a great technology for rendering HTML using Javascript. It is available for most frameworks but did you know that you can use it for rendering web components too?&lt;/p&gt;

&lt;p&gt;You can use JSX with or without transpiling your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Without transpiling
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals"&gt;Tagged template literals&lt;/a&gt; can be used directly in the browser. The &lt;a href="https://www.npmjs.com/package/htm"&gt;htm&lt;/a&gt; library provides a JSX-like tagged template literal for rendering HTML.&lt;/p&gt;

&lt;p&gt;Here is how you can use it in a &lt;a href="https://docs.ficusjs.org/"&gt;FicusJS&lt;/a&gt; web component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createCustomElement&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ficusjs/custom-element&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;renderer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ficusjs/renderers/htm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nx"&gt;createCustomElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello-world&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;renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="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;p&amp;gt;Hello world!&amp;lt;/p&amp;gt;`&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Template literals are literals delimited with backticks, allowing embedded expressions called substitutions. Tagged template literals call a function (in this case the &lt;code&gt;html&lt;/code&gt; tag function) with an array of any text segments from the literal followed by arguments with the values of any substitutions. &lt;/p&gt;

&lt;p&gt;This example uses the &lt;a href="https://github.com/ficusjs/ficusjs-renderers"&gt;&lt;code&gt;@ficusjs/renderers&lt;/code&gt;&lt;/a&gt; package which provides a browser-ready ES module using the &lt;code&gt;htm&lt;/code&gt; library.&lt;/p&gt;

&lt;p&gt;Clone this Snowpack starter to see it in action - &lt;a href="https://github.com/ficusjs/ficusjs-snowpack-starter"&gt;https://github.com/ficusjs/ficusjs-snowpack-starter&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  With transpiling
&lt;/h2&gt;

&lt;p&gt;As JSX extends Javascript, one of its best features is the ability to transpile it.&lt;/p&gt;

&lt;p&gt;Transpiling removes the overhead of loading the renderer and parsing the JSX at runtime. It would be used as a production step to remove the renderer.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/developit/htm/tree/master/packages/babel-plugin-htm"&gt;&lt;code&gt;babel-plugin-htm&lt;/code&gt;&lt;/a&gt; Babel plugin compiles tagged template literals using &lt;code&gt;htm&lt;/code&gt; to hyperscript. This is the same process React/Preact use in transpiling JSX for production.&lt;/p&gt;

&lt;p&gt;Here is an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;h&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ficusjs/renderers/jsx-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createCustomElement&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ficusjs/custom-element&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nx"&gt;createCustomElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello-world&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;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;p&amp;gt;Hello world!&amp;lt;/p&amp;gt;`&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is very similar to the without transpilation example except that no &lt;code&gt;renderer&lt;/code&gt; function is imported and the &lt;code&gt;h&lt;/code&gt; pragma is imported for transpiling the JSX.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the &lt;code&gt;h&lt;/code&gt; pragma?
&lt;/h3&gt;

&lt;p&gt;By default, Babel will transform &lt;code&gt;&amp;lt;p&amp;gt;Hello world!&amp;lt;/p&amp;gt;&lt;/code&gt; to &lt;code&gt;React.createElement("p", null, "Hello world!");&lt;/code&gt;. Pragma &lt;code&gt;h&lt;/code&gt; will generate instead as &lt;code&gt;h("p", null, "Hello world!");&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Pragma is the name to describe the function used by Babel to transpile the JSX.&lt;/p&gt;

&lt;p&gt;In this example, pragma &lt;code&gt;h&lt;/code&gt; is the function used by Babel to transpile JSX to Javascript to build the DOM rendered by the component.&lt;/p&gt;

&lt;p&gt;By default, the &lt;a href="https://docs.ficusjs.org/"&gt;FicusJS&lt;/a&gt; web component &lt;code&gt;render&lt;/code&gt; function expects a DOM element for rendering. The pragma imported from the &lt;code&gt;@ficusjs/renderers/jsx-dom&lt;/code&gt; library creates a DOM element for rendering in the component.&lt;/p&gt;

&lt;p&gt;This is the output of the transpilation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;h&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./_snowpack/pkg/@ficusjs/renderers/jsx-dom.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createCustomElement&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./_snowpack/pkg/ficusjs/custom-element.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;createCustomElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello-world&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;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;h&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;p&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello world!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clone this Snowpack starter to see JSX transpilation in action - &lt;a href="https://github.com/ficusjs/ficusjs-compiled-templates"&gt;https://github.com/ficusjs/ficusjs-compiled-templates&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Using JSX in your web components allows you to use tagged template literals in development and then transpile it away for production resulting in smaller optimised components.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/developit/htm"&gt;htm&lt;/a&gt; library gives you JSX-like syntax but goes even further.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spread props: &lt;code&gt;&amp;lt;div ...${props}&amp;gt;&lt;/code&gt; instead of &lt;code&gt;&amp;lt;div {...props}&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Self-closing tags: &lt;code&gt;&amp;lt;div /&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Components: &lt;code&gt;&amp;lt;${Foo}&amp;gt;&lt;/code&gt; instead of &lt;code&gt;&amp;lt;Foo&amp;gt;&lt;/code&gt; (where &lt;code&gt;Foo&lt;/code&gt; is a component reference)&lt;/li&gt;
&lt;li&gt;Boolean attributes: &lt;code&gt;&amp;lt;div draggable /&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No transpiler necessary&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;HTML's optional quotes: &lt;code&gt;&amp;lt;div class=foo&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Component end-tags: &lt;code&gt;&amp;lt;${Footer}&amp;gt;footer content&amp;lt;//&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Syntax highlighting and language support via the &lt;a href="https://marketplace.visualstudio.com/items?itemName=bierner.lit-html"&gt;lit-html VSCode extension&lt;/a&gt; and &lt;a href="https://github.com/MaxMEllon/vim-jsx-pretty"&gt;vim-jsx-pretty plugin&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Multiple root element (fragments): &lt;code&gt;&amp;lt;div /&amp;gt;&amp;lt;div /&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Support for HTML-style comments: &lt;code&gt;&amp;lt;div&amp;gt;&amp;lt;!-- comment --&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try it in your next project!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>webcomponents</category>
      <category>jsx</category>
    </item>
    <item>
      <title>Keep your app smooth and responsive with web workers</title>
      <dc:creator>Matt Levy</dc:creator>
      <pubDate>Tue, 20 Jul 2021 14:19:15 +0000</pubDate>
      <link>https://dev.to/ficusjs/keep-your-app-smooth-and-responsive-with-web-workers-5f06</link>
      <guid>https://dev.to/ficusjs/keep-your-app-smooth-and-responsive-with-web-workers-5f06</guid>
      <description>&lt;p&gt;How do you keep your web app smooth and responsive?&lt;br&gt;
How do you ensure a steady and sufficiently high frame rate? How do you ensure the UI responds to user interactions with minimal delay?&lt;/p&gt;

&lt;p&gt;These are key factors in making your app feel polished and high-quality.&lt;/p&gt;

&lt;p&gt;The web is single-threaded which makes it hard to write smooth and responsive apps. JavaScript was designed to run in-step with the browser's main rendering loop which means that a small amount of slow JavaScript code can prevent the browser's rendering loop from continuing.&lt;/p&gt;

&lt;p&gt;Web applications are expected to run on all devices, from the latest iPhone to a cheap smart phone. How long your piece of JavaScript takes to finish depends on how fast the device is that your code is running on.&lt;/p&gt;

&lt;p&gt;Web workers can be an important and useful tool in keeping your app smooth and responsive by preventing any accidentally long-running code from blocking the browser from rendering. Web Workers are a simple means for apps to run scripts in background threads. The worker thread can perform tasks without interfering with the user interface. &lt;/p&gt;

&lt;p&gt;Web workers have not been widely adopted and there isn’t a lot of guidance on architecture for workers. It can be hard to identify which parts of your app will work in a worker. In addition, due to the asynchronous way of communicating with a worker, adoption of workers requires some architectural adjustments in your app.&lt;/p&gt;
&lt;h2&gt;
  
  
  Application state in a web worker
&lt;/h2&gt;

&lt;p&gt;A key architecture change you can make in your app is to manage data in a worker and keep rendering updates to a minimum.&lt;/p&gt;

&lt;p&gt;By moving your application state to a worker means you move complex business logic and data loading/processing there too.&lt;/p&gt;

&lt;p&gt;State can be managed effectively in a web worker as proxies and fetch are available - both essential APIs for loading data and reactivity.&lt;/p&gt;

&lt;p&gt;To communicate with the user interface, data is sent between workers and the main UI thread via a system of messages — both sides send their messages using the &lt;code&gt;postMessage()&lt;/code&gt; method, and respond to messages via the &lt;code&gt;onmessage&lt;/code&gt; event handler.&lt;/p&gt;

&lt;p&gt;A typical store for managing application state in the UI thread could look like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createAppState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://cdn.skypack.dev/ficusjs@3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createAppState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;worker.test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;setText&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="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;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;text&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;Lets create an equivalent web worker store for managing application state.&lt;/p&gt;

&lt;p&gt;Create a worker file &lt;code&gt;worker.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// import the web worker friendly app state creator function&lt;/span&gt;
&lt;span class="nx"&gt;importScripts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://unpkg.com/@ficusjs/state@1.2.0/dist/worker-app-state.iife.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Initialize the store using the ficusjs.createAppState function&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;globalThis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ficusjs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createAppState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;setText&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="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;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// a function for communicating with the UI thread&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;postState&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;globalThis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// subscribe to store changes&lt;/span&gt;
&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;postState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// listen for actions to invoke in the store&lt;/span&gt;
&lt;span class="nx"&gt;globalThis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onmessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;actionName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;
  &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;actionName&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// post the initial state to any components&lt;/span&gt;
&lt;span class="nx"&gt;postState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  UI components
&lt;/h2&gt;

&lt;p&gt;Create components that are only responsible for rendering UI using the &lt;code&gt;withWorkerStore&lt;/code&gt; function to extend the component with the worker.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createCustomElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;withWorkerStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://cdn.skypack.dev/ficusjs@3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;renderer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://cdn.skypack.dev/@ficusjs/renderers@3/htm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nx"&gt;createCustomElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;example-worker-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;withWorkerStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./worker.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;onButtonClick&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;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setText&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;This is a test&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;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;section&amp;gt;
          &amp;lt;p&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;state&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&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;state&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="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;
          &amp;lt;button type="button" onclick="&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;onButtonClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;Dispatch worker action&amp;lt;/button&amp;gt;
        &amp;lt;/section&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;The &lt;code&gt;withWorkerStore&lt;/code&gt; function provides a &lt;code&gt;this.state&lt;/code&gt; property within the component as well as a &lt;code&gt;this.dispatch()&lt;/code&gt; method for invoking store actions.&lt;br&gt;
It also makes the component reactive to store changes as well as handling automatic store subscriptions based on the component lifecycle hooks.&lt;br&gt;
It will also refresh computed getters when store state changes.&lt;/p&gt;

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

&lt;p&gt;The investment in workers can provide you with a way to make your app smooth and responsive as well as supporting the range of devices that your app is accessed from.&lt;/p&gt;

&lt;p&gt;To view documentation on using web workers with FicusJS, visit &lt;a href="https://docs.ficusjs.org/app-state/web-workers/"&gt;https://docs.ficusjs.org/app-state/web-workers/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>webworkers</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Delay font loading using Javascript</title>
      <dc:creator>Matt Levy</dc:creator>
      <pubDate>Wed, 19 May 2021 12:20:08 +0000</pubDate>
      <link>https://dev.to/ficusjs/delay-font-loading-using-javascript-1e9b</link>
      <guid>https://dev.to/ficusjs/delay-font-loading-using-javascript-1e9b</guid>
      <description>&lt;p&gt;Achieving 100% across the board in Lighthouse can be tricky to do.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xvfBGrjH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/udb06mz81b39vjx3afva.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xvfBGrjH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/udb06mz81b39vjx3afva.png" alt="alt text" width="800" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the assets of any web application is fonts. Loading fonts can have an impact on page load times and directly affects Lighthouse scores.&lt;/p&gt;

&lt;p&gt;Fonts are often placed in the page &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; using a &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; tag.&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;link&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://fonts.googleapis.com/css2?family=Roboto&amp;amp;display=swap"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whilst this is the recommended way to load fonts, style sheets loaded in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; block rendering and impact page load times.&lt;/p&gt;

&lt;h2&gt;
  
  
  A simple solution
&lt;/h2&gt;

&lt;p&gt;Whilst Javascript shouldn't be used in place of HTML or CSS, it does offer the ability to create a simple solution that doesn't impact load times and takes one step closer to the 100% Lighthouse score.&lt;/p&gt;

&lt;p&gt;The following snippet delays the loading of fonts until the page has loaded. This means that fonts are not available whilst the page is being rendered, they are rendered after page load.&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://fonts.googleapis.com/css2?family=Roboto&amp;amp;display=swap&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&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;gf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;link&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;gf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stylesheet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="nx"&gt;gf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;
  &lt;span class="nx"&gt;gf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;gd&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;getElementsByTagName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;link&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;gd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;insertBefore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;gd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This snippet of Javascript relies on an existing &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; tag to exist in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; so it can attach the font stylesheet. If you are using Google fonts or other CDN, it is recommended to use a &lt;code&gt;rel="preconnect"&lt;/code&gt; link tag to tell the browser to establish an early connection with that origin.&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;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"preconnect"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://fonts.gstatic.com"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to use
&lt;/h2&gt;

&lt;p&gt;Copy the following Javascript into a file named &lt;code&gt;fonts.mjs&lt;/code&gt; and include URLs to the style sheets you want to load:&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://fonts.googleapis.com/css2?family=Roboto&amp;amp;display=swap&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&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;gf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;link&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;gf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stylesheet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="nx"&gt;gf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;
  &lt;span class="nx"&gt;gf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;gd&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;getElementsByTagName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;link&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;gd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;insertBefore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;gd&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;Add a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag to your HTML page pointing to the Javascript file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/path/to/fonts.mjs"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>webdev</category>
      <category>webperf</category>
    </item>
    <item>
      <title>11ty and web components, an awesome combination</title>
      <dc:creator>Matt Levy</dc:creator>
      <pubDate>Sun, 02 May 2021 10:59:29 +0000</pubDate>
      <link>https://dev.to/ficusjs/11ty-and-web-components-an-awesome-combination-4li7</link>
      <guid>https://dev.to/ficusjs/11ty-and-web-components-an-awesome-combination-4li7</guid>
      <description>&lt;p&gt;&lt;a href="https://www.11ty.dev/"&gt;11ty&lt;/a&gt; (Eleventy) and web components is an awesome combination. It is one of my go-to solutions for building web apps.&lt;/p&gt;

&lt;p&gt;Setting up a project with &lt;a href="https://www.11ty.dev/"&gt;11ty&lt;/a&gt; is pretty simple. You can set it up from scratch or you can use an 11ty &lt;a href="https://www.11ty.dev/docs/starter/"&gt;starter project&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This post shows you how to get started using 11ty with &lt;a href="https://docs.ficusjs.org"&gt;FicusJS&lt;/a&gt;. FicusJS is a set of lightweight functions for developing applications using web components.&lt;/p&gt;

&lt;p&gt;The tool we are going to use creates a starter project quickly and easily using 11ty and FicusJS. The tool of choice is &lt;a href="https://github.com/ficusjs/create-ficus-app"&gt;Create Ficus App&lt;/a&gt;. It is a simple tool that makes creating new projects quick and easy.&lt;/p&gt;

&lt;p&gt;The project will contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;11ty development set-up&lt;/li&gt;
&lt;li&gt;FicusJS web components&lt;/li&gt;
&lt;li&gt;Unit testing with &lt;a href="https://dev.to/ficusjs/unit-testing-web-components-with-ava-and-jsdom-2ofp"&gt;Ava and JSDom&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Build tooling for production optimisation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;Create Ficus App lets you focus on code, not build tools.&lt;/p&gt;

&lt;p&gt;To create a project called my-app, run this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-ficus-app my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the &lt;code&gt;my-app&lt;/code&gt; directory is created, all you need to do is install NPM packages using NPM or yarn:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="c"&gt;# use NPM&lt;/span&gt;
npm i

&lt;span class="c"&gt;# or use yarn&lt;/span&gt;
yarn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Starter projects
&lt;/h2&gt;

&lt;p&gt;Depending on what you need to build, Create Ficus App offers a selection of starter projects.&lt;/p&gt;

&lt;p&gt;More to follow soon!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic app - a simple, single HTML page with inline scripts&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.11ty.dev/"&gt;11ty&lt;/a&gt; app - a Jamstack site based on &lt;a href="https://www.11ty.dev/"&gt;11ty&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to choose a starter project, run this command and follow the prompts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-ficus-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Having a simple tool like Create Ficus App can save a lot of time when creating new projects. It gives you a headstart and allows you to incrementally add new tools and features as your project grows.&lt;/p&gt;

&lt;p&gt;If you have any feedback on the tool, please visit the &lt;a href="https://github.com/ficusjs/create-ficus-app"&gt;Github repo&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>webcomponents</category>
    </item>
    <item>
      <title>Unit testing web components with ava and jsdom</title>
      <dc:creator>Matt Levy</dc:creator>
      <pubDate>Sun, 11 Apr 2021 17:02:06 +0000</pubDate>
      <link>https://dev.to/ficusjs/unit-testing-web-components-with-ava-and-jsdom-2ofp</link>
      <guid>https://dev.to/ficusjs/unit-testing-web-components-with-ava-and-jsdom-2ofp</guid>
      <description>&lt;p&gt;Unit testing web components is tricky. The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry" rel="noopener noreferrer"&gt;&lt;code&gt;customElements&lt;/code&gt;&lt;/a&gt; API is required (or a polyfill of it) to create web component instances for testing.&lt;/p&gt;

&lt;p&gt;Due to this friction and complication, I typically use an E2E testing framework like &lt;a href="https://www.cypress.io/" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt; which runs tests against a real browser like headless Chrome.&lt;/p&gt;

&lt;p&gt;Whilst an E2E framework is a fantastic tool for testing web components, I've wanted a suite of unit tests like I have for a back-end API - a comprehensive suite of fast tests for validating web components.&lt;/p&gt;

&lt;p&gt;With Node v14, this can now be achieved through the &lt;a href="https://nodejs.org/api/packages.html#packages_determining_module_system" rel="noopener noreferrer"&gt;native support for ES modules&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This post provides an example of how to set-up web component unit testing using &lt;a href="https://github.com/avajs/ava" rel="noopener noreferrer"&gt;ava&lt;/a&gt; and &lt;a href="https://github.com/jsdom/jsdom" rel="noopener noreferrer"&gt;jsdom&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A repo containing the source code for this example is available at &lt;a href="https://github.com/ducksoupdev/ficusjs-ava-test" rel="noopener noreferrer"&gt;https://github.com/ducksoupdev/ficusjs-ava-test&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependencies
&lt;/h2&gt;

&lt;p&gt;The following dependencies are used for this example.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ava
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/avajs/ava" rel="noopener noreferrer"&gt;Ava&lt;/a&gt; is a lightweight, fast test runner for NodeJS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Jsdom
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/jsdom/jsdom" rel="noopener noreferrer"&gt;Jsdom&lt;/a&gt; is a pure Javascript implementation of HTML and DOM. Starting with v16, jsdom provides a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry" rel="noopener noreferrer"&gt;&lt;code&gt;customElements&lt;/code&gt;&lt;/a&gt; API implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set-up
&lt;/h2&gt;

&lt;p&gt;Firstly, initialize a new NodeJS project to create a &lt;code&gt;package.json&lt;/code&gt; file using &lt;code&gt;npm init&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Copy the following properties to the &lt;code&gt;package.json&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ava"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"devDependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@ficusjs/renderers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^3.1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ava"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^3.15.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ficusjs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^3.2.3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"jsdom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^16.5.2"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Secondly, create an ES module (&lt;code&gt;.mjs&lt;/code&gt;) test file at &lt;code&gt;test/component.spec.mjs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Copy the following to the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;JSDOM&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jsdom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ava&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;before&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JSDOM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;!DOCTYPE html&amp;gt;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;globalThis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;
  &lt;span class="nx"&gt;globalThis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;
  &lt;span class="nx"&gt;globalThis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customElements&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;customElements&lt;/span&gt;
  &lt;span class="nx"&gt;globalThis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HTMLElement&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;HTMLElement&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This contains the basic structure of a unit test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Imports &lt;code&gt;jsdom&lt;/code&gt; and &lt;code&gt;ava&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Initializes a new DOM and exposes global properties required during testing&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Create a web component
&lt;/h2&gt;

&lt;p&gt;Create an ES module file at &lt;code&gt;src/component.mjs&lt;/code&gt; and copy the following contents into it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ficusjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;renderer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ficusjs/renderers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nf"&gt;createComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;basic-comp&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;renderer&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;p&amp;gt;Basic component&amp;lt;/p&amp;gt;`&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example is a web component created using &lt;a href="https://www.npmjs.com/package/ficusjs" rel="noopener noreferrer"&gt;FicusJS&lt;/a&gt; and the &lt;a href="https://www.npmjs.com/package/uhtml" rel="noopener noreferrer"&gt;uhtml&lt;/a&gt; renderer. It is a basic example that renders a &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; tag internally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing a test
&lt;/h2&gt;

&lt;p&gt;Lets test the component.&lt;/p&gt;

&lt;p&gt;Open the ES module test file &lt;code&gt;test/component.spec.mjs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Copy the following to the file after the existing content.&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="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;render basic component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;t&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;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../src/component.mjs&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="nb"&gt;document&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;globalThis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;basicComp&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="s1"&gt;basic-comp&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="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;basicComp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="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="s1"&gt;basic-comp p&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Basic component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following is happening in this test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Import the component ready to test&lt;/li&gt;
&lt;li&gt;Create a new instance of the component and append it to the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Assert that the component renders the &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; tag internally&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The component is imported within the test and not at the top of the file because the global properties &lt;strong&gt;must&lt;/strong&gt; be initialized for the component to work. Importing the component during the test means that the required global properties are available for the component to register itself with the &lt;code&gt;customElements&lt;/code&gt; API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run the test
&lt;/h2&gt;

&lt;p&gt;To run the test, type &lt;code&gt;npm test&lt;/code&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F62rt8r5z9qn680j82yr5.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%2F62rt8r5z9qn680j82yr5.png" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If all is successful, you should see the above output from &lt;code&gt;ava&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;The opportunity to unit test web components this way is exciting. However, there are some caveats with this approach that might make it difficult in certain scenarios.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It follows &lt;a href="https://nodejs.org/api/packages.html#packages_determining_module_system" rel="noopener noreferrer"&gt;NodeJS ES module guidelines&lt;/a&gt; that may not be compatible with the browser.&lt;/li&gt;
&lt;li&gt;Files must be named with the &lt;code&gt;.mjs&lt;/code&gt; extension or provide a &lt;code&gt;package.json&lt;/code&gt; top level property &lt;code&gt;type&lt;/code&gt; of value &lt;code&gt;module&lt;/code&gt; if the extension is &lt;code&gt;.js&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Importing libraries from a URL is not natively supported but can be achieved through a &lt;a href="https://nodejs.org/api/esm.html#esm_https_loader" rel="noopener noreferrer"&gt;custom HTTPS loader&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;ES module support in NodeJS is relatively new and I'm sure will get better in time.&lt;/p&gt;

&lt;p&gt;For applications that use NodeJS build tools such as Rollup or Webpack, this could provide a unit testing approach to validate web components bundled together.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>testing</category>
      <category>webcomponents</category>
    </item>
    <item>
      <title>Want to get started with web components?</title>
      <dc:creator>Matt Levy</dc:creator>
      <pubDate>Wed, 07 Apr 2021 19:49:29 +0000</pubDate>
      <link>https://dev.to/ficusjs/want-to-get-started-with-web-components-4h7p</link>
      <guid>https://dev.to/ficusjs/want-to-get-started-with-web-components-4h7p</guid>
      <description>&lt;p&gt;Browsers have improved &lt;em&gt;greatly&lt;/em&gt;. Many of the reasons to reach for a big framework like React or Angular have gone away.&lt;/p&gt;

&lt;p&gt;You don't have to rely on a complex build system, bundlers, or other tooling to ship your Javascript to users anymore.&lt;/p&gt;

&lt;p&gt;Browsers have support to import Javascript modules directly. You don't have to template your components in JSX and add all the baggage and complexity of a build tool - you can use Javascript &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals"&gt;tagged template literal syntax&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If don't want to pull in the complexity of a large framework like React or Angular, but still want to build applications with components, &lt;a href="https://docs.ficusjs.org"&gt;FicusJS&lt;/a&gt; is for you!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.ficusjs.org"&gt;FicusJS&lt;/a&gt; is a set of lightweight functions for developing web applications. It is focused on creating web components, managing application state plus a pub/sub event bus.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are web components?
&lt;/h2&gt;

&lt;p&gt;Web components are a set of browser APIs that allow you to create new custom, reusable, encapsulated HTML tags for use in web applications.&lt;br&gt;
Web Components work across modern browsers and can be used with any JavaScript library or framework that works with HTML.&lt;/p&gt;
&lt;h2&gt;
  
  
  Go build-less
&lt;/h2&gt;

&lt;p&gt;Browsers have improved a lot over the past years. It's now possible to do web development without requiring any build tools, using the native module loader of the browser. We think this is a great fit for &lt;a href="https://docs.ficusjs.org"&gt;FicusJS&lt;/a&gt;, and we recommend this as a general starting point.&lt;/p&gt;
&lt;h2&gt;
  
  
  Aligns with standards
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.ficusjs.org"&gt;FicusJS&lt;/a&gt; aligns with standard browser APIs which means it is not based on any proprietary code or libraries.&lt;/p&gt;

&lt;p&gt;As it is based on standards, it has longevity and is a good choice for enterprise web applications.&lt;/p&gt;
&lt;h2&gt;
  
  
  Try it out
&lt;/h2&gt;

&lt;p&gt;The easiest way to try out &lt;a href="https://docs.ficusjs.org"&gt;FicusJS&lt;/a&gt; is using a hello world example.&lt;/p&gt;

&lt;p&gt;Create an &lt;code&gt;index.html&lt;/code&gt; file and copy the following between the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; tags.&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;hello-world&amp;gt;&amp;lt;/hello-world&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;renderer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://cdn.skypack.dev/@ficusjs/renderers/lit-html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://cdn.skypack.dev/ficusjs@3/component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nx"&gt;createComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello-world&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;renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello to you!&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;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;
&amp;lt;p&amp;gt;Test component&amp;lt;/p&amp;gt;
&amp;lt;button type="button" @click="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;Click me!&amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;`&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;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Alternatively, fork this Codepen to see it in action - &lt;a href="https://codepen.io/ducksoupdev/pen/GRZPqJO"&gt;https://codepen.io/ducksoupdev/pen/GRZPqJO&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The hello world example creates a new &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements"&gt;custom element&lt;/a&gt;&lt;br&gt;
using the &lt;code&gt;createComponent&lt;/code&gt; function and registers it to the &lt;code&gt;hello-world&lt;/code&gt; tag. It uses the &lt;a href="https://www.npmjs.com/package/lit-html"&gt;lit-html&lt;/a&gt; renderer (&lt;a href="https://github.com/ficusjs/ficusjs-renderers"&gt;multiple renderers are available&lt;/a&gt;) for creating HTML from &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals"&gt;tagged template literals&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once registered, the tag can be used multiple times in HTML and instances can be programmatically obtained using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector"&gt;&lt;code&gt;document.querySelector&lt;/code&gt;&lt;/a&gt;&lt;br&gt;
or &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector"&gt;&lt;code&gt;element.querySelector&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Less Javascript, more HTML and CSS</title>
      <dc:creator>Matt Levy</dc:creator>
      <pubDate>Thu, 29 Oct 2020 17:26:55 +0000</pubDate>
      <link>https://dev.to/ducksoupdev/less-javascript-more-html-and-css-49gl</link>
      <guid>https://dev.to/ducksoupdev/less-javascript-more-html-and-css-49gl</guid>
      <description>&lt;p&gt;I'm a big fan of modern Javascript frameworks. I use them every day and they make development fun again (even if you dislike Javascript!). However, more and more Javascript is something that is making me increasingly uncomfortable. For a number of years now, I've been worried about web obesity. I'm not alone &lt;a href="https://idlewords.com/talks/website_obesity.htm"&gt;https://idlewords.com/talks/website_obesity.htm&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We use Javascript for everything! As cool as it is, it's not good for our front-end health.&lt;/p&gt;

&lt;p&gt;Maybe I'm old school but I remember when Javascript was used to sprinkle web pages with interaction and other loveliness not available in HTML and CSS. This kept web pages lean, mean and Javascript to a minimum.&lt;/p&gt;

&lt;h2&gt;
  
  
  Less Javascript
&lt;/h2&gt;

&lt;p&gt;As I said modern Javascript frameworks are amazing to work with but I've seen them used badly. This results in bloated web applications. It is common to see web apps that are over 2 MB in payload - even after tree-shaking!&lt;/p&gt;

&lt;p&gt;This is in part due to the awesomeness of NPM. NPM seems to be a default for many developers looking to solve problems with a library and not considering the extra payload it will add to their applications. NPM packages are primarily for NodeJS and although many do provide browser bundles, often these are transpiled using polyfills and other unnecessary code to make them compatible with all browsers.&lt;/p&gt;

&lt;p&gt;In a recent internal hackathon, an open clinic was set-up to allow developers to ask front-end questions at the start of their hacks. One question was asked more than any other "how can I use this NPM package I've found in my hack?". One of the limitations of the hack was that build tools were not allowed - no Webpack, no Rollup, no transpilation - just pure HTML, CSS and Javascript in the browser. Are developers lacking the understanding of how web applications run in the browser?&lt;/p&gt;

&lt;p&gt;Progressive Web Apps (PWAs) are web applications that have been designed so they are capable, reliable, and installable. They are meant to be lightweight and fast - to feel like native applications in the browser. PWAs are an excellent set of principles for developing any web application. Performance is key in providing a great experience in your application. Too much Javascript can easily degrade the performance of your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  More HTML
&lt;/h2&gt;

&lt;p&gt;Whilst it is easy to fall into the trap of using Javascript for everything, it bloats unnecessarily.&lt;/p&gt;

&lt;p&gt;Component based frameworks are amazing but they ultimately mean more and more javascript. Javascript is needed to generate HTML, Javascript is needed to provide user interaction, Javascript is needed to do all the things.&lt;/p&gt;

&lt;p&gt;HTML has a rich set of elements for building modern web applications. Using more HTML and sprinkling Javascript where required will result in less Javascript. Less Javascript means more lightweight, fast web applications.&lt;/p&gt;

&lt;p&gt;Use of more HTML elements for creating the application shell - navigation, menus, page structure means that Javascript is reserved for the areas where it is needed - a form, a data grid, a tree view.&lt;/p&gt;

&lt;p&gt;Web components, whilst Javascript, provide a very lightweight way to extend HTML and provide baked-in solutions for common component problems. Web components can provide a way to implement common UI elements like tabs, dialogs and dropdown menus that work across all modern javascript and server-side frameworks.&lt;/p&gt;

&lt;h2&gt;
  
  
  More CSS
&lt;/h2&gt;

&lt;p&gt;Styling web applications can be tricky and there are some great solutions for developers out there. Unfortunately, many of these rely on Javascript - all adding more and more Javascript bloat. Is this really necessary?&lt;/p&gt;

&lt;p&gt;Being able to style components and enhance them in a progressive way can all be done natively with CSS. Using modern features like CSS variables and taking the time to split CSS into per page (or route) styles can lead to good web application performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  In summary
&lt;/h2&gt;

&lt;p&gt;The governing body for professional cycling in Great Britain,  hired Dave Brailsford in 2003 as its new performance director. At the time, professional cyclists in Great Britain had endured nearly one hundred years of mediocrity. Since 1908, British riders had won just a single gold medal at the Olympic Games, and they had fared even worse in cycling’s biggest race, the Tour de France. In 110 years, no British cyclist had ever won the event.&lt;/p&gt;

&lt;p&gt;Brailsford had been hired to put British Cycling on a new trajectory. What made him different from previous coaches was his relentless commitment to a strategy that he referred to as "the aggregation of marginal gains" which was the philosophy of searching for a tiny margin of improvement in everything you do.&lt;/p&gt;

&lt;p&gt;This philosophy works well for web application development. In particular, addressing the issue of bloated web applications that have too much Javascript.&lt;/p&gt;

&lt;p&gt;We need a new trajectory in front-end web apps; More HTML, CSS, Web components and a little Javascript.&lt;/p&gt;

&lt;p&gt;Just imagine how better the user experience will be.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>html</category>
      <category>css</category>
    </item>
    <item>
      <title>Introducing FicusJS</title>
      <dc:creator>Matt Levy</dc:creator>
      <pubDate>Thu, 15 Oct 2020 15:52:17 +0000</pubDate>
      <link>https://dev.to/ficusjs/introducing-ficusjs-3jc1</link>
      <guid>https://dev.to/ficusjs/introducing-ficusjs-3jc1</guid>
      <description>&lt;p&gt;FicusJS is a set of lightweight functions for developing applications using web components.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A function for creating fast, lightweight web components (1.88 KB gzipped)&lt;/li&gt;
&lt;li&gt;A function for creating fast, lightweight stores for application state (1.21 KB gzipped)&lt;/li&gt;
&lt;li&gt;A function for creating a fast, lightweight publish/subscribe event bus (271 B gzipped)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are looking for a fast, lightweight way to build web applications using native browser APIs, FicusJS might be what you are looking for!&lt;/p&gt;

&lt;p&gt;Browsers have improved a lot over the past years. It's now possible to do web development without requiring any build tools, using the native module loader of the browser. We think this is a great fit for FicusJS, and we recommend this as a general starting point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Aligns with standards
&lt;/h2&gt;

&lt;p&gt;FicusJS aligns with standard browser APIs which means it is not based on any proprietary code or libraries.&lt;/p&gt;

&lt;p&gt;As it is based on standards, it has longevity and is a good choice for enterprise web applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Functional programming patterns&lt;/li&gt;
&lt;li&gt;Declarative component creator&lt;/li&gt;
&lt;li&gt;Reactive components&lt;/li&gt;
&lt;li&gt;Choose your own renderer&lt;/li&gt;
&lt;li&gt;Extend components using functions&lt;/li&gt;
&lt;li&gt;Application state management with stores&lt;/li&gt;
&lt;li&gt;Application event bus&lt;/li&gt;
&lt;li&gt;Small footprint

&lt;ul&gt;
&lt;li&gt;All features - 3.54 KB gzipped&lt;/li&gt;
&lt;li&gt;Components - 1.88 KB gzipped&lt;/li&gt;
&lt;li&gt;Stores - 1.21 KB gzipped&lt;/li&gt;
&lt;li&gt;Event bus - 271 B gzipped&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Features can be loaded independently or use the all features bundle&lt;/li&gt;
&lt;li&gt;No dependencies&lt;/li&gt;
&lt;li&gt;Works with all server-side and client-side frameworks&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Documentation
&lt;/h2&gt;

&lt;p&gt;The full documentation is available at &lt;a href="https://docs.ficusjs.org"&gt;https://docs.ficusjs.org&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;To get started, you can use the FicusJS starter kit at &lt;a href="https://webcomponents.dev/create/ficus"&gt;WebComponents.dev&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  FicusJS router
&lt;/h2&gt;

&lt;p&gt;Looking for a lightweight standalone client-side router that supports history and hash routing plus web components?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://router.ficusjs.org"&gt;Try FicusJS router!&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  FicusJS script loader
&lt;/h2&gt;

&lt;p&gt;Looking for a lightweight script loader for lazy loading ES modules and ES5 scripts or both based on dynamic paths?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://script.ficusjs.org"&gt;Try FicusJS script loader!&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>typescript</category>
      <category>ficus</category>
    </item>
  </channel>
</rss>
