<?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>Forem: AsyncBanana</title>
    <description>The latest articles on Forem by AsyncBanana (@asyncbanana).</description>
    <link>https://forem.com/asyncbanana</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%2F393566%2Fdd039346-742a-46f6-8534-89bcbfd977a6.png</url>
      <title>Forem: AsyncBanana</title>
      <link>https://forem.com/asyncbanana</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/asyncbanana"/>
    <language>en</language>
    <item>
      <title>How to use ESM on the web and in Node.js</title>
      <dc:creator>AsyncBanana</dc:creator>
      <pubDate>Sat, 03 Sep 2022 16:19:28 +0000</pubDate>
      <link>https://forem.com/asyncbanana/how-to-use-esm-on-the-web-and-in-nodejs-3k04</link>
      <guid>https://forem.com/asyncbanana/how-to-use-esm-on-the-web-and-in-nodejs-3k04</guid>
      <description>&lt;p&gt;ESM (or ECMAScript Modules) is a modern module format with many advantages over previous formats like CommonJS. It is supported natively in most web browsers, is very fast, and opens up new opportunities for tree shaking, among other features. However, it is a major shift from CommonJS/AMD/UMD, and it can be hard to use if you are used to one of those module formats.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is ESM?
&lt;/h2&gt;

&lt;p&gt;ECMAScript Modules is a module format created as part of the ECMAScript (read: JavaScript) standard. It was standardized in the ES6 ECMAScript version, which you might know for adding many syntax features. ES Modules aims to solve a significant problem in JavaScript: There is no built-in way to share code between scripts. You might be familiar with importing things using &lt;code&gt;require()&lt;/code&gt;. That is using CommonJS, which is only supported in some bundlers and Node.js. Additionally, there are some problems with CommonJS, like its synchronous nature. ESM aims to solve all of these issues while making one module format universal. Today, Chrome, Safari, and Firefox fully support ESM, so you should not have any problem running it in modern browsers. Additionally, Node v12+ supports ESM, although you have to tell it you are using ESM rather than CommonJS. We will talk more about how to how to do this later on.&lt;/p&gt;

&lt;h2&gt;
  
  
  ESM Syntax
&lt;/h2&gt;

&lt;p&gt;The syntax used to import and export modules is a little more complicated than in other module systems like CommonJS, but it still is fairly easy to pick up. The most basic example is 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="c1"&gt;// script.js&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;example&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="s2"&gt;./library.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;example&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// library.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;example&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we import a function called &lt;code&gt;example&lt;/code&gt; from &lt;code&gt;library.js&lt;/code&gt;. Notice the brackets around &lt;code&gt;example&lt;/code&gt;. That shows that we are only importing &lt;code&gt;example&lt;/code&gt;. So if we wanted to import multiple things we could do 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;example&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;example2&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="s2"&gt;./library.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, we put both &lt;code&gt;example&lt;/code&gt; and &lt;code&gt;example2&lt;/code&gt; in between the brackets to import both of the exported variables. Now, what if there was only one thing exported? Using &lt;code&gt;export default&lt;/code&gt;, we can remove the brackets.&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;// script.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;defaultExample&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./library.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;defaultExample&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// library.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Default exports also allow us to name the imported value whatever we want. We can also do this with named exports, but it is a little more complicated:&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;example&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;newExampleName&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="s2"&gt;./library.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;newExampleName&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another thing you might want to do is dynamically import something. Dynamic imports work a lot like &lt;code&gt;require()&lt;/code&gt; in CommonJS, except that they run asynchronously:&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./library.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;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;library&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;library&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&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;Finally, you might want to import all functions in a module, which you can do using &lt;code&gt;import * as&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;// script.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;library&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./library.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;library&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;library&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example2&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// library.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;example&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;example2&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello world again&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;h2&gt;
  
  
  Using ESM with Node
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Make sure you are using Node v12 or higher&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Per-file
&lt;/h3&gt;

&lt;p&gt;The simplest way to use ESM in Node.js is to just replace &lt;code&gt;.js&lt;/code&gt; with &lt;code&gt;.mjs&lt;/code&gt; as the file extension for the script in which you want to use ESM. The new file extension tells Node that it should treat the file as ESM rather than CJS. This also works the other way. You can use &lt;code&gt;.cjs&lt;/code&gt; to designate a file as CommonJS if the default is ESM (more on that in the next section).&lt;/p&gt;

&lt;h3&gt;
  
  
  Package-wide
&lt;/h3&gt;

&lt;p&gt;Often you want a whole package to be ESM by default. To do this, you must add &lt;code&gt;"type": "module"&lt;/code&gt; to your &lt;code&gt;package.json&lt;/code&gt;. Adding &lt;code&gt;"type": "module"&lt;/code&gt; means files will be treated as ESM files unless they have a &lt;code&gt;.cjs&lt;/code&gt; extension. However, dependencies can still use CommonJS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Importing CJS Modules From ESM
&lt;/h3&gt;

&lt;p&gt;To ease the transition to ESM, Node offers the ability to load CommonJS modules from ESM. You can retrieve the &lt;code&gt;module.exports&lt;/code&gt; object by importing it as a default export. For 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="c1"&gt;// script.mjs&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;example&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;example-package&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;helloworld&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// example-package index.cjs&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;helloworld&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="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;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;This feature is very helpful as it allows you to use NPM packages built with CommonJS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Importing ES Modules from CJS
&lt;/h3&gt;

&lt;p&gt;Unfortunately, Node does not support importing ES Modules from CommonJS modules. Luckily, many compilers allow you to convert ESM to CommonJS, allowing you to write a library that offers a great experience for both groups. TypeScript is the most notable in this category. You can write code using ES Modules and target both ESM and CJS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Migrating from CJS To ESM
&lt;/h3&gt;

&lt;p&gt;There are tools to help make migrating code from CommonJS to ES Modules easy. One of the most popular tools is &lt;a href="https://github.com/wessberg/cjstoesm"&gt;cjstoesm&lt;/a&gt;, a command line tool that automatically transforms CommonJS code in Node to its ESM equivalent. Almost all CommonJS code is transformed. However, there are some things that are not transformed. The most notable is the &lt;code&gt;__dirname&lt;/code&gt;. &lt;code&gt;__dirname&lt;/code&gt; is not part of Node.js, but it is one thing that Node does not suppport in "ESM mode". Luckily, there are replacements. A simple way to polyfill &lt;code&gt;__dirname&lt;/code&gt; is to do 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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;__dirname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;pathname&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 uses &lt;code&gt;import.meta.url&lt;/code&gt;, which is available in all ESM contexts.&lt;/p&gt;

&lt;p&gt;Another thing that is harder to migrate is conditional imports. You can use dynamic importing to replace running &lt;code&gt;require()&lt;/code&gt; dynamically, but problems arise with that due to how &lt;code&gt;import()&lt;/code&gt; is asynchronous and &lt;code&gt;require()&lt;/code&gt; is not. Luckily, there is a simple solution to this. If you are using Node.js v14.8 or later, you can use &lt;a href="https://v8.dev/features/top-level-await"&gt;top-level await&lt;/a&gt; to make &lt;code&gt;import()&lt;/code&gt; synchronous. For 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="c1"&gt;// CommonJS&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;module1&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;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;module2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// ES Modules&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;boolean&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;module1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;module2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these tips, you should not have much trouble at all converting CommonJS code to ES Modules.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using ESM on the Web
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Native ESM
&lt;/h3&gt;

&lt;p&gt;The simplest way to use ESM on the web is by utilizing the native support for it. For about over 95% of users (&lt;a href="https://caniuse.com/es6-module"&gt;Caniuse&lt;/a&gt;), ESM is supported without polyfills. To load a script with ESM, you need to add &lt;code&gt;type="module"&lt;/code&gt; in the script tag.&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./esmscript.js&lt;/span&gt;&lt;span class="dl"&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="s2"&gt;module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, all modules you import from that script will also load as ES modules.&lt;/p&gt;

&lt;p&gt;To create a backup script for browsers that do not support ES Modules, you can use the &lt;code&gt;nomodule&lt;/code&gt; attribute. &lt;code&gt;nomodule&lt;/code&gt; tells any browser that supports ES Modules not to load the script, so only browsers without ESM support will load it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bundlers
&lt;/h3&gt;

&lt;p&gt;While just using the browser's native ESM support is simple to start with, you will be missing out on a lot of features and optimizations, like tree shaking, support for CommonJS dependencies or automatic fallback generation. Luckily, many bundlers support ESM by default. The most notable modern ESM bundlers for the web is &lt;a href="https://vitejs.dev/"&gt;Vite&lt;/a&gt;. Vite is a bundler created by the Vue team that is extremely fast and feature-rich. By default, Vite minifies and optimizes your code, and you can do a lot more with Vite/Rollup plugins. To create a Vite project, you have to run &lt;code&gt;npm create vite@latest&lt;/code&gt;. This will help you set up a project with Vite using ES Modules. If you want legacy browser support using &lt;code&gt;nomodule&lt;/code&gt;, you can use the plugin &lt;a href="https://github.com/vitejs/vite/tree/main/packages/plugin-legacy"&gt;@vitejs/plugin-legacy&lt;/a&gt;. Another feature that Vite, along with most other bundlers, has is support for dependencies that use CommonJS. Obviously, CommonJS requires transformation and therefore can add some code weight, but it is better than nothing, and you can still use ESM along with it.&lt;/p&gt;

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

&lt;p&gt;Now you are familiar with ES Modules' syntax and how to implement it on the web and in Node.js. Make sure to sign up for the newsletter or RSS &lt;a href="https://byteofdev.com/signup"&gt;here&lt;/a&gt;. I hope this article has been helpful for you, and thanks for reading.&lt;/p&gt;

</description>
      <category>esm</category>
      <category>node</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>React vs Svelte: Which is better in 2022?</title>
      <dc:creator>AsyncBanana</dc:creator>
      <pubDate>Tue, 30 Aug 2022 23:58:37 +0000</pubDate>
      <link>https://forem.com/asyncbanana/react-vs-svelte-which-is-better-in-2022-4291</link>
      <guid>https://forem.com/asyncbanana/react-vs-svelte-which-is-better-in-2022-4291</guid>
      <description>&lt;p&gt;Imagine you are &lt;a href="https://en.wikipedia.org/wiki/Doomscrolling"&gt;doomscrolling&lt;/a&gt; through Facebook, checking out the news on the New York Times' website, or listening to music on Spotify. As it turns out, all of these websites use either React or Svelte, along with many other popular websites. As you can see, React and Svelte are both very prevalent libraries (or frameworks, depending on how you define each). For many developers trying to plan their next website, they have to ask: "What should I use to build my app's interface?" This article aims to answer that question for React and Svelte. With that, let's get started on the comparison.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning Curve
&lt;/h2&gt;

&lt;h3&gt;
  
  
  React
&lt;/h3&gt;

&lt;p&gt;Let's start with React. React can take some time to adjust to, although it is usually not very hard to learn. The hardest part of React to learn is how it uses a declarative paradigm, unlike JavaScript, which is generally imperative. The difference is essentially this: with imperative JavaScript, you manipulate the DOM to represent the data using your own code, whereas with React, you simply update the data and tell React what part of the data goes where, and React will automatically update the DOM. Another more general way to explain this is with imperative coding you specify how to update the data whereas with declarative coding you only specify the data.&lt;/p&gt;

&lt;p&gt;There are some other things that take getting used to, but they are generally easy to learn. First, instead of HTML, you have to use JSX. JSX is like JavaScript and HTML combined, and it is what allows you to represent your data using declarative markup. For example, this would create a heading that contains whatever the JavaScript string &lt;code&gt;date&lt;/code&gt; is set to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, it is HTML enhanced using JavaScript.&lt;/p&gt;

&lt;p&gt;Finally, you will have to take some time to learn all of React's hooks (&lt;code&gt;useState()&lt;/code&gt;, &lt;code&gt;useEffect()&lt;/code&gt;, etc). However, this should not take long.&lt;/p&gt;

&lt;h3&gt;
  
  
  Svelte
&lt;/h3&gt;

&lt;p&gt;Svelte can take a little longer to learn. First, you still have to get used to writing declarative code. Svelte is very similar to React in that way, as they both are declarative (most other modern UI libraries also do this, including Vue and Angular). However, there are some differences in syntax that can make Svelte harder to learn than React. Unlike React, which uses JSX, Svelte has its own syntax for components. Instead of being defined inside functions (or classes), Svelte each have their own &lt;code&gt;.svelte&lt;/code&gt; file. This component design is known as SFC, or single file components. Using SFC has the advantage of allowing for more syntax flexibility, which Svelte uses. The syntax flexibility helps Svelte in some other areas, but it also makes learning Svelte harder. To show you, here is a sample Svelte component:&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&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;example&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;{test}&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag holds all of the component's JavaScript. That includes data, imports, and all of the logic. However, you still do need things like conditionals inside the markup. Unlike JSX, where you just embed a JavaScript function, Svelte has its own syntax for conditionals and loops. That is where things can get a little harder to learn. For example, if you are trying to conditionally add markup, you will have to use &lt;code&gt;#{if boolean}&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;{#if boolean}
&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;boolean is true&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
{/if}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need to do something similar for loops. Additionally, Svelte is more feature-rich, which is helpful but increases the time necessary to learn all of the features. For example, Svelte includes support for tweening values. One place where Svelte is better in terms of learning its state, as Svelte does not require you to use &lt;code&gt;usestate()&lt;/code&gt;. Instead, you can just reassign a variable in the component script and the component will automatically update with the new variable value.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;Both libraries require you to learn how to write declarative code, but React takes first here because of how it utilizes native JavaScript more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: React&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Syntax Brevity
&lt;/h2&gt;

&lt;h3&gt;
  
  
  React
&lt;/h3&gt;

&lt;p&gt;React's syntax is not super verbose, but it is not concise either. If you are using class components, it will be a lot more verbose. However, we will focus on using hooks and function components here. The biggest elements that contribute to its code size beyond the basic HTML is the state management (you need to use &lt;code&gt;useState()&lt;/code&gt; and &lt;code&gt;setState()&lt;/code&gt;) as well as how conditionals and loops work. However, React is still less verbose than some frameworks, as it cuts out most unnecessary boilerplate. For example, here we have a simple to-do list component. This component includes adding to-do items using a text input with the enter key or a button and then removing to-do items using the X button next to them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;TodoList&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;todos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTodos&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&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;newTodo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setNewTodo&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ol&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setTodos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;td&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;td&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;))}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class="nx"&gt;X&lt;/span&gt;
                        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="p"&gt;))}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ol&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;
                &lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="o"&gt;=&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;setTodos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;newTodo&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
                    &lt;span class="nx"&gt;setNewTodo&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="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="p"&gt;}}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&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="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                    &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;newTodo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nx"&gt;setNewTodo&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="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="p"&gt;}}&lt;/span&gt;
                &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&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="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Add&lt;/span&gt; &lt;span class="nx"&gt;Todo&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/form&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&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;As you can see, it is 34 lines long. We will create a functionally identical to-do list example in Svelte to compare.&lt;/p&gt;

&lt;h3&gt;
  
  
  Svelte
&lt;/h3&gt;

&lt;p&gt;Many of the same reasons Svelte lost the learning curve section give it an advantage here. The conditionals and loops are much more concise, and the state management is much simpler. Additionally, Svelte supports two-way bindings, meaning that the input value can be bound to &lt;code&gt;newTodo&lt;/code&gt; more simply. Because of these features, Svelte takes the lead for its to-do list component at only 25 lines.&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;newTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ol&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt; &lt;span class="nx"&gt;todos&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;td&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;td&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nx"&gt;X&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sr"&gt;/each&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ol&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;submit&lt;/span&gt;&lt;span class="o"&gt;=&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="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newTodo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nx"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;todos&lt;/span&gt;
            &lt;span class="nx"&gt;newTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&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;preventDefault&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&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="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;newTodo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&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="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;Add&lt;/span&gt; &lt;span class="nx"&gt;Todo&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/form&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Obviously, this is not a huge difference, but it can add up when you are building a large app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;Svelte's unique features, like using &lt;code&gt;{#if}&lt;/code&gt; for conditionals allow it to take the lead here. React is concise, but it still constrained by having to be implemented in plain JavaScript (aside from compiling JSX). The Svelte to-do list component was only 25 lines, compared to 34 lines for the same component implemented in React.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: Svelte&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;h3&gt;
  
  
  React
&lt;/h3&gt;

&lt;p&gt;React is not the most optimized library for building interfaces. It is extremely heavy, at 42kb minified and gzipped, and can be slow when rendering. However, there are some solutions to this. The primary solution is &lt;a href="https://preactjs.com/"&gt;Preact&lt;/a&gt;, which is a React-compatible library that is only 4kb minified and gzipped. Preact also includes features like the ability to use native HTML attributes in JSX instead of the JSX version. There are also libraries like &lt;a href="https://www.solidjs.com/"&gt;Solid&lt;/a&gt; and &lt;a href="https://www.infernojs.org/"&gt;Inferno&lt;/a&gt; which vary in terms of React compatibility and performance but are good alternatives to consider.&lt;/p&gt;

