<?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: Diego Sánchez</title>
    <description>The latest articles on DEV Community by Diego Sánchez (@diegosanchezp).</description>
    <link>https://dev.to/diegosanchezp</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%2F322946%2Fe94efc17-ac3e-4ffd-ae5d-7fd25392d907.jpeg</url>
      <title>DEV Community: Diego Sánchez</title>
      <link>https://dev.to/diegosanchezp</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/diegosanchezp"/>
    <language>en</language>
    <item>
      <title>Do you use UML to model complex web applications?
</title>
      <dc:creator>Diego Sánchez</dc:creator>
      <pubDate>Fri, 25 Sep 2020 02:24:17 +0000</pubDate>
      <link>https://dev.to/diegosanchezp/do-you-use-uml-to-model-complex-web-applications-3oko</link>
      <guid>https://dev.to/diegosanchezp/do-you-use-uml-to-model-complex-web-applications-3oko</guid>
      <description>&lt;p&gt;A few weeks ago I was learning from a course object oriented design in which they taught me class, state machine and sequence diagrams using the The Unified Modeling Language.&lt;/p&gt;

&lt;p&gt;I like web development so I asked myself if these diagrams, specifically class diagrams, could be used to model web applications, preferably complex ones.&lt;/p&gt;

&lt;p&gt;At first I though this wouldn't be possible since JavaScript is a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model"&gt;prototype based language&lt;/a&gt; even tho having a class keyword.&lt;/p&gt;

&lt;p&gt;Doing a little bit of research I found and read two papers that addressed this.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://docs.huihoo.com/development/rup/webapps.htm"&gt;Modeling Web Application Architectures with UML&lt;/a&gt; (1999)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.diva-portal.org/smash/get/diva2:832733/FULLTEXT01.pdf"&gt;A comparison of UML and WAE-UML for the design of Web applications&lt;/a&gt; (2005)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The second paper gives good reasons on why use UML to model web apps in chapter 1.4.&lt;/p&gt;

&lt;p&gt;What they do to use UML is to extended it with stereotypes, constraints and tagged values, this new extension is called &lt;a href="https://flylib.com/books/en/2.141.1/web_application_extension_for_uml.html"&gt;Web Application Extension&lt;/a&gt; (WAE). &lt;/p&gt;

&lt;p&gt;As you can see these are old papers, the examples that they show are for what today are called server side rendered web apps.&lt;/p&gt;

&lt;p&gt;I want to know if any of you have used UML to model web pages or if you like to consider UML to do so.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>webdev</category>
      <category>uml</category>
    </item>
    <item>
      <title>mp3split: a simple shell script for splitting mp3 audio files</title>
      <dc:creator>Diego Sánchez</dc:creator>
      <pubDate>Sun, 13 Sep 2020 20:54:45 +0000</pubDate>
      <link>https://dev.to/diegosanchezp/mp3split-a-simple-shell-script-for-splitting-mp3-audio-files-415</link>
      <guid>https://dev.to/diegosanchezp/mp3split-a-simple-shell-script-for-splitting-mp3-audio-files-415</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Downloading mp3 files these days or converting a music video to an mp3 file for later offline playback hasn't been easier these days with programs like &lt;a href="https://rg3.github.io/youtube-dl/"&gt;youtube-dl&lt;/a&gt; and other alike.&lt;/p&gt;

&lt;p&gt;For example if you liked a music mix in youtube, lets say, a '&lt;a href="https://www.youtube.com/watch?v=WI4-HUn8dFc"&gt;syntwave mix&lt;/a&gt;' for your programming sessions and you have downloaded it with one the programs mentioned above, you now have a single mp3 file. But what happens if you didn't like a song in the mix ? Well at first you might think you can't do anything about it, because how you do delete that one annoying song and keep the rest ?&lt;/p&gt;

&lt;p&gt;The solution to that problem is to split the single mp3 file into many more mp3 files and of course delete the one you don't want to keep.&lt;/p&gt;

&lt;p&gt;To begin splitting the mp3 file we would need the time where each song starts i.e timestamps. Many of those music mixes found in youtube give in the video description a 'tracklist' which is primarily compose of a timestamp and the name of the song.&lt;/p&gt;

