<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: paulbrowne</title>
    <description>The latest articles on DEV Community by paulbrowne (@paulbrowne).</description>
    <link>https://dev.to/paulbrowne</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%2F139232%2F05f28146-5443-4050-8bba-53fd92e49c4e.jpeg</url>
      <title>DEV Community: paulbrowne</title>
      <link>https://dev.to/paulbrowne</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/paulbrowne"/>
    <language>en</language>
    <item>
      <title>inline imports FTW!</title>
      <dc:creator>paulbrowne</dc:creator>
      <pubDate>Thu, 06 Mar 2025 16:00:00 +0000</pubDate>
      <link>https://dev.to/paulbrowne/inline-imports-ftw-1o3e</link>
      <guid>https://dev.to/paulbrowne/inline-imports-ftw-1o3e</guid>
      <description>&lt;h2&gt;
  
  
  event-import-then-function
&lt;/h2&gt;

&lt;h5&gt;
  
  
  html
&lt;/h5&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;input&lt;/span&gt;
    &lt;span class="na"&gt;onchange=&lt;/span&gt;&lt;span class="s"&gt;"import('/js/form.js').then(M =&amp;gt; M.default(this))"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt;
    &lt;span class="na"&gt;onchange=&lt;/span&gt;&lt;span class="s"&gt;"import('/js/form.js').then(M =&amp;gt; M.reverse(this))"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt;
    &lt;span class="na"&gt;onchange=&lt;/span&gt;&lt;span class="s"&gt;"import('/js/form.js').then(M =&amp;gt; M.upperCase(this))"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  note: the M is just short for Module
&lt;/h6&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;form.js loaded&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;reverse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;element&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;element&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;element&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="nf"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;join&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="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;upperCase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;element&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;element&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="nx"&gt;element&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="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example &lt;code&gt;form.js&lt;/code&gt; will be &lt;em&gt;loaded&lt;/em&gt; only once, no matter how many times the onchange events are triggered. So you'll only ever see one "form.js loaded" in the console.&lt;/p&gt;

&lt;p&gt;Since the loading of form.js is deferred until &lt;em&gt;after&lt;/em&gt; the onchange event has been triggered, there will be a slight delay whilst the browser fetches it.&lt;/p&gt;

&lt;p&gt;If you want to avoid this delay you can always prefetch the resource by adding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"prefetch"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/js/form.js"&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;to the html. This will of course fetch the file regardless if the user ever needs it.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>import</category>
      <category>vanillajs</category>
    </item>
    <item>
      <title>Lazyload Scripts like Images</title>
      <dc:creator>paulbrowne</dc:creator>
      <pubDate>Sat, 05 Oct 2024 10:57:40 +0000</pubDate>
      <link>https://dev.to/paulbrowne/lazyload-scripts-like-images-30e0</link>
      <guid>https://dev.to/paulbrowne/lazyload-scripts-like-images-30e0</guid>
      <description>&lt;p&gt;One of the best improvements to html over the recent years was the &lt;code&gt;loading="lazy"&lt;/code&gt; attribute that you can add to images (also iframes) that will tell the browsers to not load the image until it is in the viewport.&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;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/images/your-image.png"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&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;Very simple, very useful. But wouldn't it be great if you could do this for scripts as well. So that you could lazily load your components, only if/when they are actually needed...&lt;/p&gt;