&lt;h3&gt;
  
  
  Svelte
&lt;/h3&gt;

&lt;p&gt;Svelte is very unique in that instead of providing a runtime API that you directly interface with, it runs your Svelte code through a compiler. While React technically also does this, all React does is transform JSX tags into JSX function calls. In contrast, Svelte code is completely transformed in the compilation process. This means that your website is usually light and fast since it avoids the overhead of high-level functions in a runtime library. However, with large apps, your compiled code can grow larger, although with code splitting this is usually not a big problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;While you can make React apps faster by using a tool like Preact, that is not built-in, so Svelte wins this category. Svelte's use of an optimizing compiler that removes the need for a large runtime makes Svelte extremely fast.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: Svelte&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Ecosystem
&lt;/h2&gt;

&lt;h3&gt;
  
  
  React
&lt;/h3&gt;

&lt;p&gt;React has the largest ecosystem out of any UI library. In fact, when you search for react on NPM, there are more than 200k packages that come up. This includes everything from &lt;a href="https://mui.com/"&gt;component libraries&lt;/a&gt; to &lt;a href="https://redux.js.org/"&gt;state containers&lt;/a&gt;. Additionally, Meta created and has developed its own ecosystem around React.&lt;/p&gt;

&lt;h3&gt;
  
  
  Svelte
&lt;/h3&gt;

&lt;p&gt;Svelte has a much smaller but quickly growing ecosystem. Currently, searching Svelte brings up about 5,000 packages. However, one thing to note is that Svelte includes tools like state management, so many ecosystem tools are unnecessary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;Ultimately, React wins by a large margin in this category. While Svelte's ecosystem is growing quickly, it is still nowhere near React.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: React&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;As you can see, it is tied 2-2, so you could choose either. If you are more of a beginner and want something that is easier to learn and has a larger ecosystem, choose React. Otherwise, if you want something that is fast to build with and runs fast, choose Svelte. Both are great choices. Thanks for reading, and make sure to sign up for the mailing list &lt;a href="https://byteofdev.com/signup"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>svelte</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>10 ways to speed up JavaScript loading</title>
      <dc:creator>AsyncBanana</dc:creator>
      <pubDate>Thu, 18 Aug 2022 19:02:51 +0000</pubDate>
      <link>https://forem.com/asyncbanana/10-ways-to-speed-up-javascript-loading-3lob</link>
      <guid>https://forem.com/asyncbanana/10-ways-to-speed-up-javascript-loading-3lob</guid>
      <description>&lt;p&gt;In many modern websites, there is a lot of JavaScript. In fact, according to the HTTP Archive, the average desktop page had over 500 kilobytes of JavaScript. The problem is that JavaScript takes time both to download and parse, which makes websites load much slower and therefore affects retention, as users will leave if a website takes too long to load. Luckily, there are easy ways to reduce the amount of JavaScript you are loading on your website and make the JavaScript you are loading load faster, which we will go over today.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to make your JavaScript load faster
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Lazy loading
&lt;/h3&gt;

&lt;p&gt;Not all JavaScript requires instant loading when a user first visits a website. For example, you could have an email signup prompt at the bottom of a page. Unless the user scrolls down to there, it is not necessary to load. Because of this, many web developers use a technique called lazy loading. Instead of loading all of the JavaScript at once, lazy loading offloads some JavaScript. There are multiple different forms of lazy loading. For example, for elements that do not need to be immediately active but still should be active fairly quickly, you could wait until the page is idle using &lt;code&gt;requestIdleCallback()&lt;/code&gt;. Or, as we have already talked about, if there is an interactive element further down the page, you could wait until the user scrolls down to that element using &lt;code&gt;intersectionObserver&lt;/code&gt;. Now, the question remains: How do you actually load the code later on? One of the best ways to do this is dynamic &lt;code&gt;import()&lt;/code&gt; which is part of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules"&gt;ECMAScript Modules (ESM)&lt;/a&gt;. Dynamic importing helps you load a script at any time by running an &lt;code&gt;import()&lt;/code&gt; function. For example, this would load a script once the browser was idle:&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;// Note: This must be run in an ESM script. You can use &amp;lt;script type="module"&amp;gt; instead of &amp;lt;script&amp;gt; to make this ESM&lt;/span&gt;
&lt;span class="nx"&gt;requestIdleCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/script.mjs&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;Another option is simply using the &lt;code&gt;async&lt;/code&gt; or &lt;code&gt;defer&lt;/code&gt; attribute on scripts. This technique is much less flexible, but it is an easy way to make a script wait until the DOM is assembled.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Minification
&lt;/h3&gt;

&lt;p&gt;Minification is an easy way to improve performance a lot. It is usually done using automated minfiers like &lt;a href="https://terser.org/"&gt;Terser&lt;/a&gt; or &lt;a href="https://esbuild.github.io/"&gt;ESBuild&lt;/a&gt;. These tools essentially shrink your code by removing spacing, long variable names, and other things that are helpful in development but increase script size in production. For example, let's say I minified this code with Terser:&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="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DOMContentLoaded&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;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;images&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="s2"&gt;img&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;for&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;image&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&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 output would be:&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="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DOMContentLoaded&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;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;t&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="s2"&gt;img&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;for&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;e&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&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="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;),&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="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&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;That is a 67-byte reduction, from 203 to 136 bytes! That little would not make a noticeable difference, but for larger scripts, minification can make quite an impact.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Bundling
&lt;/h3&gt;

&lt;p&gt;Script size is not the only thing that matters. The request count does too, as each request adds overhead. Basically, you want to keep the number of scripts you have to a minimum. However, splitting code is generally a code practice for keeping code clean. Luckily, like minifiers, there are automated tools to solve this. These are called bundlers. Bundlers analyze your code, look at what scripts are importing each other, and figure out how to combine them. The most well-known bundlers are &lt;a href="https://webpack.js.org/"&gt;Webpack&lt;/a&gt;, &lt;a href="https://www.rollupjs.org/guide/en/"&gt;Rollup&lt;/a&gt;, and &lt;a href="https://vitejs.dev/"&gt;Vite&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Another advantage of using a bundler is that most bundlers also function as build tools, making it easy to do things like minification and TypeScript compilation. For more information on bundlers, check out &lt;a href="https://byteofdev.com/posts/bundlers/"&gt;my article on them&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Code Splitting
&lt;/h3&gt;

&lt;p&gt;You might be surprised that this is right after bundling. "I bundle my code just to split it back up?" Not necessarily. In fact, this is a feature of bundlers. While reducing request count is great, you do not want the user to have to load all of the code on your website at once. You could solve this by creating a new full bundle for each page, but this would negate some of the benefits of caching (which we will talk about later). To solve this, we have code splitting. Code splitting combines the advantages of bundling and lazy loading while ensuring that any unnecessary code for the page is not loaded. Bundlers perform code splitting by analyzing a map of imports and figuring out what scripts are required to be in their own bundle. Most bundlers do this automatically, although it can be helpful to write code that is more easily analyzed (e.g. using static imports where possible).&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Tree Shaking
&lt;/h3&gt;

&lt;p&gt;Another common feature of bundlers is tree shaking. You might import a part of a library but not need the rest. However, if you do this without tree shaking, end users will end up loading the whole library, which can add a lot of JavaScript. Tree shaking solves this; Bundlers that support tree shaking automatically remove unused parts of libraries, heavily reducing the code you import. For example, take a look at Lodash (lodash-es to be specific), a large JavaScript utility library. The entire module is almost 100 kilobytes minified, but if you just used the &lt;code&gt;intersect()&lt;/code&gt; function, you would only import 2.7 kilobytes of code. Now, in Lodash's case, there are packages that only contain individual functions, but these can be more annoying to use if you are using a lot of functions, and many libraries do not do this.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. ECMAScript Modules
&lt;/h3&gt;

&lt;p&gt;For lots of the previously mentioned features to work, ECMAScript Modules (ESM) is very helpful or even essential. ESM is a module spec developed to standardize how to share code between different files. Before ESM, there were conflicting standards like CommonJS and UMD, which were not even natively supported by browsers. ESM unified these standards and offered syntax that helped with features like tree shaking (notice how I said to use lodash-es over standard lodash in the previous). Additionally, because ESM is natively supported in browsers, you do not need a heavy polyfill to be able to use ESM.&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;// ESM&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;something&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="s2"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;something&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// CJS&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;something&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;something&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;something&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  7. CDN
&lt;/h3&gt;

&lt;p&gt;Hosting static files on your own server is pointless. Using a full server for actual server-side computation increases your cost, development complexity, and website loading time. Instead, CDNs are better solutions. A CDN (Content Delivery Network) is a network of servers designed for serving static files quickly and cheaply. Instead of serving from just one server, you can serve files from tens or hundreds of servers (depending on the CDN), which reduces latency as the servers are closer to users. Additionally, CDNs often configure things like caching and compression for you, saving time. Some popular examples of CDNs are &lt;a href="https://www.cloudflare.com/cdn/"&gt;Cloudflare CDN&lt;/a&gt; and Amazon &lt;a href="https://aws.amazon.com/cloudfront/"&gt;CloudFront&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Caching
&lt;/h3&gt;

&lt;p&gt;While first load experience is essential, you also need to think about performance for repeat visitors of your website. One way to make repeat visits significantly faster is through caching. Browser caching works by saving a copy of website resources and using that copy instead of downloading it again. This means that repeat visits feel almost instantaneous. To set up caching, you need to set the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control"&gt;Cache-Control&lt;/a&gt; header in the response for the resource you are caching. If you are using a CDN, this is likely automatically configured for you. If you are not, it is simple enough to set up.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Compression
&lt;/h3&gt;

&lt;p&gt;I am sure you have come across &lt;code&gt;.zip&lt;/code&gt; or &lt;code&gt;.tag.gz&lt;/code&gt; files. You might also know that along with transforming a directory into a file, they also reduce the size of the files. The size reduction is done using compression. Compression works by running an algorithm to find ways to make a file smaller by shrinking repeated statements and doing some other things depending on the algorithm used. There are many popular compression algorithms, like deflate, lz4, Brotli, and Zstandard. The compression that zip and gzipped files use is deflate.&lt;/p&gt;

&lt;p&gt;Implementing compression can be a little hard to do, but there are simple ways to do it. The simplest way is to use a CDN that automatically compresses files, as we talked about at #7. Another simple way to implement compression is to run a file server that supports compression. However, if you cannot do either of those, there are some other solutions. Lots of build tools/bundlers have plugins that automatically generate compressed forms of files, which you can serve to have the browser automatically decompress it. The browser tells you what compression algorithms it supports using the &lt;code&gt;Accept-Encoding&lt;/code&gt; header, and your server tells the browser what compression algorithm is used in the response using the &lt;code&gt;Content-Encoding&lt;/code&gt; header. For more information, check out &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Compression"&gt;MDN's article on HTTP Compression&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Lighthouse &amp;amp; Automated Performance Auditing
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://developer.chrome.com/docs/devtools/speed/get-started/"&gt;Lighthouse&lt;/a&gt; is a tool that helps you automatically audit your website's performance, along with a few other categories like SEO and Accessibility. It can be extremely helpful for finding performance issues and providing an easy path to solving them. If you have Chrome or another Chromium-based browser, Lighthouse should be available by default. If you are using another browser, you could download the extension or use &lt;a href="https://pagespeed.web.dev/"&gt;PageSpeed Insights&lt;/a&gt;. PageSpeed Insights also offers data from real users, which can be helpful if you want to see what users are actually experiencing.&lt;/p&gt;

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

&lt;p&gt;With these tips, you should achieve large performance gains in your website, translating to more retention and conversion. Thanks for reading!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>performance</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>What is Bun, and does it live up to the hype?</title>
      <dc:creator>AsyncBanana</dc:creator>
      <pubDate>Wed, 17 Aug 2022 00:41:49 +0000</pubDate>
      <link>https://forem.com/asyncbanana/what-is-bun-and-does-it-live-up-to-the-hype-4k3a</link>
      <guid>https://forem.com/asyncbanana/what-is-bun-and-does-it-live-up-to-the-hype-4k3a</guid>
      <description>&lt;p&gt;When you think of a bun, you probably think of bread. However, now, there is another Bun. &lt;a href="https://bun.sh"&gt;Bun&lt;/a&gt; is a new JavaScript runtime that claims to offer more features and performance than Node.js and &lt;a href="https://byteofdev.com/posts/deno/"&gt;Deno&lt;/a&gt;. It was created by Jarred Sumner and only was released publicly a little more than a month ago.&lt;br&gt;
Since then, it has quickly managed to gain 30,000 stars. In this article, we will investigate what bun is and whether Bun lives up to its hype.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; Bun is very experimental. Many features do not work. For information on unfinished features, check out &lt;a href="https://github.com/oven-sh/bun/issues/159"&gt;Bun's Roadmap&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why is Bun supposed to be better than Node.js or Deno.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2F_HybIn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ik.imagekit.io/serenity/ByteofDev/Blog_Content_Images/bun_sgTvWFIaT" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2F_HybIn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ik.imagekit.io/serenity/ByteofDev/Blog_Content_Images/bun_sgTvWFIaT" alt="Bunch of buns" title="Have a bun stock photo; Photo by Gil Ndjouwou on Unsplash" width="880" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bun is a runtime designed around a few central principles:&lt;/p&gt;

&lt;p&gt;First, Bun is designed to start and run faster than Node.js and Deno. It claims that it is significantly faster than both server-side JavaScript runtimes through its use of JavaScriptCore rather than V8, its use of Zig for API writing, and lots of tuning and benchmarking.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Quick guide to JavaScript engines: V8 is the engine created by Google for Chrome and JavaScriptCore is the engine created by Apple for Safari. Node.js and Deno both use V8, whereas Bun uses JavaScriptCore.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;According to benchmarks done by the creators of Bun, Bun can be over 2x the speed of Node.js and Deno in I/O intensive operations like HTTP servers and SQL. These claims might sound ludicrous. After all, it is all JavaScript, and V8 is pretty optimized. However, notice I said &lt;strong&gt;I/O intensive&lt;/strong&gt;. That means most of the execution time is spent in the runtime's API rather than the actual JavaScript engine. Since Bun &lt;em&gt;theoretically&lt;/em&gt; has a much faster I/O implementation than Node.js or Deno, Bun could be much faster in these cases. Later on, we will run our own benchmarks to see how much more performant the I/O implementation and JavaScript engine is.&lt;/p&gt;

&lt;p&gt;Second, Bun is "batteries included." I sort of lied when I said Bun was a JavaScript runtime. It is much more than just that. Similar to Deno, it includes a bundler, TypeScript transpiler, and even a test runner. Additionally, Bun includes a CSS-in-JS tool, template builder, environment variable loader, and more. This feature is very interesting, as performance-optimized and expansive usually do not go together in developer tools. However, Bun managed to do this because they do not have the same code weight constraint as web libraries do. Theoretically, while another feature built into Bun increases the installation size, it should not impact performance. Additionally, the tools built into Bun are designed to run quicker than most alternatives. Of course, you still might prefer the choice. Ultimately, it is just your preference (of course, you can still use other tools).&lt;/p&gt;

&lt;p&gt;Finally, Bun is designed to be Node-compatible. Bun includes full support for CommonJS (&lt;code&gt;require()&lt;/code&gt; is transformed into &lt;code&gt;import.meta.require()&lt;/code&gt; in Node.js modules), Node-API, and some Node.js modules. This feature is extremely helpful, as it allows you to access the vast ecosystems of Node.js. However, there are still many things not implemented, as Bun is still early software and Node's API is extensive, so we will see how well it actually works later on.&lt;/p&gt;

&lt;p&gt;Now, we see how Bun is supposed to improve over existing server-side JavaScript runtimes. Let's look at how it stacks up in its current form.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is Bun Fulfilling its promises?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qAOQuMzQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ik.imagekit.io/serenity/ByteofDev/Blog_Content_Images/bun_LwO522f5Z" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qAOQuMzQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ik.imagekit.io/serenity/ByteofDev/Blog_Content_Images/bun_LwO522f5Z" alt="Cinnamon bun" title="Another tasty-looking bun; Photo by Jonathan Ocampo on Unsplash" width="880" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;On the website, Bun lists some benchmark results. Now, we will check out the benchmark code and run it ourselves. We will be running the FFI, Log, gzip, Async, and SQLite benchmarks.&lt;/p&gt;

&lt;h4&gt;
  
  
  Benchmark Explanation
&lt;/h4&gt;

&lt;p&gt;First, let's look at the FFI benchmark. The FFI benchmark is pretty simple. The Bun, Node, and Deno program all call a Rust program through FFI, which exposes a few functions: An empty function, a long string, and a hash.&lt;/p&gt;

&lt;p&gt;Next, there is the Log benchmark. As the name implies, the log benchmark focuses on the performance of &lt;code&gt;console.log()&lt;/code&gt;. First, the programs log &lt;code&gt;"hello"&lt;/code&gt;, and then they log &lt;code&gt;{ hello: "object"}&lt;/code&gt;. The code across all of the runtimes is identical.&lt;/p&gt;