&lt;p&gt;For example, the one found in the &lt;a href="https://www.youtube.com/watch?v=WI4-HUn8dFc"&gt;syntwave mix&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0:00 Xtract - Audiotool Day 2016
3:55 Alison - space echo
7:25 Volt Age - Volt's Theme 
13:12 Lucy in Disguise - Southbound 
18:05 Lucy in Disguise - Echoes In Time
23:15 HOME - Flood
26:53 De Lorra/Augustus Wright - Let Us 
31:09 bl00dwave - Encounters
33:51 Emil Rottmayer - T.I.M.E ( Part 2 )
40:12 oDDling - Early Bird
43:22 hello meteor - at last light
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We could do the splitting manually with ffmpeg, but it would take a lot of time. Today I present to you &lt;code&gt;mp3split&lt;/code&gt; a simple shell script to aid you in the process of splitting large mp3 files with the help of tracklist and a single dependency &lt;code&gt;ffmpeg&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Usage example
&lt;/h2&gt;

&lt;p&gt;To get started, install the script running the following commands.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;wget https://raw.githubusercontent.com/diegosanchezp/mp3split/master/mp3split.sh &lt;span class="nt"&gt;-O&lt;/span&gt; ~/.local/bin/mp3split &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;chmod &lt;/span&gt;755 ~/.local/bin/mp3split
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This will put the shell script in the folder &lt;code&gt;~/.local/bin/&lt;/code&gt; and can be accessed via terminal as a binary file.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;mp3split -h&lt;/code&gt; to test if the program is installed.&lt;/p&gt;

&lt;p&gt;The script takes as input an mp3 file and a tracklist like the one above.&lt;/p&gt;

&lt;p&gt;To walk you trough the usage I have downloaded the &lt;a href="https://www.youtube.com/watch?v=WI4-HUn8dFc"&gt;syntwave mix&lt;/a&gt; with &lt;code&gt;youtube-dl&lt;/code&gt;, rename it to &lt;code&gt;testsong.mp3&lt;/code&gt; and put the tracklist in a text file named &lt;code&gt;tracklist.txt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you want to split &lt;code&gt;testsong.mp3&lt;/code&gt; automatically, run&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;mp3split testsong.mp3 tracklist.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;It will output information about the created split files to &lt;code&gt;stdout&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=== Begin to create mp3 split files ===
Processed 0:00 to 3:55; Xtract - Audiotool Day 2016.mp3
Processed 3:55 to 7:25; Alison - space echo.mp3
Processed 7:25 to 13:12; Volt Age - Volt's Theme.mp3
Processed 13:12 to 18:05; Lucy in Disguise - Southbound.mp3
Processed 18:05 to 23:15; Lucy in Disguise - Echoes In Time.mp3
Processed 23:15 to 26:53; HOME - Flood.mp3
De Lorra/Augustus Wright - Let Us.mp3: No such file or directory
Processed 26:53 to 31:09; De Lorra/Augustus Wright - Let Us.mp3
Processed 31:09 to 33:51; bl00dwave - Encounters.mp3
Processed 33:51 to 40:12; Emil Rottmayer - T.I.M.E ( Part 2 ).mp3
Processed 40:12 to 43:22; oDDling - Early Bird.mp3
Processed 43:22 to 0:45:55.680000; hello meteor - at last light.mp3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Let's list what files have created it.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;3,1M    Alison - space echo.mp3
2,4M    bl00dwave - Encounters.mp3
5,8M    Emil Rottmayer - T.I.M.E ( Part 2 ).mp3
1,5M    hello meteor - at last light.mp3
3,4M    HOME - Flood.mp3
4,9M    Lucy in Disguise - Echoes In Time.mp3
5,2M    Lucy in Disguise - Southbound.mp3
3,1M    oDDling - Early Bird.mp3
5,3M    Volt Age - Volt's Theme.mp3
3,5M    Xtract - Audiotool Day 2016.mp3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;As you can see a file is missing &lt;code&gt;De Lorra/Augustus Wright&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ffmpeg&lt;/code&gt; throws the following error.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;De Lorra/Augustus Wright - Let Us.mp3: No such file or directory
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;What happened here? &lt;code&gt;ffmpeg&lt;/code&gt; the program that helps to create the splits, interpreted the filename as directory followed by a name, you might want to fix it by substituting the &lt;code&gt;/&lt;/code&gt; by a another character.&lt;/p&gt;

&lt;p&gt;To end the article, I'd have to say that you could also apply this idea of splitting with audio books.&lt;/p&gt;