&lt;p&gt;Well, one other feature the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; element has, is the ability to run a script &lt;em&gt;after&lt;/em&gt; the image loads (or doesn't load) with the &lt;code&gt;onload&lt;/code&gt; and &lt;code&gt;onerror&lt;/code&gt; attributes.&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;img&lt;/span&gt; 
        &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/images/your-image.png"&lt;/span&gt; 
        &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;
        &lt;span class="na"&gt;onload=&lt;/span&gt;&lt;span class="s"&gt;"() =&amp;gt; console.log('image loaded')"&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;This &lt;code&gt;onload&lt;/code&gt; "callback" will only be fired when that image is loaded, and if the image is been lazily loaded, then it will fire only when the image is in the viewport. Et voilà! A Lazily loaded script.&lt;/p&gt;

&lt;p&gt;Unfortunately, like this, it isn't much use. Firstly you'll have a unwanted image on your page, and secondly, you'll need to inline the javascript you want to run, which kinda defeats the purpose of lazy loading. So, lets make some changes to improve on this.&lt;/p&gt;

&lt;p&gt;The image itself can be anything, or, more importantly, nothing. As I mentioned earlier there is the &lt;code&gt;onerror&lt;/code&gt; callback, which - as the name would suggest - will fire when the image &lt;em&gt;doesn't&lt;/em&gt; load. &lt;/p&gt;

&lt;p&gt;This doesn't mean you need to point the &lt;code&gt;src&lt;/code&gt; to a non-existent image, that would result in a console full of red 404 errors about missing images, and nobody wants that. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;onerror&lt;/code&gt; callback also fires if the &lt;code&gt;src&lt;/code&gt; image is not actually an image, and the easiest way to do that is to "badly encode" an image using the &lt;code&gt;data:&lt;/code&gt; format. This also has the benefit of not filling the console with warnings of missing images 👍&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;img&lt;/span&gt; 
        &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"data:,"&lt;/span&gt; 
        &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;
        &lt;span class="na"&gt;onerror=&lt;/span&gt;&lt;span class="s"&gt;"() =&amp;gt; console.log('image not loaded')"&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;This will still result in the page having the "broken image" thumbnail, but we'll get to that.&lt;/p&gt;

&lt;p&gt;Ok, But we still need to inline the javascript we want to run, so how do we fix that?&lt;/p&gt;

&lt;p&gt;Well, now that &lt;a href="https://caniuse.com/?search=es%20module" rel="noopener noreferrer"&gt;ES module support&lt;/a&gt; is almost universal, we can use the very powerful &lt;strong&gt;event-import-then-default&lt;/strong&gt; javascript loading technique to load a script after an event has fired, like so:&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;img&lt;/span&gt; 
        &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"data:,"&lt;/span&gt; 
        &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;
        &lt;span class="na"&gt;onerror=&lt;/span&gt;&lt;span class="s"&gt;"import('/js/some-component.js').then(_ =&amp;gt; _.default(this))"&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;&lt;em&gt;Note: This also works for &lt;code&gt;onclick&lt;/code&gt;, &lt;code&gt;onchange&lt;/code&gt;, etc. events&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Note: The underscores are just shorthand way to access the Module, you could also write &lt;code&gt;.then(Module =&amp;gt; Module.default(this))&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ok, so what is going on here!?&lt;/p&gt;

&lt;p&gt;First lets take a look at what some-component might look like:&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;// some-component.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="nx"&gt;element&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;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;outerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
        &amp;lt;div class="whatever"&amp;gt;
            &amp;lt;p&amp;gt;Hello world!&amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;
    `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, you might have noticed that in the &lt;code&gt;onerror&lt;/code&gt; callback, I passed &lt;code&gt;this&lt;/code&gt; as an argument to the default export. The reason I did &lt;em&gt;this&lt;/em&gt; (excuse the pun 😁) was to give the script the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; that called it, since in &lt;em&gt;this&lt;/em&gt; (I did it again 🤦) context &lt;code&gt;this = &amp;lt;img&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now you can simply &lt;code&gt;element.outerHTML&lt;/code&gt; to replace the broken image with your html markup and there you have it, lazyloaded scripts! 😱&lt;/p&gt;

&lt;h4&gt;
  
  
  Caching, and Passing Arguments
&lt;/h4&gt;

&lt;p&gt;If, you are using this technique more than once on a page, then you'll need to pass a "cache-busting" index, or random number to the &lt;code&gt;data:,&lt;/code&gt; eg, something like:&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;img&lt;/span&gt; 
        &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"data:,abc123"&lt;/span&gt; 
        &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;
        &lt;span class="na"&gt;onerror=&lt;/span&gt;&lt;span class="s"&gt;"import('/js/some-component.js').then(_ =&amp;gt; _.default(this))"&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; 
        &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"data:,xyz789"&lt;/span&gt; 
        &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;
        &lt;span class="na"&gt;onerror=&lt;/span&gt;&lt;span class="s"&gt;"import('/js/some-other-component.js').then(_ =&amp;gt; _.default(this))"&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;The string after the ":," can be anything, just so long as they are different.&lt;/p&gt;

&lt;p&gt;A very simple way to pass params to the function would be to use the &lt;code&gt;data-something&lt;/code&gt; attribute in the html like so:&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;img&lt;/span&gt; 
        &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"data:,"&lt;/span&gt; 
        &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;
        &lt;span class="na"&gt;data-message=&lt;/span&gt;&lt;span class="s"&gt;"hello world"&lt;/span&gt;
        &lt;span class="na"&gt;onerror=&lt;/span&gt;&lt;span class="s"&gt;"import('/js/some-component.js').then(_ =&amp;gt; _.default(this))"&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;Since we are passing the &lt;code&gt;this&lt;/code&gt; to the function, you can access the &lt;code&gt;data&lt;/code&gt; attributes like so:&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;
    &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;outerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
        &amp;lt;div class="whatever"&amp;gt;
            &amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;
    `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please let me know what you think in the comments! ❤️&lt;/p&gt;

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