&lt;p&gt;Now, let's check out the gzip benchmark. The gzip benchmark benchmarks roundtrip, compressing, and decompressing &lt;code&gt;"Hello World!"&lt;/code&gt; repeated 1,000 times. The Node.js implementation used its built-in zlib module, Deno used the web standard CompressionStream API, and Bun used its own built-in gzip compression. This test is good because it shows the differences in each implementation of gzip compression/decompression, rather than using the same library for each.&lt;/p&gt;

&lt;p&gt;Now, let's take a look at the async benchmark. The code in this test is identical across runtimes. They benchmark a synchronous empty function, an asynchronous empty function, and an asynchronous function running &lt;code&gt;await 1&lt;/code&gt;. It seems odd that they do not do more, but it still seems ok.&lt;/p&gt;

&lt;p&gt;Finally, we have the SQLite benchmark. The benchmark performs a few queries on the &lt;a href="https://github.com/jpwhite3/northwind-SQLite3/"&gt;Northwind SQLite database&lt;/a&gt; (which is the standard "Hello World" for SQL). Node uses better-sqlite3, Deno uses deno-sqlite, and Bun uses its built-in SQLite implementation. This benchmark seems like it is just trying to show that Bun's Zig SQLite implementation is fast, although it is a little unfair to Deno as deno-sqlite uses &lt;a href="https://byteofdev.com/posts/webassembly/"&gt;WASM&lt;/a&gt;, which often brings a performance disadvantage and therefore means that there can be faster Deno SQLite implementations.&lt;/p&gt;

&lt;p&gt;Whew! That was a lot. Now we can get on to the interesting part: the actual results. For context, I am running Linux 5.18 on a Ryzen 6900HS with 16 Gigabytes of DDR5 memory, and the speed is measured by average time per run.&lt;/p&gt;

&lt;h4&gt;
  
  
  Benchmark Results
&lt;/h4&gt;

&lt;h5&gt;
  
  
  FFI
&lt;/h5&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test&lt;/th&gt;
&lt;th&gt;Bun&lt;/th&gt;
&lt;th&gt;Node.js&lt;/th&gt;
&lt;th&gt;Deno&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Noop&lt;/td&gt;
&lt;td&gt;4.93 ns&lt;/td&gt;
&lt;td&gt;11.51 ns&lt;/td&gt;
&lt;td&gt;3.91 ns 🏆&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hash&lt;/td&gt;
&lt;td&gt;66.93 ns&lt;/td&gt;
&lt;td&gt;177.48 ns&lt;/td&gt;
&lt;td&gt;59.89 ns 🏆&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;190.93 ns&lt;/td&gt;
&lt;td&gt;51.97 ns 🏆&lt;/td&gt;
&lt;td&gt;127.01 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In this test, Bun was a bit of a mixed bag. It did about as well as Node but generally worse than Deno. The results were not bad, but they were not such a great start for something claiming significant performance advantages. However, part of it might be because I am testing this on a completely different CPU and architecture than the creator of Bun, and therefore what I am using might not be optimized yet.&lt;/p&gt;

&lt;h5&gt;
  
  
  Log
&lt;/h5&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test&lt;/th&gt;
&lt;th&gt;Bun&lt;/th&gt;
&lt;th&gt;Node.js&lt;/th&gt;
&lt;th&gt;Deno&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;console.log('hello')&lt;/td&gt;
&lt;td&gt;642.26 ns 🏆&lt;/td&gt;
&lt;td&gt;1,610 ns&lt;/td&gt;
&lt;td&gt;3,960 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;console.log({ hello: 'object'})&lt;/td&gt;
&lt;td&gt;893.41 ns 🏆&lt;/td&gt;
&lt;td&gt;2,700 ns&lt;/td&gt;
&lt;td&gt;6,750 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Now we are seeing some speed! Bun won both tests by a large margin. I assume this is because of Bun's static optimization, which is great to see.&lt;/p&gt;

&lt;h6&gt;
  
  
  gzip
&lt;/h6&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test&lt;/th&gt;
&lt;th&gt;Bun&lt;/th&gt;
&lt;th&gt;Node.js&lt;/th&gt;
&lt;th&gt;Deno&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;roundtrip - "Hello World!".repeat(9999))&lt;/td&gt;
&lt;td&gt;260.85 µs 🏆&lt;/td&gt;
&lt;td&gt;478.23 µs&lt;/td&gt;
&lt;td&gt;476.81 µs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gzipSync("Hello World!".repeat(9999)))&lt;/td&gt;
&lt;td&gt;201.1 µs 🏆&lt;/td&gt;
&lt;td&gt;397.02 µs&lt;/td&gt;
&lt;td&gt;281.01 µs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gunzipSync("Hello World!".repeat(9999)))&lt;/td&gt;
&lt;td&gt;62.85 µs 🏆&lt;/td&gt;
&lt;td&gt;70.33 µs&lt;/td&gt;
&lt;td&gt;152.52 µs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Once again, Bun wins all benchmarks. I suspect this is because Bun's gzip implementation is optimized and written in Zig.&lt;/p&gt;

&lt;h5&gt;
  
  
  Async
&lt;/h5&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test&lt;/th&gt;
&lt;th&gt;Bun&lt;/th&gt;
&lt;th&gt;Node.js&lt;/th&gt;
&lt;th&gt;Deno&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sync&lt;/td&gt;
&lt;td&gt;225.34 ps&lt;/td&gt;
&lt;td&gt;222.76 ps 🏆&lt;/td&gt;
&lt;td&gt;228.55 ps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Async&lt;/td&gt;
&lt;td&gt;162.28 ns&lt;/td&gt;
&lt;td&gt;58.62 ns 🏆&lt;/td&gt;
&lt;td&gt;59.4 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Await 1&lt;/td&gt;
&lt;td&gt;274.72 ns&lt;/td&gt;
&lt;td&gt;110.44 ns&lt;/td&gt;
&lt;td&gt;101.38 ns 🏆&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Bun did not do so well on this benchmark and got last in two of the three benchmarks by a large margin, probably because of some element of JavaScriptCore.&lt;/p&gt;

&lt;h5&gt;
  
  
  SQLite
&lt;/h5&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test&lt;/th&gt;
&lt;th&gt;Bun&lt;/th&gt;
&lt;th&gt;Node.js&lt;/th&gt;
&lt;th&gt;Deno&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SELECT * FROM "Order"&lt;/td&gt;
&lt;td&gt;18.74 ms 🏆&lt;/td&gt;
&lt;td&gt;52.49 ms&lt;/td&gt;
&lt;td&gt;135.07 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SELECT * FROM "Product"&lt;/td&gt;
&lt;td&gt;46.85 µs 🏆&lt;/td&gt;
&lt;td&gt;160.91 µs&lt;/td&gt;
&lt;td&gt;232.57 µs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SELECT * FROM "OrderDetail"&lt;/td&gt;
&lt;td&gt;213.36 ms 🏆&lt;/td&gt;
&lt;td&gt;1.05 s&lt;/td&gt;
&lt;td&gt;663.34 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This was an excellent final benchmark for Bun. Bun beat both Node and Deno by a large margin on every benchmark, showing just how fast Bun's Zig SQLite implementation is.&lt;/p&gt;

&lt;h4&gt;
  
  
  Summary
&lt;/h4&gt;

&lt;p&gt;Overall, I was somewhat disappointed by these results. Given the benchmarks Bun shows on its website, I would have expected it to be significantly faster than Node.js and Deno in most or all benchmarks. But, of course, the creators of Bun would focus on the most positive benchmarks rather than showing them indiscriminately. Nonetheless, Bun performed pretty well, especially given it is still in a very early stage and more optimizations are planned in the future.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extra Features
&lt;/h3&gt;

&lt;p&gt;One of Bun's main selling points is the extra features. We will review some of the most significant additional features and see how well they work.&lt;/p&gt;

&lt;h4&gt;
  
  
  Task Runner
&lt;/h4&gt;

&lt;p&gt;Bun's task runner is like the task runner included in Node, except it is noticeably faster. In fact, it is even possible to use Bun's task manager in a Node project and take advantage of how fast it is. While a task runner is an expected essential tool (both Node/NPM and Deno include one by default), I decided to include it here because it is so much faster than the ones in NPM and Deno. Additionally, Bun's task manager can run almost any script without using the run subcommand, whereas npm can only do that for a few select script names.&lt;/p&gt;

&lt;h4&gt;
  
  
  Package Manager
&lt;/h4&gt;

&lt;p&gt;Once again, a package manager is expected, but Bun's package manager exceeds expectations because of its performance. In fact, Bun should be even faster than PNPM or Yarn. There are three reasons for that. First, Bun uses symlinks. That means that packages for each project are linked to a central location, so modules used in another project do not need to be redownloaded. Second, Bun uses a binary lockfile. Binary files are usually serialized and deserialized faster, which decreases the overall time used by the package manager. Finally, Bun's package manager is written in Zig. As we have already discussed, Zig is a fast language, much faster than JavaScript, which most other JavaScript package managers use.&lt;/p&gt;

&lt;h4&gt;
  
  
  Transpiler
&lt;/h4&gt;

&lt;p&gt;Bun's transpiler is a great feature, which transpiles TypeScript, JSX, and even vanilla JavaScript. You might have been suprised to hear the last part. After all, why would you need to transpile plain JavaScript? Here is where one of Bun's performance-improving features comes in. Bun automatically optimizes JavaScript ahead of time. Most of this feature is still in development, but the developers plan to add an optimized binary format for JavaScript in the future. These optimizations would have very interesting implications for edge apps and other short-lived processes. However, we can't talk about it much yet because most of it is still in development.&lt;/p&gt;

&lt;p&gt;The other transpilers are pretty good. The TypeScript transpiler is fast, although it does not have type checking currently, instead just stripping types (you are expected to use your text editor/IDE to type check). The JSX transpiler also works pretty well, although for many cases, it would not work well due to the lack of &lt;a href="https://babeljs.io/docs/en/babel-preset-typescript#jsxpragma"&gt;@jsxpragma support&lt;/a&gt;, meaning you can only use React, not Preact or any other JSX library/framework. I was able to set up a react app by simply running &lt;code&gt;bun create react&lt;/code&gt;, which was pretty nice (no &lt;code&gt;react-scripts&lt;/code&gt; used!). This also shows the CSS importing, as one of the JSX files imports CSS, which works seamlessly.&lt;/p&gt;

&lt;h4&gt;
  
  
  File loaders
&lt;/h4&gt;

&lt;p&gt;A helpful feature of Bun is how it supports many filetypes by default. For example, you can load a YAML or TOML file by simply importing it. In my testing, this functioned quite well, although &lt;code&gt;bun-types&lt;/code&gt; did not seem to signal to TypeScript that &lt;code&gt;.toml&lt;/code&gt; files were supported, which made my editor flag the &lt;code&gt;.toml&lt;/code&gt; import. You could likely fix this with a quick type declaration file, and &lt;code&gt;bun-types&lt;/code&gt; should eventually fix this.&lt;/p&gt;

&lt;p&gt;Additionally, environment variables from .env files automatically. Creating a &lt;code&gt;.env&lt;/code&gt; file in the project directory will automatically load the variables into &lt;code&gt;process.env&lt;/code&gt; and &lt;code&gt;Bun.env&lt;/code&gt;. In my testing, Bun successfully found the &lt;code&gt;.env&lt;/code&gt; file and loaded the variables in &lt;code&gt;process.env&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Summary
&lt;/h4&gt;

&lt;p&gt;Bun has a very good feature set. There are some rough edges and unfinished features, but it can still be very helpful for quickly creating a project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Node.js compatibility
&lt;/h3&gt;

&lt;p&gt;Now let's see how well Bun can work with Node.js modules currently. Out of all of them, I expect this element to be the most unfinished, but it will still be interesting to see how Bun fares.&lt;/p&gt;

&lt;h4&gt;
  
  
  Next.js
&lt;/h4&gt;

&lt;p&gt;This one is an easy one to find out, because Bun supports Next.js by default. However, the support currently has some issues. First, you need to rerun &lt;code&gt;bun --use-next&lt;/code&gt; whenever you import a new module. This issue could become annoying, although the developers of Bun are working to create an automatic solution for this. Second, Bun does not currently support features like &lt;code&gt;getStaticPaths&lt;/code&gt;, API routes, and React Server Components. This is probably the biggest issue, as these features are quite important. Additionally, locales and all of &lt;code&gt;next.config.js&lt;/code&gt; are unsupported. Basically, Next.js works on Bun, but it is not near feature complete yet.&lt;/p&gt;

&lt;h4&gt;
  
  
  Vite
&lt;/h4&gt;

&lt;p&gt;Vite is a popular bundler, used by frameworks like SvelteKit and Astro. Unfortunately, Bun does not support Vite at all, as many Node modules used in Vite are not part of Bun yet (&lt;code&gt;https&lt;/code&gt;,&lt;code&gt;child_process&lt;/code&gt;, &lt;code&gt;perf_hooks&lt;/code&gt;, etc). Luckily, &lt;a href="https://github.com/oven-sh/bun/issues/250"&gt;Bun is working on Vite support&lt;/a&gt;, so hopefully we will see Vite working on Bun soon.&lt;/p&gt;

&lt;h4&gt;
  
  
  Express
&lt;/h4&gt;

&lt;p&gt;Express works, but only to a minimal extent. Even basic examples are malfunctioning and, once again, modules like &lt;code&gt;https&lt;/code&gt; are missing. Luckily, &lt;a href="https://github.com/oven-sh/bun/issues/496"&gt;Bun is working on it&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Summary
&lt;/h4&gt;

&lt;p&gt;Overall, it seems like Node.js compatibility is nowhere near where it needs to be, but that is an ongoing focus of development, so I expect this to change as development progresses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison with Node and Deno
&lt;/h2&gt;

&lt;p&gt;Now we will see how Bun compares to Node.js and Deno in general:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Element&lt;/th&gt;
&lt;th&gt;Bun&lt;/th&gt;
&lt;th&gt;Node&lt;/th&gt;
&lt;th&gt;Deno&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Created&lt;/td&gt;
&lt;td&gt;2021&lt;/td&gt;
&lt;td&gt;2009&lt;/td&gt;
&lt;td&gt;2018&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Created By&lt;/td&gt;
&lt;td&gt;Jarred Sumner&lt;/td&gt;
&lt;td&gt;Ryan Dahl&lt;/td&gt;
&lt;td&gt;Ryan Dahl&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Language Written in&lt;/td&gt;
&lt;td&gt;Zig&lt;/td&gt;
&lt;td&gt;C++&lt;/td&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JavaScript Engine&lt;/td&gt;
&lt;td&gt;JavaScriptCore&lt;/td&gt;
&lt;td&gt;V8&lt;/td&gt;
&lt;td&gt;V8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ecosystem&lt;/td&gt;
&lt;td&gt;Very small&lt;/td&gt;
&lt;td&gt;Very large&lt;/td&gt;
&lt;td&gt;Small&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Benchmarks in First&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Benchmarks in Last&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Package Manager&lt;/td&gt;
&lt;td&gt;bun install&lt;/td&gt;
&lt;td&gt;npm&lt;/td&gt;
&lt;td&gt;URL-based packaging&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TypeScript Support&lt;/td&gt;
&lt;td&gt;🟢&lt;/td&gt;
&lt;td&gt;🔴&lt;/td&gt;
&lt;td&gt;🟢&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JSX Support&lt;/td&gt;
&lt;td&gt;🟢&lt;/td&gt;
&lt;td&gt;🔴&lt;/td&gt;
&lt;td&gt;🟢&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WebAssembly Support&lt;/td&gt;
&lt;td&gt;🟢&lt;/td&gt;
&lt;td&gt;🟢&lt;/td&gt;
&lt;td&gt;🟢&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Permissions System*&lt;/td&gt;
&lt;td&gt;🔴&lt;/td&gt;
&lt;td&gt;🔴&lt;/td&gt;
&lt;td&gt;🟢&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Testing Framework&lt;/td&gt;
&lt;td&gt;🟢&lt;/td&gt;
&lt;td&gt;🔴&lt;/td&gt;
&lt;td&gt;🟢&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web Compatibility&lt;/td&gt;
&lt;td&gt;🟡&lt;/td&gt;
&lt;td&gt;🟡&lt;/td&gt;
&lt;td&gt;🟢&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node Compatibility&lt;/td&gt;
&lt;td&gt;🟡&lt;/td&gt;
&lt;td&gt;🟢&lt;/td&gt;
&lt;td&gt;🟡&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MacOS Support&lt;/td&gt;
&lt;td&gt;🟢&lt;/td&gt;
&lt;td&gt;🟢&lt;/td&gt;
&lt;td&gt;🟢&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linux Support&lt;/td&gt;
&lt;td&gt;🟢&lt;/td&gt;
&lt;td&gt;🟢&lt;/td&gt;
&lt;td&gt;🟢&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows Support&lt;/td&gt;
&lt;td&gt;🟡*&lt;/td&gt;
&lt;td&gt;🟢&lt;/td&gt;
&lt;td&gt;🟢&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;* Windows supported through WSL. Native support in progress&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q9QyMssR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ik.imagekit.io/serenity/ByteofDev/Blog_Content_Images/bun_ExONxYgu4" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q9QyMssR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ik.imagekit.io/serenity/ByteofDev/Blog_Content_Images/bun_ExONxYgu4" alt="Group of buns in a basket" title="I am hungry now; Photo by Photo by César Guel on Unsplash" width="870" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bun is a very promising project. Initially, I was skeptical of Bun, especially of its use of JavaScriptCore rather than V8, but after this, I am now convinced that Bun has a lot of potential. Currently, the ecosystem and uneven Node support is stopping me from using Bun that much, but the development of Bun is moving along very quickly, so I expect Node compatibility to improve a lot over the next few months/year. Additionally, the Bun ecosystem should grow quickly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Bun's Node.js support and ecosystem currently limit it, but it is very promising for the future.&lt;/p&gt;