&lt;p&gt;Thanks for reading.&lt;/p&gt;
&lt;h2&gt;
  
  
  Useful links
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/diegosanchezp"&gt;
        diegosanchezp
      &lt;/a&gt; / &lt;a href="https://github.com/diegosanchezp/mp3split"&gt;
        mp3split
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Shell script for splitting or slicing large mp3 audio files
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
MP3split&lt;/h1&gt;
&lt;p&gt;A Shell script for splitting or slicing large mp3 audio files.&lt;/p&gt;
&lt;p&gt;The idea of this program is to take an mp3 file e.g a music 'mix' downloaded from youtube or another site and split it with a timestamps file found on youtube or another site, you might want to adjust it to the &lt;a href="https://raw.githubusercontent.com/diegosanchezp/mp3split/master/#documentation"&gt;format&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
Table of Contents&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/diegosanchezp/mp3split/master/#required-dependencies"&gt;Required dependencies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/diegosanchezp/mp3split/master/#installation-instructions"&gt;Installation instructions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/diegosanchezp/mp3split/master/#documentation"&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/diegosanchezp/mp3split/master/#usage-example"&gt;Usage example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/diegosanchezp/mp3split/master/#notes-on-errors"&gt;Notes on errors&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
Required dependencies
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;FFmpeg&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Install these dependencies with your package manager.&lt;/p&gt;
&lt;p&gt;For example in Ubuntu and the rest of Debian based systems.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sudo apt install ffmpeg&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
Installation instructions
&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Download the script&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight highlight-source-shell"&gt;&lt;pre&gt;wget https://raw.githubusercontent.com/diegosanchezp/mp3split/master/mp3split.sh -O &lt;span class="pl-k"&gt;~&lt;/span&gt;/.local/bin/mp3split&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This will put the shell script in the folder &lt;code&gt;~/.local/bin/&lt;/code&gt; and can be accessed via terminal as a binary file.&lt;/p&gt;
&lt;p&gt;Also the command above can be executed to update the script.&lt;/p&gt;
&lt;p&gt;You must have the folder &lt;code&gt;~/.local/bin/&lt;/code&gt; added to your &lt;code&gt;$PATH&lt;/code&gt; variable, if you don't want…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/diegosanchezp/mp3split"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



</description>
      <category>linux</category>
      <category>ubuntu</category>
      <category>bash</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I've made a web component to easily implement and switch  two themes in a webpage.</title>
      <dc:creator>Diego Sánchez</dc:creator>
      <pubDate>Sat, 05 Sep 2020 21:23:04 +0000</pubDate>
      <link>https://dev.to/diegosanchezp/i-ve-made-a-web-component-to-easily-implement-and-switch-two-themes-in-a-webpage-1hm2</link>
      <guid>https://dev.to/diegosanchezp/i-ve-made-a-web-component-to-easily-implement-and-switch-two-themes-in-a-webpage-1hm2</guid>
      <description>&lt;p&gt;A lot of websites nowadays have this feature of having two color schemes for the user to choose, namely "dark" and "light", implementing this is a peace of cake with the help of CSS custom properties (variables) and a bit of ECMAscript. Today I present you a web component that abstracts the ECMAscript part and lets you switch between the themes dynamically.&lt;/p&gt;

&lt;p&gt;Using the component is straightforward. The component adds and updates a data attribute "data-theme" to the body element which you can handle in CSS via attribute selectors, so depending on the theme you have you can update your theme variables. &lt;/p&gt;

&lt;p&gt;See a &lt;a href="https://diegosanchezp.github.io/theme-switcher-component"&gt;live demo&lt;/a&gt; before using it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage example
&lt;/h2&gt;

&lt;p&gt;To install it use your preferred package manager.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install theme-switcher-component&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;OR &lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add theme-switcher-component&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In a .html file include and declare the component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Theme switcher component demo&lt;span class="nt"&gt;&amp;lt;/title&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;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"./styles.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Include the component --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./node_modules/theme-switcher-component/switch.js"&lt;/span&gt; &lt;span class="na"&gt;defer&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;main&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;section&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Components are not applications, they are just a part of the whole.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- Declare the component --&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- The first element of the array themes defines the default theme --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;theme-switcher&lt;/span&gt; &lt;span class="na"&gt;themes=&lt;/span&gt;&lt;span class="s"&gt;'["light", "dark"]'&lt;/span&gt; &lt;span class="na"&gt;verbose&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/theme-switcher&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Note: other names in the themes array rather than the typical "light" and "dark" can be defined, for example, "solarized" and "tango".&lt;/p&gt;

&lt;p&gt;In a .css file declare in the root selector the css variables to use and change their values accordingly to the two themes defined selecting the body.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* Define a theme with variables */&lt;/span&gt;
&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* Light theme the default*/&lt;/span&gt;
  &lt;span class="py"&gt;--border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bg-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* Change variables values accordingly*/&lt;/span&gt;