&lt;p&gt;I hope you learned something from this, and thanks for reading.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>webdev</category>
      <category>bunjs</category>
    </item>
    <item>
      <title>State of JS 2021 Results and Analysis</title>
      <dc:creator>AsyncBanana</dc:creator>
      <pubDate>Mon, 21 Feb 2022 04:24:34 +0000</pubDate>
      <link>https://forem.com/asyncbanana/state-of-js-2021-results-and-analysis-5mj</link>
      <guid>https://forem.com/asyncbanana/state-of-js-2021-results-and-analysis-5mj</guid>
      <description>&lt;p&gt;This week for State of the Web, we have a special edition about one of the most extensive surveys in web development, the State of JS. State of JS is a survey about everything related to JavaScript, including language features, front-end frameworks, and bundlers. This year's version, the 2021/2022 version, collected more than 15,000 responses. This article looks at the results and what they mean for web development.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There are a few terms in this that mean things specific to this survey:&lt;br&gt;
&lt;strong&gt;Usage&lt;/strong&gt;: The percentage of people that have used the library or feature out of the total survey takers&lt;br&gt;
&lt;strong&gt;Awareness&lt;/strong&gt;: The percentage of people who know about a feature/library out of the total survey takers&lt;br&gt;
&lt;strong&gt;Interest&lt;/strong&gt;: (Only for libraries) The percentage of people that want to learn a library out of everyone who does not already use that library&lt;br&gt;
&lt;strong&gt;Satisfaction&lt;/strong&gt;: (Only for libraries) The percentage of people who have used a library and are satisfied out of everyone who has used that library&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Languages Features + Web APIs
&lt;/h2&gt;

&lt;p&gt;First, let's look at the usage of modern language features and web APIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Language Features
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Nullish Coalescing (??) and Optional Chaining (?.) Quickly Grow
&lt;/h4&gt;

&lt;p&gt;Two new features in JavaScript, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator"&gt;nullish coalescing&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining"&gt;optional chaining&lt;/a&gt;, have grown quickly. Nullish coalescing is a feature that allows you to return the right-hand side of the operator if the left-hand side is null, and optional chaining allows you to return &lt;code&gt;undefined&lt;/code&gt; when accessing properties of a nonexistent object instead of erroring.&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;// Nullish coalescing&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="c1"&gt;// returns 1&lt;/span&gt;
&lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="c1"&gt;// returns 2&lt;/span&gt;

&lt;span class="c1"&gt;// Optional chaining&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="c1"&gt;// errors&lt;/span&gt;
&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="c1"&gt;// returns undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These methods have been gaining momentum quickly, with more than 65% of users reporting to have used nullish coalescing and &amp;gt;75% using optional chaining. This is despite being introduced in ES2020. They have most likely grown so much because they help provide clearer, more efficient code, they are easy to adopt, and you can easily transpile them into older syntax using something like Babel or ESBuild.&lt;/p&gt;

&lt;h3&gt;
  
  
  ESM Dynamic Imports are gaining steam
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#dynamic_imports"&gt;Dynamic importing&lt;/a&gt; is a way to dynamically load ECMAScript Modules, similar to how you could call &lt;code&gt;require()&lt;/code&gt; dynamically for CommonJS. If you have not heard of ESM before, it is a module format introduced in ES6 that is native to browsers. However, before dynamic importing, you had to import modules statically at the top of your JavaScript module. Static imports are helpful for tree shaking and static analysis, but sometimes you need to import things dynamically. Now, you can run the function &lt;code&gt;import()&lt;/code&gt; to import modules.&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;// Static importing&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;something&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./example.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// Always has to be at the top of the file&lt;/span&gt;
&lt;span class="c1"&gt;// Dynamic importing&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;something&lt;/span&gt; &lt;span class="o"&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="s2"&gt;./example.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dynamic importing opens doors to ESM code splitting, lazy loading, and more. Because of all these features, dynamic importing has grown a lot, with almost 50% of users reporting to have used it. This feature is also related to a newer feature, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await#top_level_await"&gt;top level await&lt;/a&gt;, as top-level await makes it possible to import modules dynamically outside of am async function. Top-level await very new but already has 31% usage according to State of JS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Web APIs
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Service workers and PWAs are mainstream
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API"&gt;Service Workers&lt;/a&gt; are scripts that can intercept HTTP requests coming from websites, which allows for more advanced caching, offline access, and other network capabilities. They have been around for a few years now and have steadily gained usage. In this survey, they come in at 45% usage. The growth of service workers is bolstered by Progressive Web Apps (PWAs), which usually require service workers and have a usage rate of 52.3%. Progressive web apps are web apps that can you can install like a native app and &lt;a href="https://developers.google.com/web/updates/capabilities"&gt;include many native capabilities&lt;/a&gt;. The high usage rate is surprising, especially since Firefox does not support PWAs and has stated they do not intend to do so.&lt;/p&gt;

&lt;h4&gt;
  
  
  WebAssembly is growing but is still uncommon
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/WebAssembly"&gt;WebAssembly&lt;/a&gt; is an Assembly-like language designed for the web and serverless. It can be faster than JavaScript, and allows you to use a wider variety of languages that compile to WebAssembly, but its usage rate is still low, at 15.6%. That still growing (usage was only at 10.5% in 2020), and awareness is very high at 97.9%, but it still has not gone mainstream. That is likely due to how hard it is to adopt (you need to learn another language) and the smaller ecosystem. To learn more about WebAssembly, check out this &lt;a href="https://byteofdev.com/posts/webassembly"&gt;State of the Web webassembly article&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Websockets are very popular
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API"&gt;Websockets&lt;/a&gt; are connections designed for real-time communication both from client to server and server to client. More than half of the respondents to State of JS 2022 said they had used Websockets before, making it the most well-used browser API. That is likely due to the wide use cases, from real-time chat to gaming to streaming analytics, and the fact that the Websocket browser API has been around for a long time and is supported in browsers like IE 11.&lt;/p&gt;

&lt;h4&gt;
  
  
  WebGL is well known but uncommonly used
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Getting_started_with_WebGL"&gt;WebGL&lt;/a&gt; is a browser API that enables web developers to create graphical applications with an OpenGL ES-like interface. While most people are aware of it (87.6%), only 21.6% of people actually use it. That is likely because of the WebGL learning curve, as well as the alternatives to WebGl, like SVG, and, more notably, Canvas. Another interesting related browser API is &lt;a href="https://web.dev/gpu/"&gt;WebGPU&lt;/a&gt;, which mirrors the Vulkan API and is being standardized.&lt;/p&gt;

&lt;h2&gt;
  
  
  Libraries
&lt;/h2&gt;

&lt;p&gt;Almost any web developer is using bundlers, frameworks, and more. Because everyone needs them, there are many different JavaScript tools, and it can be hard to choose between them. Now we will look at the state of libraries like bundlers, frameworks, mobile/desktop tools, and monorepo tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Front-end frameworks
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k9c4E1Ya--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ik.imagekit.io/serenity/ByteofDev/Blog_Content_Images/front_end_frameworks_experience_ranking" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k9c4E1Ya--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ik.imagekit.io/serenity/ByteofDev/Blog_Content_Images/front_end_frameworks_experience_ranking" alt="Satisfaction of front-end frameworks" width="880" height="890"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  React keeps the crown of usage
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt; has been the most popular front-end framework in the State of JS for 5 years and continues this tradition this year. React has a usage rate of 80%, significantly higher than the next most popular framework, Angular (at 54%). React is popular because it is relatively stable and established and has a lower learning curve than something like Angular. For more information on why Facebook created React and its current state, take a look at &lt;a href="https://byteofdev.com/posts/react/"&gt;State of the Web: React&lt;/a&gt;. However, newer frameworks have some advantages over React, which this article covers later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vue is steadily growing
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://vuejs.org/"&gt;Vue&lt;/a&gt; is a newer alternative to React that has grown over the past few years. It now has a 51% usage rate and seems like it could surpass React in the future. Vue has the advantage of a different template syntax and is faster, both in loading speed and runtime performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Svelte and Solid take the highest satisfaction
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://svelte.dev/"&gt;Svelte&lt;/a&gt; and &lt;a href="https://www.solidjs.com/"&gt;Solid&lt;/a&gt; lead the front-end frameworks in satisfaction, both with 90%. Svelte has been around for a few years and offers a concise template syntax and a compiler that compiles to native JavaScript. Developers use Svelte for its performance and the power of the templating language, which offers things like two-way binding and the ability to update the DOM by reassigning a variable with data rather than having to use something like &lt;code&gt;setState()&lt;/code&gt;. Svelte has already gained some usage, with a 20% usage rate.&lt;/p&gt;

&lt;p&gt;On the other hand, Solid is a newer framework closer to React but is the fastest framework by far. Solid uses the same JSX and hooks patterns but has a different updating system that removes the need for a virtual DOM and the need to reevaluate components every time the state is changed. Solid's bundle size is also significant smaller than React's. In contrast to Svelte, since Solid is newer, it has much less usage, at 3%.&lt;/p&gt;

&lt;h4&gt;
  
  
  Other interesting newer frameworks
&lt;/h4&gt;

&lt;p&gt;There are some other newer frameworks, like Lit, Alpine.js, and Stimulus. Lit is a web component-based framework that aims to offer an easy to use layer over web components. It has only 7% usage but 40% interest. Alpine.js is another interesting framework that is special in that you use attributes inside HTML to control behavior. However, I cannot recommend it, as it does not have very good runtime performance. Alpine is slightly lower than Lit with usage and interest, at 6% and 33%. Finally, Stimulus is another framework that is part of the &lt;a href="https://hotwired.dev/"&gt;Hotwire&lt;/a&gt; project. Stimulus is somewhat like Alpine, although it relies a little less on HTML attributes. It is designed to compliment Hotwire Turbo, which provides HTML AJAX, by making it possible to add small bits of interactivity where needed. Stimulus is the smallest framework, with 2% usage and 21% interest.&lt;/p&gt;

&lt;h3&gt;
  
  
  Backend Frameworks
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hYOUBbeL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ik.imagekit.io/serenity/ByteofDev/Blog_Content_Images/back_end_frameworks_experience_ranking" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hYOUBbeL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ik.imagekit.io/serenity/ByteofDev/Blog_Content_Images/back_end_frameworks_experience_ranking" alt="Satisfaction of backend frameworks" width="880" height="1021"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Express is the top framework by far
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://expressjs.com/"&gt;Express&lt;/a&gt; is a basic Node.js backend framework that provides routing and middleware. That simplicity has made it the most used backend framework by a large margin, with 80% usage, compared to 45% for the next highest, Next.js. Express also tops awareness and does moderately well in interest at 59%. Additionally, Express is growing, so it does not seem like it will soon lose its throne.&lt;/p&gt;

&lt;h4&gt;
  
  
  Front-end framework based frameworks are growing
&lt;/h4&gt;

&lt;p&gt;Nowadays, many backend frameworks use front-end frameworks. For example, take the second most popular backend framework, &lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt;. Next.js is built for React. In fact, about half of the frameworks in State of JS integrate with various front-end frameworks like React, Vue, and Svelte. This trend is quickly growing as people look for alternatives to running a Single Page App (SPA) due to SPA's SEO and performance.&lt;/p&gt;

&lt;h4&gt;
  
  
  SvelteKit has the happiest developers
&lt;/h4&gt;

&lt;p&gt;Once again, we see Svelte. However, this time it is for Svelte's official framework, &lt;a href="https://kit.svelte.dev/"&gt;SvelteKit&lt;/a&gt;. SvelteKit offers built-in server-side rendering and static generation for Svelte websites, as well as other helpful features for Svelte developers. SvelteKit is like Next.js, but it is the official Svelte backend framework, and it is for Svelte, not React. Because Svelte has such high satisfaction and SvelteKit works very well with Svelte, SvelteKit has a satisfaction rate of 96%, which is the highest satisfaction out of all the backend frameworks.&lt;/p&gt;

&lt;h4&gt;
  
  
  Other new frameworks like Remix and Astro have high satisfaction
&lt;/h4&gt;

&lt;p&gt;There is a group of frameworks at 91% satisfaction. They are Astro, Fastify, Next.js, and Remix. Next.js is not new, but all of the other frameworks are, and each brings new features to the table.&lt;/p&gt;

&lt;h5&gt;
  
  
  Next.js
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt; has been around for a few years and is established as the most popular framework for React, but it has still managed to match or do better than other newer frameworks in satisfaction. However, Next.js satisfaction has decreased after peaking at 92%, although that is not a huge drop.&lt;/p&gt;

&lt;h5&gt;
  
  
  Fastify
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://www.fastify.io/"&gt;Fastify&lt;/a&gt; is unique in that it is not designed to be used with a front-end framework. Instead, it is more like Express, just significantly faster. According to &lt;a href="https://www.fastify.io/benchmarks/"&gt;Fastify's own benchmarks&lt;/a&gt;, Fastify is more than 3x faster than Express. Fastify also offers built-in support for JSON parsing and JSON Schema. Fastify's performance has given it 11% usage and 60% interest, which is not bad for a new Express alternative.&lt;/p&gt;

&lt;h5&gt;
  
  
  Remix
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://remix.run/"&gt;Remix&lt;/a&gt; is a React backend framework created by the creators of React Router, the most popular client-side router for React used today. Remix focuses on web fundamentals, server-side rendering, and advanced routing to improve performance and user experience. Remix is also designed to have support for multiple serverless providers just like SvelteKit. Because of all of its features, Remix is growing at a fast pace. It only has 5% usage due to it being released very recently, but it already has 69% interest and, of course, 91% satisfaction.&lt;/p&gt;

&lt;h5&gt;
  
  
  Astro
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://astro.build/"&gt;Astro&lt;/a&gt; is probably the most innovative of the bunch. Not only does it offer partial hydration on the component level using &lt;a href="https://jasonformat.com/islands-architecture/"&gt;the "Islands" architecture&lt;/a&gt;, it also supports multiple different client-side frameworks. You can even use multiple at the same time. For example, you could code most of your site in Svelte but then use React for one component and avoid hydrating the components that are not needed to be interactive, even if other components on the page need to be interactive. These features brought Astro 3% usage and 66% interest, despite Astro being published partway through 2021.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vyD3cFnh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ik.imagekit.io/serenity/ByteofDev/Blog_Content_Images/testing_experience_ranking" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vyD3cFnh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ik.imagekit.io/serenity/ByteofDev/Blog_Content_Images/testing_experience_ranking" alt="Satisfaction of testing tools" width="880" height="934"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Jest remains the most popular
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://jestjs.io/"&gt;Jest&lt;/a&gt;, an easy-to-use testing library from Facebook, is the most popular JavaScript testing library. It has a usage rate of 73%, which is significantly higher than the next most popular's, Mocha (50%). Jest's popularity is due to its ease of use and speed.&lt;/p&gt;

&lt;h4&gt;
  
  
  Testing library takes satisfaction
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://testing-library.com/"&gt;Testing Library&lt;/a&gt; is another testing library that ranks the highest for satisfaction, with a satisfaction rate of 96%. Additionally, Testing Library has moderately high usage, at 35%. The interesting thing about Testing Library is that it is not a testing runtime, nor is it a test runner. What is does it provides a querying toolkit that can be used on DOM runtimes like Jest or a real browser. The querying toolkit tries to mimic user behavior, which helps you make better UI tests.&lt;/p&gt;

&lt;h4&gt;
  
  
  Vitest makes testing fast
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://vitest.dev/"&gt;Vitest&lt;/a&gt; is a mostly Jest compatible testing framework that uses Vite under the hood. Using Vite makes Vitest significantly faster than Jest and makes it possible to use only one build pipeline for testing and building if you use Vite already. Vitetest has been well received, with satisfaction at 94% and interest at 82%. In fact, the most modern testing pipeline you could use is probably Testing Library running on Vitest.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build Tools
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I-RbEYWG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ik.imagekit.io/serenity/ByteofDev/Blog_Content_Images/build_tools_experience_ranking" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I-RbEYWG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ik.imagekit.io/serenity/ByteofDev/Blog_Content_Images/build_tools_experience_ranking" alt="Satisfaction of build tools" width="880" height="978"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Webpack is the most used
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://webpack.js.org/"&gt;Webpack&lt;/a&gt; is the most used bundler/build tool (no surprises here). That is because Webpack was created when the alternatives were much worse, and it has been able to retain its dominant position. However, it is now being challenging by alternatives like Vite, so its future domination is uncertain.&lt;/p&gt;

&lt;h4&gt;
  
  
  Vite is becoming the next big thing in bundling
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://vitejs.dev/"&gt;Vite&lt;/a&gt; is a bundler that has quickly grown to 30% usage and is used by frameworks like SvelteKit and Astro, despite only becoming public in the past two years. Vite also has the highest satisfaction rating, at 98%. Most people attribute Vite's popularity to its &lt;a href="https://byteofdev.com/posts/bundlers/#unbundled-development"&gt;massive speed improvements due to ESM&lt;/a&gt; and easy configuration. Vite's growth is also bolstered by the fact that was created by the team behind Vue and is used in modern Vue frameworks like Vitepress.&lt;/p&gt;

&lt;h4&gt;
  
  
  esbuild and SWC are climbing quickly
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://esbuild.github.io/"&gt;esbuild&lt;/a&gt; and &lt;a href="https://swc.rs/"&gt;SWC&lt;/a&gt; are both JavaScript build tools that are significantly faster than previous tools due to the choice to use languages like Go and Rust, as well as better multithreaded design. They replace tools like Babel and Terser and can be tens of times faster. That speed has brought large amounts of interest (81% for esbuild and 75% for SWC) and satisfaction (96% and 94% for esbuild and SWC, respectively). SWC is especially notable, as Next.js recently adopted it, so it has a bright future ahead.&lt;/p&gt;

&lt;h4&gt;
  
  
  tsc CLI is quietly becoming popular
&lt;/h4&gt;

&lt;p&gt;Surprisingly, the &lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt; CLI is the second most popular build tool after Webpack, at 79% usage. The usage was up from 62% in the 2020 survey, so the usage is proliferating. The TypeScript CLI is the main way to compile TypeScript projects. However, projects like esbuild and SWCD offer TypeScript compilation, and TypeScript cannot do much beyond compiling TypeScript.&lt;/p&gt;

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

&lt;p&gt;Whew! That was a lot. If you want to view the full results, you can look at &lt;a href="https://2021.stateofjs.com/en-US/"&gt;2021 State of JS Results&lt;/a&gt;. If you enjoyed reading this article, be sure to subscribe to RSS and join the mailing list &lt;a href="https://byteofdev.com/signup/"&gt;here&lt;/a&gt;. I hope you learned about a new tool today, and thanks for reading!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
      <category>node</category>
    </item>
    <item>
      <title>State of the Web: React</title>
      <dc:creator>AsyncBanana</dc:creator>
      <pubDate>Sun, 13 Feb 2022 20:56:53 +0000</pubDate>
      <link>https://forem.com/asyncbanana/state-of-the-web-react-40kf</link>
      <guid>https://forem.com/asyncbanana/state-of-the-web-react-40kf</guid>
      <description>&lt;p&gt;React is one of the most popular JavaScript frameworks out there. While many other frameworks offer some advantages, React has retained dominance. There is also a vast ecosystem around React, which is changing quickly. This article aims to provide an overview of the recent trends in React, like Remix, server components, partial hydration, and more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background of React
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Bolt &amp;amp; FaxJS
&lt;/h3&gt;

&lt;p&gt;Around a decade ago, Facebook started looking for a way to modernize its web app. It was becoming increasingly complicated, and they needed a framework to make it easier to build and maintain. To fix this, they created a project called Bolt. Bolt was an MVC framework built on top of JavelinJS, and it solved many of the problems Facebook had. However, it was not perfect. Jordan Walke, a developer at Facebook, created the next iteration of Bolt, called &lt;a href="https://github.com/jordwalke/FaxJs"&gt;FaxJS&lt;/a&gt;. It offered many features that React has today, like rendering on both client and server, DOM diffing, and more. Jordan Walke renamed FaxJS FBolt and started using it in Facebook's codebase.&lt;/p&gt;

&lt;h3&gt;
  
  
  React's creation
&lt;/h3&gt;

&lt;p&gt;In 2013, Facebook renamed FBolt, you guessed it, React. Additionally, they started working on JSX, an abstraction layer for defining UI in React. JSX made compiling HTML like statements to JavaScript function calls. Interestingly, according to &lt;a href="https://reactjs.org/blog/2016/09/28/our-first-50000-stars.html#adding-jsx"&gt;a post by the React team&lt;/a&gt;, JSX was initially based on a system in PHP that allowed for embedding XML literals. JSX was initially just a fork of &lt;a href="https://github.com/laverdet/js-xml-literal"&gt;jsx-xml-literal&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Initial Growth
&lt;/h3&gt;

&lt;p&gt;React started growing quite a bit after that. React's GitHub repository reached 10k stars in late 2014, 20k in 2015, and 50k in 2016. Additionally, React's ecosystem started to grow with things like &lt;a href="https://www.reactiflux.com/"&gt;Reactiflux&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hooks
&lt;/h3&gt;

&lt;p&gt;Hooks are ways of defining lifecycle methods in functional components. In 2019, React released hooks, which completely changed the way people wrote applications in React. Before hooks existed, you had to use classes for stateful components. Functional components could only be simple components that just relied on props. However, hooks offered a way of accessing state through functions, which opened the door to completely using functional components. Nowadays, most new applications use hooks instead of class components, as hooks are simpler to use and more concise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why People use React
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Dynamic updating
&lt;/h3&gt;

&lt;p&gt;React automatically updates your UI if your data changes, saving a significant amount of time. For example, if you had a table of various transactions set to update every 15 seconds, you would have to define the difference checking and updating manually. However, with a framework like React, you can just change the value of the data, and everything happens for you. Dynamic updating also makes your UI easier to reason with, as you can guarantee it represents the data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Isomorphic rendering
&lt;/h3&gt;

&lt;p&gt;React can render UI on both the client and server with the same code. That opens up opportunities for server-side rendering and hydrating on the client. In this way, React contrasts with lots of traditional templating languages where you could generate static HTML but not make that automatically interactive.&lt;/p&gt;

&lt;p&gt;React does this through two different APIs. Their primary rendering API function exposed through &lt;code&gt;react-dom&lt;/code&gt; is &lt;code&gt;render&lt;/code&gt;, which renders the JSX passed on to the client. However, to render HTML on the server, there is &lt;code&gt;renderToString&lt;/code&gt; under &lt;code&gt;react-dom/server&lt;/code&gt;, which renders static HTML that can be hydrated later using &lt;code&gt;render&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advanced templating
&lt;/h3&gt;

&lt;p&gt;React allows you to do many things to reduce repetition in your code, including embedding JavaScript and modularizing markup inside components. These features help reduce repetition and the maintenance burden by making it easier to update repeated pieces of markup.&lt;/p&gt;

&lt;h2&gt;
  
  
  The State of React
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Remix and the new React frameworks
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://remix.run"&gt;Remix&lt;/a&gt; is a new React framework (like Next.js), created by the people who made React Router, that was only recently open-sourced but has been growing very quickly. Remix promises better integration with web platform features, integration with the edge, and simpler isomorphic code. Remix has already managed to gain 12k stars. Another unique thing about Remix is that instead of offering static site generation and dynamic server-side rendering, it focuses entirely on server-side rendering. That means that while Remix does not support static site generation, if you prefer rendering dynamic data on the server rather than using API fetching on the client, Remix works quite well. Of course, there are tradeoffs to both rendering on the server and fetching data on the client for dynamic data, and it depends on your use case. Finally, due to the author's experience building React Router, Remix has advanced routing, with features like nested routing and isolated errors.&lt;/p&gt;

&lt;p&gt;Remix is not the only new React framework. There are others, like &lt;a href="https://astro.build/"&gt;Astro&lt;/a&gt;. Astro is a promising &lt;a href="https://byteofdev.com/posts/static-site-generators/"&gt;static site generator&lt;/a&gt; that supports multiple ways of building UI, including React. Astro is also notable because it supports partial hydration, which reduces the JavaScript sent to the client by only including what is needed to make your web app interactive.&lt;/p&gt;

&lt;h3&gt;
  
  
  React 18
&lt;/h3&gt;

&lt;p&gt;React 18 is an upcoming React release that offers many new features, like the concurrent renderer. The concurrent renderer allows for multiple versions of the UI to be built at once, which opens up opportunities for new features like automatic batched updates, streaming server-side rendering, and more. These features help improve performance. For example, automatic batched updates reduce the amount of UI updates needed, which increases performance on the client.&lt;/p&gt;

&lt;h3&gt;
  
  
  CSS
&lt;/h3&gt;

&lt;p&gt;There are numerous approaches to using CSS in React. Of course, you can use native CSS, but there are many other approaches that work better with React's UI style.&lt;/p&gt;

&lt;h4&gt;
  
  
  CSS in JS
&lt;/h4&gt;

&lt;p&gt;CSS in JS integrates with React very well. The most popular CSS in JS tool is &lt;a href="https://www.npmjs.com/package/styled-components"&gt;styled-components&lt;/a&gt;, which allows you to define styles inside JavaScript using tagged templates. However, there are newer approaches to CSS in JS that are often superior in certain ways. Some of the most interesting of those are Linaria and vanilla-extract. &lt;a href="https://linaria.dev/"&gt;Linaria&lt;/a&gt; is a library that aims to optimize CSS in JS by compiling CSS in JS to native CSS. Linaria also has built-in React integration, making it easier to add dynamic styling without a high runtime cost. &lt;a href="https://vanilla-extract.style/"&gt;vanilla-extract&lt;/a&gt; does the same thing but better integrates with TypeScript and offers features like building custom utility styles.&lt;/p&gt;

&lt;h4&gt;
  
  
  Atomic CSS
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://byteofdev.com/posts/atomic-css/"&gt;Atomic CSS&lt;/a&gt; works well with React due to its scoping. Since the styles are atomic, they are automatically scoped to just the elements that use them, making it easier to reason about styling with components. Additionally, Atomic CSS's repetition can be solved using components. Some of the most notable Atomic CSS libraries currently are &lt;a href="https://tailwindcss.com/"&gt;Tailwind&lt;/a&gt; and &lt;a href="https://github.com/unocss/unocss"&gt;UnoCSS&lt;/a&gt;. Tailwind is, by far, the most dominant Atomic CSS library out there due to its wide variety of features and ease of use. UnoCSS is a more recent project that is significantly faster and more flexible than Tailwind.&lt;/p&gt;

&lt;h3&gt;
  
  
  Faster React Replacements
&lt;/h3&gt;

&lt;p&gt;While React has many advantages, performance is not one of them. Luckily, there are replacements for React that retain a identical or almost identical API. The most notable are &lt;a href="https://preactjs.com/"&gt;Preact&lt;/a&gt; and &lt;a href="https://www.solidjs.com/"&gt;Solid&lt;/a&gt;. First, we have Preact. Preact is faster and significantly smaller (3kb Gzipped) than React while having an identical API. You can use Preact almost anywhere, and it can be used as a drop in replace with &lt;code&gt;preact/compat&lt;/code&gt;. Second, there is Solid. Solid does not have an identical API to React, but the ways it differs allows it to get a large performance advantage. In terms of runtime performance, Solid is significantly faster than both Preact and React. Solid achieves this by forgoing a virtual DOM and building components only once instead of whenever state updates. Solid is also smaller than React, although it is a bit bigger than Preact.&lt;/p&gt;

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

&lt;p&gt;I hope you learned something from this today. If you enjoyed reading this, sign up for the mailing list &lt;a href="https://byteofdev.com/signup"&gt;here&lt;/a&gt; and subscribe to RSS to get more of these articles. Thanks for reading!&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>10 ways to speed up web font loading</title>
      <dc:creator>AsyncBanana</dc:creator>
      <pubDate>Fri, 11 Feb 2022 01:17:56 +0000</pubDate>
      <link>https://forem.com/asyncbanana/10-ways-to-speed-up-web-font-loading-1i0i</link>
      <guid>https://forem.com/asyncbanana/10-ways-to-speed-up-web-font-loading-1i0i</guid>
      <description>&lt;p&gt;Fonts are popular tools on the web nowadays. Most modern websites use custom fonts, usually from Google Fonts, because it adds a custom touch to the interface and allows for more options. However, there are many performance implications with fonts on the web. Fonts are often hundreds of kilobytes and are on another domain, slowing down the website. Luckily, you can solve these problems. Here are ten tips to improve font loading performance on a website.&lt;/p&gt;

&lt;h2&gt;
  
  
  The list
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Self your fonts
&lt;/h3&gt;

&lt;p&gt;When you go on a website, you often see something like this:&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.googleapis.com"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&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="na"&gt;crossorigin&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&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;That means the website is using Google Fonts to load fonts. Google Fonts is excellent for prototyping, as it is straightforward but is terrible for performance. Performance is bad because Google Fonts has a complicated string of requests to get a font, which adds significant latency.&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%2Fik.imagekit.io%2Fserenity%2FByteofDev%2FBlog_Content_Images%2FGoogle_Fonts_Loading" 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%2Fik.imagekit.io%2Fserenity%2FByteofDev%2FBlog_Content_Images%2FGoogle_Fonts_Loading" alt="Google font loading diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the font loading with Google Fonts can be complicated. However, you can reduce how many requests are needed to just one by self-hosting the font and putting the &lt;code&gt;@font-face&lt;/code&gt; declaration inside your CSS bundle instead of an external stylesheet. A tool like &lt;a href="https://google-webfonts-helper.herokuapp.com/" rel="noopener noreferrer"&gt;Google Webfonts Helper&lt;/a&gt; can be helpful for this.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Use modern web font formats
&lt;/h3&gt;

&lt;p&gt;Fonts are like images on the web because of how their formats work. With images, modern web formats like AVIF and WebP replaced less compressed formats like PNG and JPEG. Similarly, web fonts have WOFF and WOFF2, which provide superior compression to formats like TrueType and OpenType (TTF and OTF). Additionally, web fonts are almost universally supported:&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%2Fik.imagekit.io%2Fserenity%2FByteofDev%2FBlog_Content_Images%2FWOFF_Support" 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%2Fik.imagekit.io%2Fserenity%2FByteofDev%2FBlog_Content_Images%2FWOFF_Support" alt="WOFF Support from CanIUse (98.36% of users support it)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point, because of the almost universal browser support, the best thing to do is use WOFF2 with a WOFF fallback, although you could even just use WOFF2, as ~96% of users support it.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Subset your fonts
&lt;/h3&gt;

&lt;p&gt;Font subsetting means trimming your fonts down to only the characters you need. Subsetting can yield massive amounts of size savings without having any drawbacks as long as you are not using the characters you remove. The simplest way to do this is subsetting to remove languages that you do not use. For example, take Inter, one of the most popular fonts. If you include all languages, which includes the Latin alphabet, Cyrillic, Vietnamese, and Greek, the size of the WOFF2 font is &lt;strong&gt;95kb&lt;/strong&gt;. However, chances are you are not using all of those languages. If you remove all characters outside of the English language, the size is reduced to just &lt;strong&gt;16kb&lt;/strong&gt;! There are many ways to subset fonts, including Google Fonts (and by extension, Google Webfonts Helper), &lt;a href="https://everythingfonts.com/subsetter" rel="noopener noreferrer"&gt;Everything Fonts&lt;/a&gt;, and &lt;a href="https://github.com/fonttools/fonttools" rel="noopener noreferrer"&gt;fontTools&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The size reduction is beneficial for performance, but you can do even better if you are willing to take on more complexity. Instead of subsetting by wide character ranges, you can subset to include precisely what you use. Tools like fontTools allow you to subset fonts by arbitrary character lists. The problem with this approach is that you need a complicated build process to get every character you use. Or, of course, you can manually add each character, but that is a lot of work 🙁.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Use font-display
&lt;/h3&gt;

&lt;p&gt;By default, text will not show up in many browsers until the correct font is loading. That behavior is called Flash of Invisible Text, or FOIT. Some other browsers display text using the fallback font while it is loading, which makes sure text is not invisible but can cause a &lt;a href="https://web.dev/optimize-cls/#web-fonts-causing-foutfoit" rel="noopener noreferrer"&gt;layout shift&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Luckily, you can customize font loading through the &lt;code&gt;font-display&lt;/code&gt; option in your &lt;code&gt;@font-face&lt;/code&gt; declaration. The two recommended values for &lt;code&gt;font-display&lt;/code&gt; are &lt;code&gt;swap&lt;/code&gt; and &lt;code&gt;optional&lt;/code&gt;. &lt;code&gt;swap&lt;/code&gt; uses a fallback font and then switches to the custom font once it is loaded, and &lt;code&gt;optional&lt;/code&gt; blocks page load for a maximum of 100ms to let the font load, and if it does not, it uses a fallback font.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="k"&gt;@font-face&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;'Example'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;normal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;400&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;'Example'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;'Example'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sx"&gt;url(https://example.com/example.woff2)&lt;/span&gt; &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;'woff2'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;font-display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;swap&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;&lt;code&gt;font-display: optional&lt;/code&gt; is the best for when you don't need the font to be loaded because it prevents any layout shift and ensures the text is not invisible. However, &lt;code&gt;font-display: swap&lt;/code&gt; is best when you need the font to load because it swaps in the font even if it takes more than 100ms.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Match your fallback font with your custom font
&lt;/h3&gt;