&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"dark"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bg-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* ... More CSS rules below ... */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;After a theme is changed, it gets stored to &lt;code&gt;localStorage&lt;/code&gt;, if you want to see values of the local store and the current theme set the &lt;code&gt;verbose&lt;/code&gt; attribute to the  custom element, like the example.&lt;/p&gt;

&lt;p&gt;That's it ! Hope this helps you. &lt;/p&gt;

&lt;p&gt;If you want more in depth documentation check the github repository&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/diegosanchezp"&gt;
        diegosanchezp
      &lt;/a&gt; / &lt;a href="https://github.com/diegosanchezp/theme-switcher-component"&gt;
        theme-switcher-component
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A web component that helps you implement and change two themes on a web page.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;And the &lt;a href="https://github.com/diegosanchezp/theme-switcher-component/tree/master/demo"&gt;live demo code&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Using nodejs packages in the browser with import maps </title>
      <dc:creator>Diego Sánchez</dc:creator>
      <pubDate>Mon, 17 Aug 2020 17:44:12 +0000</pubDate>
      <link>https://dev.to/diegosanchezp/using-nodejs-packages-in-the-browser-with-import-maps-38ei</link>
      <guid>https://dev.to/diegosanchezp/using-nodejs-packages-in-the-browser-with-import-maps-38ei</guid>
      <description>&lt;p&gt;Import maps is a browser proposal that allow web pages to control the behavior of JavaScript imports, in this article will cover the usage of this feature with nodejs packages, the related problems, and posible solutions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What are import maps&lt;/li&gt;
&lt;li&gt;Using import maps&lt;/li&gt;
&lt;li&gt;Generating import maps&lt;/li&gt;
&lt;li&gt;The problem of NodeJs packages&lt;/li&gt;
&lt;li&gt;Heritage a package manager for modern web development&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;li&gt;Additional notes&lt;/li&gt;
&lt;li&gt;References&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What are import maps &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Import maps is a browser proposal that allow web pages to control the behavior of JavaScript imports, in other words control over what URLs get fetched by JavaScript &lt;code&gt;import&lt;/code&gt; statements and &lt;code&gt;import()&lt;/code&gt; expressions.&lt;/p&gt;

&lt;p&gt;A NodeJs developer is used to import packages this way&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lit-element&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;If we tried to do that directly in the browser it will fail, throwing an error similar to&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;  Uncaught TypeError: Failed to resolve module specifier &lt;span class="s2"&gt;"lit-element"&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; Relative references must start with either &lt;span class="s2"&gt;"/"&lt;/span&gt;, &lt;span class="s2"&gt;"./"&lt;/span&gt;, or &lt;span class="s2"&gt;"../"&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This is happens because the specified path ('lit-element') is 'bare', meaning that is not the full path to the file where the source code of that object is.&lt;/p&gt;

&lt;p&gt;There is also the problem that if we gave the full path of the file, that file could also be importing another package in the same way, with a bare path.&lt;/p&gt;

&lt;p&gt;The typical workaround for this problem is to use a bundler like Rollup or Webpack that resolves all of the paths. And puts all of the required code into one single file.&lt;/p&gt;

&lt;p&gt;There is the exception of packages that have &lt;strong&gt;zero dependencies&lt;/strong&gt; (meaning that they simply do not import from another packages), they do things like relative imports, for example,&lt;code&gt;import { defaultTemplateProcessor } from './lib/default-template-processor.js';&lt;/code&gt;  or have the so called "dist" files which have all of the required code in one single file. &lt;/p&gt;

&lt;p&gt;In those cases we could do something like &lt;code&gt;import { foo } from './node_modules/lib-foo/file.js'&lt;/code&gt; there will be no problems.&lt;/p&gt;

&lt;p&gt;But what if we wanted to still use the bare paths syntax, since is better and more comfortable to work with and have something that tells that a bare path points to a full path. That's exactly what import maps does!   &lt;/p&gt;