&lt;p&gt;Fonts are usually spaced and sized differently. For example, Merriweather is larger than Georgia, even if the CSS font size is the same. These inconsistencies can cause a layout shift if you use &lt;code&gt;font-display: swap&lt;/code&gt; and make fonts less consistent if you use &lt;code&gt;font-display: optional&lt;/code&gt;. Luckily, you can configure your fallback font to look a lot more like the web font you are using. Matching both fonts can be done by customizing spacing and font size to remove the inconsistencies. A helpful tool for this is &lt;a href="https://meowni.ca/font-style-matcher/" rel="noopener noreferrer"&gt;Font Style Matcher&lt;/a&gt;, which allows you to look at two different fonts, configure various spacing properties, and see a demo of the layout shift.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Use a CDN
&lt;/h3&gt;

&lt;p&gt;CDNs are great for speeding up static content delivery. They deliver content closer to your users and often offer other ways of speeding up delivery. It is a good idea to host your fonts on a CDN, along with all of your other static assets. Using a CDN also has the advantage of reducing server costs, as CDNs are generally cheaper compared to serving the request from your source server.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Preload your fonts
&lt;/h3&gt;

&lt;p&gt;Preloading is often a good idea for various resources, as it makes the browser know it needs to download a resource sooner and increases that resource's priority. It is the same idea for fonts. However, you do not always want to preload your fonts because it might make a font load unnecessarily. That is because the browser automatically detects whether the website uses a font on the page before downloading it, even if the &lt;code&gt;@font-face&lt;/code&gt; is present. Now, you might know that you always use the fonts you include with &lt;code&gt;@font-face&lt;/code&gt;. There is one other potential problem. If your font is low priority, it might make other resources take longer to load. However, if both of these things are not true, preloading can be a great way to speed up your font loading.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Use local()
&lt;/h3&gt;

&lt;p&gt;Depending on the font, users can often have the font you are using locally installed on their machine. If they do, you can easily use the font locally to prevent any performance degradation from a custom font. You do this using a &lt;code&gt;local()&lt;/code&gt; statement in your &lt;code&gt;@font-face&lt;/code&gt; &lt;code&gt;src&lt;/code&gt; rule.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="k"&gt;@font-face&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;'Awesome Font'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;normal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;400&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;'Awesome Font'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sx"&gt;url('example.com/awesome-font.woff2')&lt;/span&gt; &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;'woff2'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This &lt;code&gt;@font-face&lt;/code&gt; checks if the user has the font locally, and if they do not, downloads it remotely. That means that users with the font get a free performance boost while adding little complexity to the code and no disadvantage to users who do not have the font locally.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Implement Caching
&lt;/h3&gt;

&lt;p&gt;Caching is very important, especially if you have lots of repeat visitors. Caching allows the font to load from the disk after the first time it is downloaded. You can implement caching through the &lt;code&gt;Cache-Control&lt;/code&gt; header. If you use a CDN like Cloudflare, it is simple to do from the dashboard. Otherwise, you can do it by simply sending the header with your font responses.&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Don't use custom fonts
&lt;/h3&gt;

&lt;p&gt;I bet you didn't see that one coming 😉. I am talking about &lt;a href="https://systemfontstack.com/" rel="noopener noreferrer"&gt;system font stacks&lt;/a&gt;. System fonts are great for body text or other text that isn't important for branding, as it is built-in and makes the interface more comfortable because it is the same font as the operating system.&lt;br&gt;
You can implement system UI fonts through the system font stacks linked above or the &lt;code&gt;system-ui&lt;/code&gt; font family.&lt;/p&gt;

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

&lt;p&gt;That is all! I hope you enjoyed learning how to optimize your web fonts, and I hope this has helped you optimize fonts on your websites. If you enjoyed reading this, be sure to sign up for the mailing list &lt;a href="https://byteofdev.com/signup" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Thanks for reading!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>performance</category>
      <category>html</category>
      <category>css</category>
    </item>
    <item>
      <title>State of the Web: Static Site Generators</title>
      <dc:creator>AsyncBanana</dc:creator>
      <pubDate>Sun, 30 Jan 2022 20:22:20 +0000</pubDate>
      <link>https://forem.com/asyncbanana/state-of-the-web-static-site-generators-g6f</link>
      <guid>https://forem.com/asyncbanana/state-of-the-web-static-site-generators-g6f</guid>
      <description>&lt;p&gt;Static site generators (SSGs) can be beneficial for making large websites without reducing performance. They have existed for more than a decade, but they have evolved a lot, especially more recently due to the rise of "Jamstack." This article goes over the background of static site generators, why people use them, and the current state of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background of Static Site Generators
&lt;/h2&gt;

&lt;p&gt;Static websites have risen and fallen across the lifetime of the internet. The first websites were fully static, built-in plain HTML. This worked well for the first websites because it was straightforward, as there is no build process and you need nothing more than a simple static file web server, and most websites did not need much more functionality. However, as the web started to evolve, this changed. Eventually, people started using server-side languages to dynamically generate HTML, using languages like PHP, Ruby, and Perl. This was the beginning of the usage of dynamic websites.&lt;/p&gt;

&lt;h3&gt;
  
  
  The rise of CMSs
&lt;/h3&gt;

&lt;p&gt;Not everyone who writes knows how to program too. Because of that, it was hard for people who did not know how to program to manage content. That is why people created CMSs. CMSs made it easy for marketers to create and manage content without touching code. The first CMSs were enterprise CMSs like FileNet and Documentum (now OpenText). However, as many people know, this did not last forever. A few years later, in 2003, Matt Mullenweg and Mike Little created &lt;a href="https://wordpress.org/"&gt;WordPress&lt;/a&gt;. WordPress' was completely open-source and quickly grew to become the most popular CMS on the web, and it still is. However, while it became popular, WordPress did not make everyone happy. This is where static site generators come in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Jekyll and the first static site generators
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;I was tired of complicated blogging engines like WordPress and Mephisto. I wanted to write great posts, not style a zillion template pages, moderate comments all day long, and constantly lag behind the latest software release.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This excerpt is from &lt;a href="https://tom.preston-werner.com/2008/11/17/blogging-like-a-hacker.html"&gt;Tom Preston Warner's announcement of Jekyll&lt;/a&gt;, and it started the rise of static site generators. Instead of using basic HTML pages, static sites would bring the more advanced tools like Liquid. Unlike WordPress, Jekyll would build the HTML at build-time rather than runtime, which was simpler and cheaper to run on a server. Jekyll grew in popularity, partially due to GitHub's adoption of Jekyll for GitHub pages. After Jekyll's creation, many more static site generators followed, which helped static site generation grow to a large category in web development. Now let's look at why static site generators are helpful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Static Site Generators are significant
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;Static site generators are significantly faster than dynamic websites because they run expensive computations beforehand and compile static files. First, let's dig deeper into the first point. If you run a website with dynamic software like WordPress, there are multiple steps to send your content to the user. Before actually sending the HTML, WordPress has to fetch the content from a database, likely MySQL, build the page, run any relevant plugins, and finally send the file. These steps take valuable time, and if they take too long, the user could leave before the content loads. Some of this can be alleviated using caching, but caching is imperfect, so users often get served a page uncached. On the other hand, with static site generators, everything is built beforehand, so users do not need to wait for database fetching or computations.&lt;/p&gt;

&lt;p&gt;Another thing static files allow is static file hosting. If you run a WordPress server, you need a compute unit, like a bare metal server or virtual machine. When doing this, you make it so users can only access the uncached website from one location. That is fine if your users are close to your server, but they are likely not. If, for example, a user is in Singapore and you are in the US, the connection needs to travel almost halfway around the world to reach your server. The connection distance adds a significant amount of latency. It is possible to cache it globally on a &lt;a href="(https://www.cloudflare.com/learning/cdn/what-is-a-cdn/)"&gt;CDN&lt;/a&gt;, but once again, it is hard to get a 100% cache hit ratio and often nearly impossible since it is hard to cache HTML files. On the other hand, if you use static site generators, you can cache everything easily (most static hosting services integrate with a CDN), and cache invalidation is much simpler.&lt;/p&gt;

&lt;h3&gt;
  
  
  Server Costs
&lt;/h3&gt;

&lt;p&gt;Once again, CDNs help in this area. First, let's look at the pricing of &lt;a href="https://wpengine.com/"&gt;WP Engine&lt;/a&gt;, one of the most popular managed WordPress hosts. For up to 25,000 visits, you have to pay $25 (USD) a month. Between 25,000 and  75,000 visits, the cost rises to $59 a month. Once again, you can put a CDN in front of the host, but visits often miss the cache. In contrast, static file hosting is extremely cheap. For example, the hosting &lt;a href="https://byteofdev.com/"&gt;ByteofDev&lt;/a&gt; runs on is &lt;a href="https://pages.cloudflare.com/"&gt;Cloudflare Pages&lt;/a&gt;. The free tier offers unlimited requests and bandwidth. The pricing means that even if traffic suddenly spiked 10 times, not only would my website remain online and fast, it would not cost me any more money.&lt;/p&gt;

&lt;h2&gt;
  
  
  The State of Static Site Generators
&lt;/h2&gt;

&lt;h3&gt;
  
  
  JavaScript Client-Side Frameworks
&lt;/h3&gt;

&lt;p&gt;Many modern static site generators integrate with modern JavaScript frameworks like React, Svelte, and Vue. Using a framework like those mentioned earlier instead of a traditional templating language gives you access to the vast ecosystem of framework-specific components and code that can run on both the build server and client. Currently, the most popular SSG that does this is &lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt;, which supports both dynamic rendering and static rendering. However, many other popular SSGs do this, like &lt;a href="https://www.gatsbyjs.com/"&gt;Gatsby&lt;/a&gt;, &lt;a href="https://vitepress.vuejs.org/"&gt;VitePress&lt;/a&gt;, and &lt;a href="https://astro.build/"&gt;Astro&lt;/a&gt;. Next.js and Gatsby both support React, VitePress supports Vue, and Astro supports multiple frameworks, including React, Svelte, and Vue.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fast Building
&lt;/h3&gt;