&lt;p&gt;Quoting from the specification on &lt;a href="https://www.chromestatus.com/feature/5315286962012160"&gt;chromestatus&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Until import maps, the web has had no native ability to do this kind of mapping (although the specification has included a carveout for it since modules were first introduced). Import maps bring this ability to the web's native module system, putting it on parity with web developer expectations.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Using import maps &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Currently import maps are a experimental feature, the only browser that has implemented it is google-chrome, so, to start using them we have two methods&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enable import maps on google-chrome by putting in the address bar the url &lt;code&gt;chrome://flags/&lt;/code&gt;, then search for import maps in the search bar and enable the flag "Experimental Productivity Features".&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xpeTTgW4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mvyxkeunquguwjsz6rny.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xpeTTgW4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mvyxkeunquguwjsz6rny.png" alt="Chrome flag Experimental Productivity Features image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use a polyfill, in this moment there are two,&lt;a href="https://github.com/guybedford/es-module-shims"&gt;es-module-shims&lt;/a&gt; and &lt;a href="https://github.com/systemjs/systemjs"&gt;SystemJS&lt;/a&gt; for the following example I'll be using the first one.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's begin setting up the example by installing the required dependencies&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;es-dev-server&lt;/code&gt; we are going to need a server because the polyfill uses the fetch api.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;es-module-shims&lt;/code&gt; the polyfill that's going to do the import magic &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lit-element&lt;/code&gt; the dependency that uses the npm system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Install the dependencies with yarn only, we'll need the generated &lt;code&gt;yarn.lock&lt;/code&gt; file for later.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add es-dev-server -D&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add es-module-shims lit-element&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then we are going to craft the html file which will have the import map and the javascript code that uses imports with the bare syntax.&lt;/p&gt;