&lt;p&gt;As we have learned, SSGs are all about the build step. No one likes to wait a long time for their website to build. SSGs like &lt;a href="https://gohugo.io/"&gt;Hugo&lt;/a&gt; and &lt;a href="https://www.getzola.org/"&gt;Zola&lt;/a&gt; are trying to create a build experience that is significantly faster than previous SSGs. Hugo is usually around 6 times faster than Jekyll and is even faster compared to Next.js or other framework-based SSGs. There are multiple reasons for this. First, Hugo and Zola are written in Go and Rust, respectively, rather than JavaScript or Ruby, which most other static site generators use. Go and Rust are much faster than Ruby and JavaScript because they use static types (along with manual garbage collection in Rust's case) and are compiled beforehand. Second, they both are designed to use multithreading. Multithreading multiple allows tasks to run simultaneously by utilizing multiple CPU cores instead of running everything sequentially on one CPU core. Finally, Hugo and Zola simply focus on optimizing their code for fast build times.&lt;/p&gt;

&lt;p&gt;While the SSGs mentioned before are currently the fastest SSGs by a large margin, there is still innovation for speed on the JavaScript framework-based front. One of the biggest bottlenecks in JavaScript framework-based SSGs is the bundling step. The first SSGs of this type primarily used Webpack, but many modern SSGs have started using &lt;a href="https://byteofdev.com/posts/bundlers/"&gt;next-gen bundlers&lt;/a&gt; like Vite, which help speed up builds by a large margin. Even SSGs like Next.js, which still use Webpack, are beginning to adopt faster elements like &lt;a href="https://nextjs.org/blog/next-12#faster-builds-and-fast-refresh-with-rust-compiler"&gt;SWC instead of Babel and Terser&lt;/a&gt;. Astro is pretty notable in this as it both uses Vite and has migrated its core compiler to Go using &lt;a href="https://byteofdev.com/posts/webassembly"&gt;WebAssembly&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Partial Hydration
&lt;/h3&gt;

&lt;p&gt;JavaScript is one of the most significant contributors to page bloat. If you use one of the SSGs that use a JavaScript framework, you are likely sending unnecessary JavaScript to the client. However, partial hydration can solve this. To understand why, let's first look at what hydration is. Most JavaScript frameworks run code on both the build step and the client. The build step creates the HTML. However, interactivity is still needed. To solve this, they use hydration. Hydration uses client-side JavaScript to make static HTML interactive. Sounds good, right? The problem is that frameworks often send code for parts of the HTML that are not interactive. Doing that slows down page loading without actually changing anything.&lt;/p&gt;

&lt;p&gt;The solution is partial hydration, which allows you to define what you want to hydrate. There are two forms of this, page-level and component-level. Page-level hydration is a form of partial hydration that works with SSGs like SvelteKit and allows partial hydration on a per-page basis. You can choose whether to include JavaScript for each page. However, you often want to include JavaScript, but only for one part of the page. To do this, you can use component-level partial hydration. Component-level hydration allows you to implement partial hydration in a significantly more granular way by defining precisely what components you want to hydrate. The most popular way of doing this is using the &lt;a href="https://jasonformat.com/islands-architecture/"&gt;Islands Architecture&lt;/a&gt;, which Astro uses.&lt;/p&gt;

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

&lt;p&gt;That is it! Hopefully, now you know a lot more about static site generators. If you want my personal recommendation, it is Astro, for the reasons I have mentioned in various parts of this article. If you liked this article, be sure to join the newsletter &lt;a href="https://byteofdev.com/signup"&gt;here&lt;/a&gt; and subscribe to the RSS feed &lt;a href="https://byteofdev.com/rss.xml"&gt;here&lt;/a&gt;. Thanks for reading!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>nextjs</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>State of the Web: Bundlers &amp; Build Tools</title>
      <dc:creator>AsyncBanana</dc:creator>
      <pubDate>Sun, 23 Jan 2022 20:40:23 +0000</pubDate>
      <link>https://forem.com/asyncbanana/state-of-the-web-bundlers-build-tools-1j73</link>
      <guid>https://forem.com/asyncbanana/state-of-the-web-bundlers-build-tools-1j73</guid>
      <description>&lt;p&gt;Ever since Browserify, bundlers have been extremely important in the web ecosystem. They provide the ability to automatically process code, which opens up opportunities for performance optimization and non-native languages. This article looks at the background of bundlers, why they are essential, and their current state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background of Bundlers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Web Before Bundlers
&lt;/h3&gt;

&lt;p&gt;For a large part of the web, bundlers did not exist. To include scripts, most people just linked to the library on a CDN like &lt;a href="https://cdnjs.com/"&gt;CDNJS&lt;/a&gt; or &lt;a href="https://developers.google.com/speed/libraries"&gt;Google Hosted Libraries&lt;/a&gt;. This would begin to change in 2009 when Node.js was released. Instead of using CDNs, Node.js came with its package manager, npm. npm was easy to use because every library was just one &lt;code&gt;npm install&lt;/code&gt; away, and updating was effortless. Because of the ease of use, many people wanted to use npm on the web. However, this was impossible until &lt;a href="https://browserify.org/"&gt;Browserify&lt;/a&gt; came along.&lt;/p&gt;

&lt;h3&gt;
  
  
  Browserify
&lt;/h3&gt;

&lt;p&gt;Browserify's tagline describes itself pretty well.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Browserify lets you &lt;code&gt;require('modules')&lt;/code&gt; in the browser by bundling up all of your dependencies.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Browserify was the first JavaScript "bundler." If you do not know what a bundler is, it is a tool that bundles multiple scripts together into one script and often performs transformations on the scripts it bundles. This means that you can bundle different scripts from NPM with your code by parsing &lt;code&gt;require()&lt;/code&gt; statements in your code. Bundling also meant that your site was often faster because there were not as many HTTP requests being sent out, which reduced overhead (this is less the case in modern browsers because HTTP/2 adds the ability to download multiple resources on a single connection). Browserify quickly gained adoption because of these advantages. It is also important to note other ways of using modules on the web, like Require.js, which used AMD instead of CommonJS, and Bower, which fully replaced NPM for the browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  Grunt &amp;amp; Gulp
&lt;/h3&gt;

&lt;p&gt;While Browserify was great at bundling scripts together, it was not quite as good at transforming code. Let's say you wanted to compile your CoffeeScript code to JavaScript. You can do this with plain Browserify. However, it is unwieldy and relatively inflexible. To fix this, a new group of tools for the web where born, which focused on running code transforms. These are usually called task runners, and the most popular ones are &lt;a href="https://gruntjs.com/"&gt;Grunt&lt;/a&gt; and &lt;a href="https://gulpjs.com/"&gt;Gulp&lt;/a&gt;. Grunt was the first task manager, first released in January of 2012. It allowed for more flexible code transforms when using bundlers like Browserify or without a bundler. However, there were still problems with Grunt, which were solved by Gulp. Gulp is faster, as it uses Node streams instead of temporary files and runs tasks in parallel, as well as allowing for people to use a script instead of a JSON configuration file. This was still not perfect, though, because it was annoying to use two separate tools. This was fixed by Webpack&lt;/p&gt;

&lt;h3&gt;
  
  
  Webpack
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://webpack.js.org/"&gt;Webpack&lt;/a&gt; combines both bundling and compiling, making it easier than the previous standard of Gulp + Browserify. Webpack first started becoming popular in 2016, and it is still popular to this day. There are also some other advantages of Webpack. First, it supports bundling and transforming non-JavaScript assets, like HTML, CSS, and images. Second, the API is often easier to use (although it is still complicated relative to the newest bundlers). Many tools, like Create-React-App, Next.js, and Vuepress, use Webpack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Bundlers/Build tools are Significant
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;If you already know why bundlers are used, you can skip this section&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Optimization
&lt;/h3&gt;

&lt;p&gt;In general, most people do not write their code 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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; 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;l&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead, to make things readable, they would probably write something 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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; world! &lt;/span&gt;&lt;span class="dl"&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="nx"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, the first example is smaller and therefore transferred faster. Now, you might think you have to sacrifice size for readability, but there is a solution, minifiers. Minifiers automatically transform your source code into a smaller form. In fact, the first code example was generated by &lt;a href="https://terser.org/"&gt;Terser&lt;/a&gt;, which is one of the best minifiers. Bundlers make using minifiers easy through plugins. Additionally, bundlers help perform other optimizations, like tree shaking, which removes unused code. Finally, bundling scripts itself can improve performance by reducing HTTP requests needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Non-web Native Languages
&lt;/h3&gt;

&lt;p&gt;Often, it is more efficient to use a language like &lt;a href="https://sass-lang.com/"&gt;Sass&lt;/a&gt; or &lt;a href="https://stylus-lang.com/"&gt;Stylus&lt;/a&gt; instead of plain CSS. Or, perhaps you are trying to use &lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt; to enforce static typing in your code. Whatever the case, it is often better to use languages that the web does not natively support. Bundlers can help with this. Instead of running a bunch of different commands yourself to compile everything, you can often just add plugins to your bundler config file and run the bundler.&lt;/p&gt;

&lt;h3&gt;
  
  
  Development Features
&lt;/h3&gt;

&lt;p&gt;Most modern bundlers have features that enable faster iteration, like Hot Module Reload (HMR). HMR automatically reloads specific modules that have changed rather than the whole page, making reloading faster. Additionally, if you are using a framework like React, React state can be preserved, which means that the page data does not reset every time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Easy Inclusion of Modules
&lt;/h3&gt;

&lt;p&gt;Bundling modules together is the original reason why bundlers were made. Even though there are many other features now, this is still important. Even with the native support of ESM, it is still helpful to be able to &lt;code&gt;import&lt;/code&gt; or &lt;code&gt;require&lt;/code&gt; modules without having to write full import paths (although &lt;a href="https://github.com/WICG/import-maps"&gt;import maps&lt;/a&gt; could help with this).&lt;/p&gt;

&lt;h2&gt;
  
  
  The State of Build Tools
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Adoption
&lt;/h3&gt;

&lt;p&gt;Nowadays, almost every web developer uses one bundler or another. Webpack is by far the most popular, with &lt;a href="https://rollupjs.org/"&gt;Rollup&lt;/a&gt; and &lt;a href="https://vitejs.dev/"&gt;Vite&lt;/a&gt; in second and third, respectively. Currently, Vite is the fastest-growing major bundler, which has been adopted by frameworks like Vitepress, SvelteKit, Astro, and more.&lt;/p&gt;

&lt;h3&gt;
  
  
  ECMAScript Modules (ESM)
&lt;/h3&gt;

&lt;p&gt;ESM is supported in most modern bundlers. While tools like Browserify do not support ESM, most tools as new or newer than Webpack support ESM. Additionally, ESM is often the recommended way to do things for supported bundlers because it is more future-oriented than CommonJS or AMD, and it is easier to statically analyze imports for tree shaking. ESM also opens up the opportunity for unbundled development, which we cover below.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unbundled Development
&lt;/h3&gt;

&lt;p&gt;Unbundled development utilizes native ESM support in browsers to offer an ultra-fast development experience. Unlike a traditional bundler which bundles everything in development, unbundled development transforms the code and rewrites import paths to the ESM compliant file path without bundling your code. Additionally, most bundlers that do this pre-bundle dependencies because that decreases the number of imports needed, and dependencies are unlikely to change often. The two most prominent bundlers that utilize unbundled development are &lt;a href="https://vitejs.dev/"&gt;Vite&lt;/a&gt; and &lt;a href="https://www.snowpack.dev/"&gt;Snowpack&lt;/a&gt;. Snowpack, created in 2019, was the first bundler to have an unbundled development experience. However, while Snowpack was popular for some time, this did not last forever. In 2020, the team behind Vue created Vite. Vite has many advantages over Snowpack, like the ease of use, speed, better optimization, and more. Additionally, popular projects like SvelteKit adopted Vite instead of Snowpack. All of this helped Vite pass Snowpack in downloads, and it now has &lt;a href="https://www.npmtrends.com/snowpack-vs-vite"&gt;more than 10x downloads&lt;/a&gt; compared to Snowpack. In fact, even &lt;a href="https://astro.build/"&gt;Astro&lt;/a&gt;, a project created by the team behind Snowpack (be on the lookout for an article about Astro), is now using Vite. Overall, if you want fast, unbundled development, I recommend Vite.&lt;/p&gt;

&lt;h3&gt;
  
  
  Faster Languages
&lt;/h3&gt;

&lt;p&gt;Another way that many people are trying to speed up bundling and code transformation is through using more optimized languages like Go or Rust. Currently, the two most notable tools that do this are &lt;a href="https://esbuild.github.io/"&gt;esbuild&lt;/a&gt; and &lt;a href="https://swc.rs/"&gt;SWC&lt;/a&gt;. esbuild was created by Evan Wallace in 2016 using Go. esbuild performed the role of Babel in transforming modern JavaScript, the TypeScript compiler, Terser, and basic bundling all in one package that was significantly faster than any other tools at that time. SWC was created in 2017 by kdy1 using Rust. SWC is even faster than esbuild, although only marginally. esbuild is currently more popular than SWC and is used by projects like Vite, although &lt;a href="https://dev.to/posts/deno"&gt;Deno&lt;/a&gt; and Next.js have adopted SWC.&lt;/p&gt;

&lt;h3&gt;
  
  
  Low to Zero Config
&lt;/h3&gt;

&lt;p&gt;Webpack has an infamously complex plugin system. While it is very powerful, it can be scary for beginners. Luckily, there are newer bundlers that focus on this. &lt;a href="https://parceljs.org/"&gt;Parcel&lt;/a&gt; was created in 2017 by Devon Govett to allow for easy, zero-config bundling. Parcel supports many of the features Webpack plugins provide, like Sass, TypeScript, and JSX, without requiring you to do anything. Additionally, due to caching and the increasing use of Rust, Parcel v2 can be faster than Webpack. Vite is another low-config bundler, although it does not do as much out of the box.&lt;/p&gt;

&lt;h3&gt;
  
  
  What About Webpack?
&lt;/h3&gt;

&lt;p&gt;Webpack is still the most popular bundler. While it has not been taking advantage of the ability for massive speed improvements specified above, it still has added new features in the most recent version, Webpack 5. The biggest thing added in Webpack 5 is &lt;a href="https://webpack.js.org/concepts/module-federation/"&gt;module federation&lt;/a&gt;, or micro-frontends. Module federation separates different elements of a website and makes it easier to share pieces of code like component libraries. Another big thing Webpack added in version 5 is better caching, which can improve reload times in development. Overall, Webpack is still advancing, although it is falling behind some bundlers in certain features.&lt;/p&gt;

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

&lt;p&gt;The world of web bundlers is advancing quickly. Hopefully this article gave you an overview of what is currently happening for bundlers. If you liked this article, sign up for the ByteofDev mailing list &lt;a href="https://byteofdev.com/signup/"&gt;here&lt;/a&gt; (or don't, but I hope you do 🙃), and thank you for reading.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>webpack</category>
      <category>programming</category>
    </item>
    <item>
      <title>State of the Web: Serverless Functions</title>
      <dc:creator>AsyncBanana</dc:creator>
      <pubDate>Sun, 16 Jan 2022 15:55:20 +0000</pubDate>
      <link>https://forem.com/asyncbanana/state-of-the-web-serverless-functions-hhc</link>
      <guid>https://forem.com/asyncbanana/state-of-the-web-serverless-functions-hhc</guid>
      <description>&lt;p&gt;Serverless functions (also known as Function as a Service) execute code statelessly on the Cloud. This means that they can do things like scale infinitely and run anywhere. There are many different serverless function providers, like &lt;a href="https://aws.amazon.com/lambda/"&gt;AWS Lambda&lt;/a&gt;, &lt;a href="https://workers.cloudflare.com/"&gt;Cloudflare Workers&lt;/a&gt;, and &lt;a href="https://vercel.com/"&gt;Vercel&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background of Serverless Functions
&lt;/h2&gt;

&lt;p&gt;Google created the first serverless model in their &lt;a href="https://cloud.google.com/appengine/"&gt;Google App Engine&lt;/a&gt; product, which offered auto-scaling stateless code execution. App Engine was different from most more recent serverless function providers, but it was the first product to try this idea. However, while it was used by companies like Snapchat, it did not catch on with the overall developer community.&lt;/p&gt;

&lt;p&gt;The first Function as a Service (FaaS) provider to truly catch on was &lt;a href="https://aws.amazon.com/lambda/"&gt;AWS Lambda&lt;/a&gt;. AWS Lambda was a serverless function service that Amazon released in November 2014. Lambda allows for functions written in many different languages to automatically scale in under a second while allowing users not to have to worry about the underlying hardware. Companies like Google, Microsoft, and Oracle also created their own service for serverless functions. Although to this day, Lambda is the most popular serverless function provider, and since its release, it has become faster, more flexible, and easier to use.&lt;/p&gt;

&lt;p&gt;However, that is not the end of the story. Since then, many services have improved on AWS Lambda's model in ways like ease of use and performance. The first notable FaaS provider was &lt;a href="https://vercel.com/"&gt;Vercel&lt;/a&gt; (ZEIT Now at the time), which was released in April of 2016 and was a lot simpler to use than Lambda. Another selling point was that it integrated well with &lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt;, a React framework made by Vercel. Other, newer services also try to be a lot easier, like &lt;a href="https://begin.com/"&gt;Begin&lt;/a&gt;, although Vercel is still the most popular in that group.&lt;/p&gt;

&lt;p&gt;The second major innovation in serverless functions was edge computing with lightweight isolates. This was pioneered by &lt;a href="https://workers.cloudflare.com/"&gt;Cloudflare Workers&lt;/a&gt;, a serverless product released in September 2017. It promised to allow your code to run on any of the many Points of Presence Cloudflare has worldwide, and it used &lt;a href="https://developers.cloudflare.com/workers/learning/how-workers-works#isolates"&gt;V8 Isolates&lt;/a&gt; to reduce the startup time to a few milliseconds, and later, even zero.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Serverless Functions are Significant
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;Many serverless function providers offer high-speed services. As talked about in the background, edge computing has revolutionized serverless functions. Because serverless functions are stateless, they do not need to always run in the same place. This means they can work like CDNs and automatically deliver content from data centers close to users (the "edge") rather than one centralized location. Serving from the edge can be a huge difference in latency for large networks like Cloudflare's. Not all serverless function providers support this, but a growing number do, like &lt;a href="https://www.netlify.com/products/edge/edge-handlers/"&gt;Netlify&lt;/a&gt;, &lt;a href="https://workers.cloudflare.com/"&gt;Cloudflare Workers&lt;/a&gt;, &lt;a href="https://vercel.com/features/edge-functions"&gt;Vercel&lt;/a&gt;, &lt;a href="https://aws.amazon.com/lambda/edge/"&gt;AWS Lambda@Edge&lt;/a&gt;, and more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scalability
&lt;/h3&gt;

&lt;p&gt;Unlike virtual machines, serverless functions can usually scale from zero to infinity. This means that you never get overloaded by requests, and you don't have to waste money on computing power that you are not using. Whenever users request the HTTP endpoint, most serverless function providers automatically determine whether there are already running functions that can process the request. If there are not, a new function is created. Additionally, if function instances are not processing anything, they are automatically stopped. Some virtual machine and container services also offer autoscaling, but because it takes longer to start a virtual machine/container, it is much less granular.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ease of Setup
&lt;/h3&gt;

&lt;p&gt;Serverless functions abstract over the hardware usually (hence the serverless). Instead of worrying about setting up servers and operating systems, the provider takes care of everything. This is not necessarily unique to serverless functions, as containers and virtual machines usually do this too, but with serverless functions, you don't even need to worry about the operating system or software running your code. The advantage of not managing your hardware and operating system is that you can get started a lot faster and not have to worry about as much.&lt;/p&gt;

&lt;h2&gt;
  
  
  The State of Serverless Functions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Language support
&lt;/h3&gt;

&lt;p&gt;You can use almost any language with serverless functions. Whether you are using JavaScript, Go, or C, most serverless function providers support them. However, if you use a V8-based serverless function setup (most edge serverless function setups do this), language support might be more limited. Since V8 is primarily a JavaScript engine, the best-supported language is JavaScript. However, sometimes you want to use languages that do not support compiling to JavaScript. The solution is often WebAssembly, a portable assembly-like language that most modern languages support as a compilation target. WebAssembly also has other advantages, like how it can often perform faster. For more information on WebAssembly, &lt;a href="https://dev.to/posts/webassembly/"&gt;you can look at our article on WebAssembly&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Production readiness
&lt;/h3&gt;

&lt;p&gt;Serverless functions are used by many different companies and are supported by some of the biggest names in web hosting like AWS and Cloudflare. While serverless functions are somewhat new, they are still very production-ready.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running on the Edge
&lt;/h3&gt;

&lt;p&gt;Edge serverless functions are still experimental for the most part. However, some services are battle-tested, namely &lt;a href="https://aws.amazon.com/lambda/edge/"&gt;AWS Lambda@Edge&lt;/a&gt; and &lt;a href="https://workers.cloudflare.com/"&gt;Cloudflare Workers&lt;/a&gt;. These services have existed for multiple years and are used by companies like NPM and Amazon. There are also other more recent services offered by companies like Vercel, Netlify, and Fastly.&lt;/p&gt;

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

&lt;p&gt;That is it! Hopefully, now you understand serverless functions, why they are helpful, and what state they are currently in. If you liked this article, be sure to sign up for the mailing &lt;a href="https://byteofdev.com/signup/"&gt;here&lt;/a&gt;. I hope you learned something, and thanks for reading.&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>programming</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>State of the Web: Deno</title>
      <dc:creator>AsyncBanana</dc:creator>
      <pubDate>Sun, 09 Jan 2022 22:04:56 +0000</pubDate>
      <link>https://forem.com/asyncbanana/state-of-the-web-deno-4lmh</link>
      <guid>https://forem.com/asyncbanana/state-of-the-web-deno-4lmh</guid>
      <description>&lt;p&gt;&lt;a href="https://deno.land/" rel="noopener noreferrer"&gt;Deno&lt;/a&gt; is a modern JavaScript runtime, competing with Node.js, that promises features like secure I/O and built-in TypeScript support. Ryan Dahl, Node.js' original creator, created Deno, building it in Rust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background of Deno
&lt;/h2&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%2Fik.imagekit.io%2Fserenity%2FByteofDev%2FBlog_Content_Images%2Fdeno_city" 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%2Fik.imagekit.io%2Fserenity%2FByteofDev%2FBlog_Content_Images%2Fdeno_city" alt="Dino from Deno logo in a raining city (by Dimitrij Agal)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Ryan Dahl's talk &lt;a href="https://www.youtube.com/watch?v=M3BM9TB-8yA" rel="noopener noreferrer"&gt;Ten things I regret about Node&lt;/a&gt;, he talked about many problems with Node. This includes things like Node's failure to embrace web standards, security, Node's way of compiling native modules (GYP), and NPM. Then, he revealed Deno. Deno was a new project that fixed many of the problems Ryan Dahl had earlier mentioned, along with extra advantages like built-in TypeScript support. Ryan Dahl initially built Deno in Go but later switched to Rust.&lt;/p&gt;

&lt;p&gt;Since Deno was first announced, it has made significant progress. 1.0 was released in August 2020, and companies like Slack have adopted Deno. In addition, Deno has also released their own edge serverless function platform, &lt;a href="https://deno.com/deploy" rel="noopener noreferrer"&gt;Deno Deploy&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Deno is significant
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Security
&lt;/h3&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%2Fik.imagekit.io%2Fserenity%2FByteofDev%2FBlog_Content_Images%2Fphone_security" 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%2Fik.imagekit.io%2Fserenity%2FByteofDev%2FBlog_Content_Images%2Fphone_security" alt="Phone with lock"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;V8 is a sandboxed language that makes it impossible for code to do something outside of its boundaries. However, Node.js allows access to things like networking and the filesystem inside the sandbox, which removes the security benefits of V8. Even for trusted programs, this can be hurtful because insecure code or malicious dependencies could deal significant damage and steal information.&lt;/p&gt;

&lt;p&gt;Deno solves with a system of &lt;a href="https://deno.land/manual@v1.17.1/getting_started/permissions" rel="noopener noreferrer"&gt;permissions&lt;/a&gt;. These permissions make you define precisely what the program can do outside of the sandbox, like filesystem access and environment variables. For example, if you wanted to allow for reading files within the local &lt;code&gt;assets&lt;/code&gt; directory, you would run Deno with a command like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;deno run --allow-read=./assets
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because of these capabilities, you can ensure that your code does not reach outside of its boundaries, increasing security.&lt;/p&gt;

&lt;h3&gt;
  
  
  Standardized APIs
&lt;/h3&gt;

&lt;p&gt;Because the Node.js and web platforms evolved in parallel, they have many differences. There are many examples of this, like the module system and HTTP requests.&lt;/p&gt;

&lt;h4&gt;
  
  
  ECMAScript Modules and CommonJS
&lt;/h4&gt;

&lt;p&gt;When Node.js was first created, JavaScript could not use other modules beyond embedding them in &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags and using them from the global window scope. Since HTML and the window were unavailable on the server, Node.js needed a module format. Nodejs decided to adopt a form of CommonJS, which was a popular, simple, synchronous module format. However, CommonJS was not native to browsers (you would have to use a library like &lt;a href="https://browserify.org/" rel="noopener noreferrer"&gt;Browserify&lt;/a&gt;), and there were differences between implementations of CommonJS.&lt;/p&gt;

&lt;p&gt;Years later, in 2016, a new module specification called ECMAScript Modules (ESM) was finalized in ES6. This module specification would work without any libraries in browsers. Additionally, it would solve many problems with CommonJS, like asynchronous module loading and tree shaking. However, it took a while for Node.js to add ESM support, and even after that, ESM adoption in Node.js was not very high, with the majority of NPM packages still only include CommonJS versions. Additionally, Node.js does not have an entirely standards-compliant ESM implementation and differs in things like including &lt;code&gt;.js&lt;/code&gt; file extensions.&lt;/p&gt;

&lt;p&gt;In contrast, Deno only works with entirely standards-compliant ESM. This makes using Deno a lot simpler for both users and library authors. Speaking from experience, using one module format is a lot simpler than including both ESM and CommonJS. Deno also is more straightforward in that it sticks to the standards, so you know that your module code works correctly in browsers.&lt;/p&gt;

&lt;h4&gt;
  
  
  HTTP Fetching
&lt;/h4&gt;

&lt;p&gt;Sending HTTP requests is another area of incompatibility which Deno solves. Node.js allows for HTTP requests through the &lt;code&gt;http&lt;/code&gt; and &lt;code&gt;https&lt;/code&gt; standard library functions. However, the modern way of running HTTP requests on the web is through the &lt;code&gt;fetch()&lt;/code&gt; API, which is standardized and is simpler than &lt;code&gt;http&lt;/code&gt;. Node.js does not support &lt;code&gt;fetch()&lt;/code&gt;, and so people have had to turn to using packages like &lt;a href="https://www.npmjs.com/package/node-fetch" rel="noopener noreferrer"&gt;node-fetch&lt;/a&gt; for the simplicity of &lt;code&gt;fetch()&lt;/code&gt; or &lt;a href="https://www.npmjs.com/package/cross-fetch" rel="noopener noreferrer"&gt;cross-fetch&lt;/a&gt; for full cross-platform compatibility. This is problematic because it is another dependency needed, and it is not immediately available without importing. However, Deno supports the &lt;code&gt;fetch()&lt;/code&gt; API by default, which solves these problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decentralized Module Hosting
&lt;/h3&gt;

&lt;p&gt;No, just because it is decentralized does not mean it uses blockchain 😉 (&lt;a href="https://nest.land/" rel="noopener noreferrer"&gt;although there is a Deno package hosting service that is backed by blockchain&lt;/a&gt;). Instead, Deno's decentralized module hosting allows you to request modules by URL instead of from a centralized package database like NPM. Doing this allows for more freedom in module hosting. Deno does offer a module hosting service itself at &lt;a href="https://deno.land/x" rel="noopener noreferrer"&gt;deno.land/x&lt;/a&gt;, but there are many others you can use, and you can even link to any ESM CDN or something else that serves a JavaScript file. Many people worry about the remote code changing because it is not necessarily controlled, but most Deno module hosting services are immutable, and Deno caches the remote file, so it only changes if you explicitly reload the cache.&lt;/p&gt;

&lt;h3&gt;
  
  
  Built-in TypeScript support
&lt;/h3&gt;

&lt;p&gt;Deno allows you to directly run a TypeScript file like JavaScript without passing it through a compiler. Deno even optimizes this process by caching the resulting JavaScript and using &lt;a href="https://swc.rs/" rel="noopener noreferrer"&gt;SWC&lt;/a&gt;, a fast Rust-based compiler, if type checking is not required. Built-in TypeScript support increases efficiency because you don't need to set up a build step if you are building an application with TypeScript. There are ways to do automatic TypeScript compiling in Node.js, like through &lt;a href="https://www.npmjs.com/package/ts-node" rel="noopener noreferrer"&gt;ts-node&lt;/a&gt;, but they are not as feature-rich and are not installed by default.&lt;/p&gt;

&lt;h2&gt;
  
  
  The State of Deno
&lt;/h2&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%2Fik.imagekit.io%2Fserenity%2FByteofDev%2FBlog_Content_Images%2Fdeno_planet" 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%2Fik.imagekit.io%2Fserenity%2FByteofDev%2FBlog_Content_Images%2Fdeno_planet" alt="Planet with the Deno dinosaur (By Hashrock)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Ecosystem
&lt;/h3&gt;

&lt;p&gt;Currently, this is the biggest problem with Deno and is a big reason why most Node.js developers are not migrating to Deno (this is a nasty problem because if Node.js developers don't migrate, the ecosystem grows more slowly). There are 3,501 modules on &lt;a href="https://deno.land/x" rel="noopener noreferrer"&gt;deno.land/x&lt;/a&gt;, compared to 1.3 million on NPM. However, many people use other package hosting services (see "Decentralised Module Hosting" above), and most modern web packages should work on Deno. The biggest blockers to Node compatibility are CommonJS and the Node API. Deno provides a &lt;a href="https://deno.land/manual@v1.17.2/npm_nodejs/compatibility_mode" rel="noopener noreferrer"&gt;Node.js compatibility mode&lt;/a&gt;, but it is experimental.&lt;/p&gt;

&lt;h3&gt;
  
  
  Development
&lt;/h3&gt;

&lt;p&gt;Deno is very actively developed, with monthly releases and new features in each release. Deno is even backed by a &lt;a href="https://deno.com/blog/the-deno-company" rel="noopener noreferrer"&gt;official company&lt;/a&gt;, which can be both good or bad depending on how you look at it. There are more than 600 contributors to Deno, which is growing. Basically, Deno is a very actively maintained project&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployment
&lt;/h3&gt;

&lt;p&gt;Deno can be deployed pretty widely, although not as widely as Node.js.&lt;/p&gt;

&lt;h4&gt;
  
  
  Containers &amp;amp;  Managed VMs
&lt;/h4&gt;

&lt;p&gt;Deno has ok support for various container services. Deno.land provides an &lt;a href="https://hub.docker.com/r/denoland/deno" rel="noopener noreferrer"&gt;official Docker image&lt;/a&gt; for services that support Docker. However, while most popular container services support Deno, the support is often unofficial and not always maintained. Here is a list of tools and resources for running Deno on container services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/google-cloud/deno-on-cloud-run-89ae64d1664d" rel="noopener noreferrer"&gt;Cloud Run&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/chibat/heroku-buildpack-deno" rel="noopener noreferrer"&gt;Heroku&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/developer/javascript/tutorial/deploy-deno-app-azure-app-service-azure-cli" rel="noopener noreferrer"&gt;Azure App Service&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Serverless Functions
&lt;/h4&gt;

&lt;p&gt;Serverless is where the Deno company comes in. Their primary commercial offering is &lt;a href="https://deno.com/deploy" rel="noopener noreferrer"&gt;Deno Deploy&lt;/a&gt;, a serverless edge function runner for Deno scripts. It is conceptually similar to Cloudflare Workers in that it uses V8 Isolates for ultra-fast startup times. The advantage of Deno Deploy is that it includes the Deno API and all of the other features that make Deno so helpful. However, Deno Deploy is still in beta, so you might want to look elsewhere right now. Here is a list of tools and resources to run Deno on various serverless function providers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/hayd/deno-lambda" rel="noopener noreferrer"&gt;AWS Lambda&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/lucacasonato/now-deno" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.begin.com/posts/2019-12-20-deno-runtime-support-for-architect" rel="noopener noreferrer"&gt;Begin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anthonychu/azure-functions-deno-worker" rel="noopener noreferrer"&gt;Azure Functions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Deno is an up-and-coming technology and might someday replace Node as the primary way to run JavaScript. Join the mailing list &lt;a href="https://byteofdev.com/signup" rel="noopener noreferrer"&gt;here&lt;/a&gt; if you want to learn more about emerging technologies in web development weekly. I hope you learned something from this, and thank you for reading.&lt;/p&gt;

</description>
      <category>deno</category>
      <category>javascript</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building the fastest object and array differ</title>
      <dc:creator>AsyncBanana</dc:creator>
      <pubDate>Sat, 01 Jan 2022 23:14:34 +0000</pubDate>
      <link>https://forem.com/asyncbanana/building-the-fastest-object-and-array-differ-2l6f</link>
      <guid>https://forem.com/asyncbanana/building-the-fastest-object-and-array-differ-2l6f</guid>
      <description>&lt;p&gt;I maintain &lt;a href="https://github.com/AsyncBanana/microdiff"&gt;Microdiff&lt;/a&gt;, a performance and size optimized library for deep object diffing.&lt;br&gt;
Someone posted in a &lt;a href="https://github.com/AsyncBanana/microdiff/issues/2#issuecomment-962491393"&gt;Microdiff issue&lt;/a&gt; that asked me to write a blog post about how I made Microdiff fast.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I believe that an explainer (perhaps a blog post?) of the inefficiencies you've noticed with other libraries and how you've overcome them (including the "edge cases" you're saying are unsupported) would be very interesting. They'd also help correctly interpret the benchmark results.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, I decided to do that. This blog post describes how I made Microdiff faster than most other object and array diffing libraries.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;: I am very biased on this subject.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Intro to diffing
&lt;/h2&gt;

&lt;p&gt;Diffing (difference tracking) is tracking what is different between two objects. For example, let's say you have two objects, object a and object b.&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;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;bananas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;apples&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;peaches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;bananas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;apples&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;lemons&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Microdiff, to get the differences, you would do 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="nx"&gt;diff&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;microdiff&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;microdiff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

&lt;span class="cm"&gt;/*
[
    {
        'type':'CHANGE',
        'path':['apples'],
        'value':false,
        'oldValue':true},
    {
        'type':'REMOVE',
        'path':['peaches'],
        'oldValue':true
    },
    {
        'type':'CREATE',
        'path':['lemons'],
        'value':true
    }
]
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, all changes, whether values were changed, added, or removed, were recorded. Diffing is essential for many things, like Virtual DOMs, because they need to record changes in elements. Now, let's learn about the problems with the diffing ecosystem before Microdiff.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Diffing Ecosystem before Microdiff
&lt;/h2&gt;

&lt;p&gt;The diffing ecosystem was in a bad state. Many libraries had millions of downloads but were not maintained actively and were poorly made. Now, let's look at our first example, deep-diff.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.npmjs.com/package/deep-diff"&gt;Deep-Diff&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Deep-Diff is one of the most popular JavaScript libraries for deep object diffing. It gets between 1 and 2 million downloads each week, and tools with more than 10k GitHub stars use it. However, there are many flaws with it. First, the last commit was in 2019, and it doesn't follow modern conventions like supporting ESM and offering bundled TypeScript types.&lt;/p&gt;

&lt;p&gt;Additionally, there are problems with its size and performance. It has a size of 5.5kb minified and 1.9kb Gzipped. That size is not terrible, except that this is a simple utility and therefore should have an even smaller size. In comparison, Microdiff has a size of 0.9kb minified and 0.5kb Gzipped. Now, for performance, Deep-Diff also does not do that well. It is not made to be small or fast, as it has many different functions, which adds significant overhead. Additionally, it does not do things like grouping type behavior to improve performance. Because of all these things, Microdiff can be as much as &lt;a href="https://github.com/AsyncBanana/microdiff#benchmarks"&gt;400% faster&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.npmjs.com/package/deep-object-diff"&gt;Deep-Object-Diff&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Deep-Object-Diff is another popular diffing library. While it has not been updated since 2018, it has some of the modern features that Deep-Diff was missing, like ESM and built-in TypeScript types. Additionally, it can perform at speeds near Microdiff if you use the basic diffing. However, there are still two problems with it, the size and the information it provides. First, while it is not as big as deep-diff, it is still significant, weighing in at 5.2kb minified and 1kb Gzipped. Second, because of the way the output is designed, it provides few details. Where Microdiff provides the change type, new value, old value, and path, the most detailed diff (&lt;code&gt;detailedDiff&lt;/code&gt;) of Deep-Object-Diff does not provide the old value. Additionally, if you want near Microdiff speeds, you have to use the primary diff function instead of &lt;code&gt;detailedDiff&lt;/code&gt;, making it so you do not know the change type.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.npmjs.com/package/diff"&gt;jsdiff&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;While JSDiff supports object diffing, it is primarily designed for diffing text. It is big, at 15.8kb minified and 5.9kb Gzipped, and extremely slow (&lt;a href="https://github.com/AsyncBanana/microdiff#benchmarks"&gt;2100% slower than Microdiff&lt;/a&gt;). I will not go in-depth on why it is so slow because it is simply not designed for object diffing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Microdiff does to fix this
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Performance focused architecture
&lt;/h3&gt;

&lt;p&gt;Microdiff fixes many of these problems by focusing on performance and size without sacrificing ease of use. Instead of having a web of complicated functions, it is a simple recursive function.&lt;br&gt;
Microdiff also uses strategies like combining type behaviors to reduce size while increasing performance. For example, lets say you want to see the differences between RegEx and JavaScript Dates. In order to get accurate change tracking, you have to stringify the RegEx and turn the Date into a number. A naive implementation of this might be 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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;RegExp&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;value2&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;RegExp&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;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;value2&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value2&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 works, but what if you needed to check &lt;code&gt;new String()&lt;/code&gt; objects or &lt;code&gt;new Number()&lt;/code&gt; objects too? (&lt;code&gt;new String()&lt;/code&gt; and &lt;code&gt;new Number()&lt;/code&gt; do not create primitives, so you have to convert them into primitives like with the Dates and RegExs) To fix this without introducing a lot of &lt;code&gt;if then&lt;/code&gt;s, Microdiff's implementation of this is more 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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;richTypes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;String&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;richTypes&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;getPrototypeOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;isNaN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;value2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value2&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 code first gets a list of types that cannot be compared directly (&lt;code&gt;richTypes&lt;/code&gt;). Then, it checks if the value is one of those types. If it is, then the code checks if the value can be coerced into a number with &lt;code&gt;isNaN&lt;/code&gt;. If it can (which is true in the case of dates and &lt;code&gt;new Number()&lt;/code&gt;s), it checks the version coerced into a number. If not (which is the case for RegEx and &lt;code&gt;new String()&lt;/code&gt;), it coerces the value into a string and compares that version. The actual rich type conversion logic is not that different in Microdiff, although there are a few differences that decrease the size and help the logic fit in with the rest of the code.&lt;/p&gt;

&lt;p&gt;Things like that are part of why Microdiff is fast. However, another reason is that it focuses on only more common cases instead of every possible edge case.&lt;/p&gt;

&lt;h3&gt;
  
  
  Focusing on 99% of cases instead of fixing all edge cases
&lt;/h3&gt;

&lt;p&gt;In this regard, Microdiff has improved massively since its release. In fact, since writing the &lt;a href="https://github.com/AsyncBanana/microdiff/issues/2#issuecomment-960291469"&gt;initial explanation&lt;/a&gt;, Microdiff has added support for more rich types and cyclical references. However, there are still cases where Microdiff has less correct behavior, like when comparing objects with prototype properties, because it includes prototype properties. Type combination solves this for the listed types but not for all other types. In testing previously, ways of excluding prototype properties have not been fast. However, I might add a way for you to pass custom inheritance types for string/number coercion, which might help for certain things. Nonetheless, currently, this is not possible.&lt;/p&gt;

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

&lt;p&gt;In conclusion, Microdiff is the fastest diffing library because of its performance-focused architecture and the focus on 99% of cases, and Microdiff is still able to also use modern features and make it possible to use easily. If you are interested in Microdiff, &lt;a href="https://github.com/AsyncBanana/microdiff"&gt;check out the GitHub repo&lt;/a&gt;. I hope you have learned something from this, and thank you for reading.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>performance</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