&lt;p&gt;Make an html file that requires the lit-html dependency&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- index.html --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;ES Import Maps Shim&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Include the polyfill --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;defer&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./node_modules/es-module-shims/dist/es-module-shims.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- Declare the import map wich is a json object that starts with the key "imports". 
    This is an object that contains the mapping of the import URLs to the node_modules folder --&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!--Line 11 below--&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"importmap-shim"&lt;/span&gt;&lt;span class="nt"&gt;&amp;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;imports&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lit-html&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;./node_modules/lit-html/lit-html.js&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;lit-element&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;./node_modules/lit-element/lit-element.js&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;lit-html/lit-html.js&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;./node_modules/lit-html/lit-html.js&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;lit-html/lib/shady-render.js&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;./node_modules/lit-html/lib/shady-render.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- JavaScript code that uses bare module syntax --&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Line 23 below --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module-shim"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;LitElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;css&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lit-element&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;CustomBtn&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;LitElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;styles&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;css&lt;/span&gt;&lt;span class="s2"&gt;`
            button {
              color: blue;
            }
          `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`
            &amp;lt;button&amp;gt;Custom Button&amp;lt;/button&amp;gt;
          `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;customElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;custom-button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CustomBtn&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;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;custom-button&amp;gt;&amp;lt;/custom-button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;

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


&lt;p&gt;Next serve the html file &lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx es-dev-server --app-index index.html --watch --open&lt;/code&gt;&lt;/p&gt;

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

&lt;p&gt;Let's explain some things about the example.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We are making a simple web component with LitElement base class.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The import map makes the bare path in line 25 to be resolved to &lt;code&gt;import { LitElement, html, css } from './node_modules/lit-element/lit-element.js';&lt;/code&gt;. It does the same for the internal imports of &lt;code&gt;lit-element&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you are using chrome with the enabled flag “Experimental Productivity Features”. You don't need line 6, change line 11 to &lt;code&gt;&amp;lt;script type="importmap"&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;  and line 23 to &lt;code&gt;&amp;lt;script type="module"&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is still one thing you might be asking. How did you know how to list those other imports ? If you are only importing lit-element. Well that's one thing we have to take care about, the internal imports of lit-element, doing this by hand might be a huge pain, the import map you see above took me a few minutes to setup, I've had to analyze the &lt;code&gt;package.json&lt;/code&gt; of &lt;code&gt;lit-element&lt;/code&gt; and &lt;code&gt;lit-html&lt;/code&gt; since the first one is dependent on the last one. Even the import map that I've provided could fail for others imports of lit-html.&lt;/p&gt;

&lt;p&gt;So the ideal is to have something more robust, a tool that automatically generates the import map for ourselves.   &lt;/p&gt;
&lt;h3&gt;
  
  
  Generating import maps &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;We'll use the package &lt;a href="https://www.npmjs.com/package/@import-maps/generate"&gt;@import-maps/generate&lt;/a&gt; to generate the import map. The caveats are that it only supports &lt;code&gt;yarn.lock&lt;/code&gt; file ( this is why the dependencies must have be installed only with yarn at the beginning ) and that Windows paths are not supported.&lt;/p&gt;

&lt;p&gt;Install @import-maps/generate as a development dependency&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add @import-maps/generate -D&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To generate the import map run the command &lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx @import-map/generate&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will output the importmap in a file named &lt;code&gt;import-map.json&lt;/code&gt;, below is an example&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"imports"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"es-module-shims/"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/node_modules/es-module-shims/dist/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lit-element"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/node_modules/lit-element/lit-element.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lit-element/"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/node_modules/lit-element/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lit-html"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/node_modules/lit-html/lit-html.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lit-html/"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/node_modules/lit-html/"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Ideally you'll want to generate the import map after installing any additional dependency, to do so add to &lt;code&gt;package.json&lt;/code&gt; a post install script&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"postinstall"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"generate-import-map"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Lastly include the import map by replacing line 11 on the index.html file used before.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- index.html --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;ES Import Maps Shim&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;defer&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./node_modules/es-module-shims/dist/es-module-shims.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- Generated import map --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"importmap-shim"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"import-map.json"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;custom-button&amp;gt;&amp;lt;/custom-button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The problem of NodeJs packages &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Some NodeJs packages might not be compatible with the browser, back before the &lt;code&gt;import/export&lt;/code&gt; (ESM modules) syntax, &lt;code&gt;require()&lt;/code&gt; (CommonJS) was used instead. There is a chance that some package uses a dependency that uses the old syntax making it unusable in the browser since it only understands &lt;code&gt;import/export&lt;/code&gt;. The solution to the problem would be to simply convert the old syntax to the new one, there is a tool that does that automatically &lt;a href="https://www.snowpack.dev/"&gt;Snowpack&lt;/a&gt;, the next example is about it.&lt;/p&gt;

&lt;p&gt;The reason why I choose the lit-element package was because it's ESM ready, thus avoiding the problem described above.&lt;/p&gt;

&lt;p&gt;For the example that covers this topic will continue using web components, instead of making one we will download the paper-button from &lt;a href="https://www.npmjs.com/package/@polymer/paper-button"&gt;@polymer&lt;/a&gt;. The characteristic of this is that it's not declared as an ESM module. If you inspect the &lt;code&gt;node_modules/@polymer/paper-button/package.json&lt;/code&gt; it has no &lt;strong&gt;"module"&lt;/strong&gt; field, even do the file main file uses &lt;code&gt;import&lt;/code&gt; syntax.&lt;/p&gt;

&lt;p&gt;Running the generator from the last example, will trow an exception&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;node:10621&lt;span class="o"&gt;)&lt;/span&gt; UnhandledPromiseRejectionWarning: Error: Cannot find module &lt;span class="s1"&gt;'@polymer/iron-behaviors'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;I've inspect the &lt;code&gt;package.json&lt;/code&gt; of 'iron-behaviors' and didn't find the "main" field. Which is probably what's causing problems.&lt;/p&gt;

&lt;p&gt;Back to Snowpack, it acts as a middleware or intermediary between the dependencies stored in the &lt;code&gt;node_modules&lt;/code&gt; folder and the web browser making these fully compatible. Takes as input a &lt;code&gt;.js&lt;/code&gt; file declared as main in &lt;code&gt;package.json&lt;/code&gt;, analyzes the declared imports and outputs a &lt;code&gt;web_modules&lt;/code&gt; folder with bundled javascript files and the respective import map. &lt;/p&gt;

&lt;p&gt;To start the example install snowpack&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add snowpack -D&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And the component &lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add @polymer/paper-button&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Create a new &lt;code&gt;snowpack.html&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- snowpack.html --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Import Maps with Snowpack&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;defer&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./node_modules/es-module-shims/dist/es-module-shims.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- Import map is located in the web_modules folder --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"importmap-shim"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./web_modules/import-map.json"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module-shim"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"main.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;paper-button&lt;/span&gt; &lt;span class="na"&gt;raised&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Another Button&lt;span class="nt"&gt;&amp;lt;/paper-button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Create &lt;code&gt;main.js&lt;/code&gt; file, inside this file import the paper-button&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@polymer/paper-button/paper-button.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;Update your &lt;code&gt;package.json&lt;/code&gt; main field&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"main.js"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Run the command to generate the web_modules folder&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx snowpack&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you inspect the  &lt;code&gt;web_modules&lt;/code&gt; folder there is one single js file per dependency&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;web_modules/
├── import-map.json
├── lit-element.js
└── @polymer
    └── paper-button
        └── paper-button.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If some of the dependencies share a common dependency they will be put in a common folder.&lt;/p&gt;

&lt;p&gt;Like the last generator you'll want to update the &lt;code&gt;import-map.json&lt;/code&gt; every time a dependency is added, to do so, add to &lt;code&gt;package.json&lt;/code&gt; a postinstall script.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"postinstall"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"snowpack"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Run the server&lt;br&gt;
&lt;code&gt;npx es-dev-server --app-index snowpack.html --watch --open&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You should see a blank page with a button&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--USbG_pM---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/s5dxbl3uw1wvxw3x8v7j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--USbG_pM---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/s5dxbl3uw1wvxw3x8v7j.png" alt="snowpack page"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Heritage a package manager for modern web development&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;We have seen some of the problems related to node packages and how to fix them, the proposed solution required to use snowpack to act as a middleware and convert those packages to ESM modules to be used in the browser, the conversion outputted a web_modules folder which is a shallow copy of node_modules, you might find this a problem when the number of dependencies grow, since there will be code duplication. &lt;/p&gt;

&lt;p&gt;But hey, what happens if you are a person that lives on the edge an only installs ESM ready dependencies and even don't like to much the node_modules folder because is heavy on disk usage, then it wouldn't make sense to use snowpack. You could rely on a content delivery network like &lt;a href="https://unpkg.com/"&gt;unpkg&lt;/a&gt; to import packages and then craft an import map that points to unpkg url's, for example&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"imports"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lit-html"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://unpkg.com/lit-html@latest/lit-html.js?module"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lit-element"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://unpkg.com/lit-element@latest/lit-element.js?module"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lit-html/lit-html.js"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://unpkg.com/lit-html@latest/lit-html.js?module"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lit-html/lib/shady-render.js"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://unpkg.com/lit-html@latest/lib/shady-render.js?module"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This approach looks OK, but there is something that downgrades the development experience, every time when the web page is initially served by a static server, for example, the one we been using &lt;code&gt;es-dev-server&lt;/code&gt; it will have to make a request to the &lt;code&gt;unpkg&lt;/code&gt; servers to get those js files, this is something that I don't personally like since my Internet is slow, what I would like is to make the request once and get those files stored in the disk, something similar of what &lt;a href="https://deno.land/"&gt;Deno&lt;/a&gt; does to "cache" it's dependencies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/nestarz/heritage"&gt;Heritage&lt;/a&gt; is a package manager for the web based on the &lt;a href="https://github.com/WICG/import-maps"&gt;WICG/import-maps&lt;/a&gt; specification, it only have two dependencies &lt;code&gt;acorn&lt;/code&gt; and &lt;code&gt;node-fetch&lt;/code&gt;. Heritage installs node packages is a special way, it downloads them by default from Pika and Unpkg registries and puts them in a folder named &lt;code&gt;web_modules&lt;/code&gt; similar to snowpack. The obvious difference here is that it doesn't need to have a node_modules folder, and for me it's a big plus.&lt;/p&gt;

&lt;p&gt;Let's see an example similar to the others where we install two ESM ready packages &lt;code&gt;lit-element&lt;/code&gt; and &lt;code&gt;@lit-element-bootstrap/button&lt;/code&gt; with heritage. Since heritage generates a web_modules folder this will conflict with the previous setup. &lt;/p&gt;

&lt;p&gt;Create a new folder&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;heritage
&lt;span class="nb"&gt;cd &lt;/span&gt;heritage
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Install heritage&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add -D @eliaspourquoi/heritage&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Installing dependencies with heritage is similar to yarn&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx heritage add lit-element @lit-element-bootstrap/button&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;What heritage will do is to use the &lt;code&gt;package.json&lt;/code&gt; to register required packages under the &lt;code&gt;webDependencies&lt;/code&gt; field, exactly like Snowpack before version 2. The lock file is the generated &lt;code&gt;import-map.json&lt;/code&gt; used to manage imports by the browser.&lt;/p&gt;

&lt;p&gt;Check the &lt;code&gt;package.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"webDependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"lit-element"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.3.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@lit-element-bootstrap/button"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;One minor problem here, installing &lt;code&gt;es-module-shims&lt;/code&gt; with heritage trowed an exception, so I'll have to install it with yarn.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add es-module-shims&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Install the server&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add es-dev-server -D&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Use installed packages&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- heritage.html --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Heritage&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Include the polyfill --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;defer&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./node_modules/es-module-shims/dist/es-module-shims.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- Include the import map generated by heritage --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"importmap-shim"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"web_modules/import-map.json"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- Make a custom button, and use the downloaded web component --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module-shim"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BsButton&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BsButtonDarkCss&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@lit-element-bootstrap/button&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;LitElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;css&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lit-element&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;CustomBtn&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;LitElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="nx"&gt;BsButtonDarkCss&lt;/span&gt; 
          &lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`
            &amp;lt;bs-button context="dark"&amp;gt;Dark custom bootstrap button&amp;lt;/bs-button&amp;gt;
          `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;customElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;custom-button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CustomBtn&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;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;custom-button&amp;gt;&amp;lt;/custom-button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Run the server&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx es-dev-server --app-index heritage.html --watch --open&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ON1sv5cu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7mo5ajgzcf84ch65of88.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ON1sv5cu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7mo5ajgzcf84ch65of88.png" alt="boostrap style button installed with heritage"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Conclusion &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Import maps is a great proposal that enhances the development workflow and makes a bridge between the npm ecosystem and the browser, sadly is not all pretty, there is compatibility problems between the import system that uses the browser ESM and the one that nodejs used in the past commonJS, snowpack has provided a way to breach into this problem.&lt;/p&gt;

&lt;p&gt;The one thing that I personally don't Like about snowpack is that is that there will be duplication of code, the node_modules and web_modules folder are similar. I guess that's the price to pay for a package manager that was not designed to work with the browser.&lt;/p&gt;

&lt;p&gt;Heritage provides a morden way to install packages, it's still a new technology so I dont expect it to be as robust and have the same features as the yarn package manager for example.&lt;/p&gt;
&lt;h2&gt;
  
  
  Additional notes &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Check out the &lt;a href="https://github.com/diegosanchezp/import-maps-examples"&gt;github source code repository&lt;/a&gt; with all the examples included!&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/diegosanchezp"&gt;
        diegosanchezp
      &lt;/a&gt; / &lt;a href="https://github.com/diegosanchezp/import-maps-examples"&gt;
        import-maps-examples
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Examples of import-maps 
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Import Maps Examples&lt;/h1&gt;
&lt;p&gt;Simple examples of &lt;a href="https://github.com/WICG/import-maps"&gt;import maps&lt;/a&gt; using the polyfill &lt;a href="https://github.com/guybedford/es-module-shims"&gt;es-module-shims&lt;/a&gt;. These examples come from the &lt;a href="https://diegosanchezp.github.io/blog/import-maps" rel="nofollow"&gt;blog post&lt;/a&gt;, visit for better explanation.&lt;/p&gt;
&lt;p&gt;The purpose of these examples is try to use &lt;a href="https://lit-element.polymer-project.org/guide/start" rel="nofollow"&gt;lit-element&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/@polymer/paper-button" rel="nofollow"&gt;@polymer/paper-button&lt;/a&gt; with bare module specifiers in the browser without a bundler.&lt;/p&gt;
&lt;h2&gt;
Get started&lt;/h2&gt;
&lt;p&gt;Dependencies can only be installed with yarn
&lt;code&gt;yarn install&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The import-map.json file should be auto generated after installed dependencies, if not
&lt;code&gt;yarn run postinstall&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Generate the web_modules folder
&lt;code&gt;npx run snowpack&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;To see the examples in the browser, run the scripts in &lt;code&gt;package.json&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
Notes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="comment-mentioned-user" href="https://dev.to/polymer"&gt;@polymer&lt;/a&gt;
/paper-button had to be installed as a development dependency, since it would have conflicts with &lt;a href="https://www.npmjs.com/package/@import-maps/generate" rel="nofollow"&gt;@import-maps/generate&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you run the script "serve-chrome", you'll need to have the flag "Experimental Productivity Features" enabled on chrome. Read the blog post to find how to.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/diegosanchezp/import-maps-examples"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Snowpack and the polyfill es-module-shim can do much more than the examples provided here. I encourage you to checkout their documentation.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can check the progress of the import maps on &lt;a href="https://www.chromestatus.com/feature/5315286962012160"&gt;chromestatus.com&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Import maps can also be used with &lt;a href="https://unpkg.com/"&gt;unpkg&lt;/a&gt; content delivery network. The bare syntax can be mapped to an unpkg url,&lt;a href="https://deno.land/manual/linking_to_external_code/import_maps"&gt;Deno&lt;/a&gt; uses import maps to do something similar. You can even use unpkg urls as a fallback in case a module is not available in the node_modules folder.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  References &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.snowpack.dev/"&gt;Snowpack&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.chromestatus.com/feature/5315286962012160"&gt;Import maps - chromestatus.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/WICG/import-maps"&gt;Import maps - Editor's draft&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://wicg.github.io/import-maps/"&gt;Import Maps Draft Community Group Report&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>node</category>
      <category>importmaps</category>
    </item>
  </channel>
</rss>
