<?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: Orhun Özer</title>
    <description>The latest articles on Forem by Orhun Özer (@orabazu).</description>
    <link>https://forem.com/orabazu</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%2F264171%2F53205ee8-5eec-42c7-a566-238e59daedef.png</url>
      <title>Forem: Orhun Özer</title>
      <link>https://forem.com/orabazu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/orabazu"/>
    <language>en</language>
    <item>
      <title>kill any port from terminal 🥷</title>
      <dc:creator>Orhun Özer</dc:creator>
      <pubDate>Wed, 17 May 2023 16:25:12 +0000</pubDate>
      <link>https://forem.com/orabazu/kill-any-port-from-terminal-2l1b</link>
      <guid>https://forem.com/orabazu/kill-any-port-from-terminal-2l1b</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;killport&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$# &lt;/span&gt;&lt;span class="nt"&gt;-eq&lt;/span&gt; 0 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Usage: killport &amp;lt;port&amp;gt;"&lt;/span&gt;
        &lt;span class="k"&gt;return &lt;/span&gt;1
    &lt;span class="k"&gt;fi

    &lt;/span&gt;&lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;lsof &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;-i4TCP&lt;/span&gt;:&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$port&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'NR&amp;gt;1 {print $2}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nv"&gt;$pid&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;kill&lt;/span&gt; &lt;span class="nt"&gt;-9&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$pid&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Process with PID &lt;/span&gt;&lt;span class="nv"&gt;$pid&lt;/span&gt;&lt;span class="s2"&gt; killed."&lt;/span&gt;
    &lt;span class="k"&gt;else
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"No process found running on port &lt;/span&gt;&lt;span class="nv"&gt;$port&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add this to &lt;code&gt;.zshrc&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Call &lt;code&gt;killport 8080&lt;/code&gt; from terminal.&lt;/p&gt;

</description>
      <category>terminal</category>
      <category>bash</category>
    </item>
    <item>
      <title>Configuring Git SSH Keys for Multiple Accounts and Workspaces</title>
      <dc:creator>Orhun Özer</dc:creator>
      <pubDate>Thu, 30 Mar 2023 09:54:04 +0000</pubDate>
      <link>https://forem.com/orabazu/configuring-ssh-keys-and-git-for-multiple-accounts-and-workspaces-4o0i</link>
      <guid>https://forem.com/orabazu/configuring-ssh-keys-and-git-for-multiple-accounts-and-workspaces-4o0i</guid>
      <description>&lt;p&gt;You can have different keys based on different domains. The following code is an example of how you can configure your SSH keys for different accounts on GitHub and Bitbucket.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;code ~/.ssh/config&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Personal account
Host github.com
   HostName github.com
   User git
   UseKeychain yes 
   AddKeysToAgent yes
   IdentityFile ~/.ssh/id_ed25519

# Work account-1
Host bitbucket.org    
   HostName bitbucket.org
   User git
   UseKeychain yes
   AddKeysToAgent yes
   IdentityFile ~/.ssh/id_rsa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Multiple git configs
&lt;/h2&gt;

&lt;p&gt;If you want to have multiple git configs one of the easiest ways to achieve this is having a separate workspaces and gitconfigs respectively.&lt;/p&gt;

&lt;p&gt;In the context git, a workspace refers to a directory or folder on your computer where you store your work-related projects and files.&lt;/p&gt;

&lt;p&gt;By using the includeIf directive in your .gitconfig file, you can tell Git to use a specific configuration file depending on which workspace you're currently in.&lt;/p&gt;

&lt;p&gt;In case you don't have a gitconfig;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch .gitconfig 
code .gitconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside of  .gitconfig separate config files based on path&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[includeIf "gitdir:/Users/your_username/workspace-company/"]
path = ~/.gitconfig-company
[includeIf "gitdir:/Users/your_username/workspace-personal/"]
path = ~/.gitconfig-personal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then in each config you’ll have different setup.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.gitconfig-company&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[user]
 name = Orhun Ozer
 email = orhun.ozer@company.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;.gitconfig-personal&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[user]
 name = HelluvaDevelopa
 email = helluva@developa.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExYTI1NWU4MTliMDhjNTRkM2Y0ZWVjMjNhZjBlYTU4M2I5ZDhlZTUwOCZjdD1n/goEWraNuCucVi/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExYTI1NWU4MTliMDhjNTRkM2Y0ZWVjMjNhZjBlYTU4M2I5ZDhlZTUwOCZjdD1n/goEWraNuCucVi/giphy.gif" width="350" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Resources &lt;a href="https://www.freecodecamp.org/news/how-to-handle-multiple-git-configurations-in-one-machine/"&gt;freecodecamp&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Three.js text scenes on Google Maps are so-good-it-hurts 🏙🔠😎</title>
      <dc:creator>Orhun Özer</dc:creator>
      <pubDate>Thu, 17 Nov 2022 22:16:47 +0000</pubDate>
      <link>https://forem.com/orabazu/threejs-text-scenes-on-google-maps-are-so-good-it-hurts-2fb0</link>
      <guid>https://forem.com/orabazu/threejs-text-scenes-on-google-maps-are-so-good-it-hurts-2fb0</guid>
      <description>&lt;p&gt;I genuinely love 3D text tracking titles in movies like the example below. We are going to put the name of the city near a historic location in a similar way for this example. Only on a map.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfg9cwc744ofwp1h7aif.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfg9cwc744ofwp1h7aif.gif" alt="Text tracking"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me show you how I did something similar on google maps. Source code at the end 👇 &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy6yuh0ntytovhjl1pr36.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy6yuh0ntytovhjl1pr36.gif" alt="3d Text on the map"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First you need to install dependencies&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add @googlemaps/js-api-loader @googlemaps/three three

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

&lt;/div&gt;



&lt;p&gt;Import the libraries&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;ThreeJSOverlayView&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;latLngToVector3&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;@googlemaps/three&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;Loader&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;@googlemaps/js-api-loader&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;Before loading data make sure you have vector maps enabled from google console. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmugp37cn9b3w6y0qrryk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmugp37cn9b3w6y0qrryk.png" alt="google vector maps"&gt;&lt;/a&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LOADER_OPTIONS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_API_KEY_HERE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;beta&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// to use beta features &lt;/span&gt;
  &lt;span class="na"&gt;libraries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mapOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// location of Galata Tower at Istanbul&lt;/span&gt;
  &lt;span class="na"&gt;center&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;41.025615&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lng&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;28.974133&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;zoom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;heading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;tilt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;mapId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OPTIONALLY_MAP_ID_HERE&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;new&lt;/span&gt; &lt;span class="nc"&gt;Loader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;LOADER_OPTIONS&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&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="p"&gt;...&lt;/span&gt; &lt;span class="nx"&gt;threejs&lt;/span&gt; &lt;span class="nx"&gt;stuff&lt;/span&gt; &lt;span class="nx"&gt;goes&lt;/span&gt; &lt;span class="nx"&gt;here&lt;/span&gt; 

&lt;span class="p"&gt;})&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;A three.js scene inside google maps is not much different than you would see in an ordinary Three.js scene. Therefor you have light and objects.&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;// installing map here&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;map&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;google&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;map&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;mapOptions&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// creating new scene&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scene&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;THREE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Scene&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;ambientLight&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;THREE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AmbientLight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0xffffff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.75&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ambientLight&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;directionalLight&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;THREE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DirectionalLight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0xffffff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// default light comes from above&lt;/span&gt;
  &lt;span class="nx"&gt;directionalLight&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;directionalLight&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;intensity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;directionalLight&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;directionalLightHelper&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To render fonts within Three we will use &lt;code&gt;FontLoader&lt;/code&gt;. I am using Helvetiker Regular font for this example. You can find it in the source code as well.&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;FontLoader&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;three/examples/jsm/loaders/FontLoader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fontLoader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FontLoader&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;fontLoader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./font.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;font&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;font&lt;/span&gt; &lt;span class="nx"&gt;stuff&lt;/span&gt; &lt;span class="nx"&gt;here&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are going add Geometry and Material combined as a Mesh. You can't use pixel coordinates because you are rendering on a map. &lt;code&gt;latLngToVector3&lt;/code&gt; is going to do the transformation for us.&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;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ISTANBUL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;titleGeom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TextGeometry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;font&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;textMaterial&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;THREE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;MeshPhongMaterial&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;0xff2d00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;specular&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;0xffffff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;titleMesh&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;THREE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Mesh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;titleGeom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;textMaterial&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// set position behind the tower&lt;/span&gt;
    &lt;span class="nx"&gt;titleMesh&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nf"&gt;latLngToVector3&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;41.024615&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;lng&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;28.974533&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;titleMesh&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Then we are going add the scene to the map. Here we are also enriching the experience with nice camera movement to get closer to the scene.&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;// instantiate the ThreeJS Overlay with the scene and map&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;overlay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ThreeJSOverlayView&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;scene&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;THREE&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;Animation using &lt;code&gt;requestAnimationFrame&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;animate&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="p"&gt;{&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;mapOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tilt&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;67.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;mapOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tilt&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;mapOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;heading&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;mapOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zoom&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mf"&gt;0.005&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;mapOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;heading&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;210&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;mapOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;heading&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;mapOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zoom&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mf"&gt;0.007&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="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// exit animation loop&lt;/span&gt;
      &lt;span class="k"&gt;return&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;tilt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;heading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;zoom&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mapOptions&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="nf"&gt;moveCamera&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;tilt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;heading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;zoom&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Source code -&amp;gt; &lt;a href="https://github.com/orabazu/threejs-text-googlemaps" rel="noopener noreferrer"&gt;https://github.com/orabazu/threejs-text-googlemaps&lt;/a&gt;&lt;/p&gt;

</description>
      <category>threejs</category>
      <category>googlemaps</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Visualizing a mountain using Three.js, Landsat and SRTM</title>
      <dc:creator>Orhun Özer</dc:creator>
      <pubDate>Tue, 15 Nov 2022 19:41:10 +0000</pubDate>
      <link>https://forem.com/orabazu/visualizing-a-mountain-using-threejs-landsat-and-srtm-50kp</link>
      <guid>https://forem.com/orabazu/visualizing-a-mountain-using-threejs-landsat-and-srtm-50kp</guid>
      <description>&lt;p&gt;Originally posted on Medium on Mar 11, 2019 &lt;br&gt;
&lt;a href="https://zubazor.medium.com/visualizing-a-mountain-using-three-js-landsat-and-srtm-26275c920e34"&gt;https://zubazor.medium.com/visualizing-a-mountain-using-three-js-landsat-and-srtm-26275c920e34&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Using freely available satellite data and Javascript you can visualize a topography on earth. Link to source &lt;a href="https://github.com/zhunor/threejs-dem-visualizer"&gt;code&lt;/a&gt; and &lt;a href="https://zhunor.github.io/threejs-dem-visualizer/"&gt;demo&lt;/a&gt;. If you think it’s going to be fun let’s continue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/r07K4fvHDD8Z2/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/r07K4fvHDD8Z2/giphy.gif" width="408" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Mount What?
&lt;/h2&gt;

&lt;p&gt;A few weeks back, I decided to spend some time with Three.js in my leisure. I decided to visualize the 3D model of Turkey’s highest mountain: Mount Ağrı, only using freely available satellite data and Javascript. Like 15th century romantic William Blake once said; “Great things are done when men and mountains meet”. So, Willy, it is gonna be hilarious baby.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bootstrapping with ES6 and Webpack
&lt;/h2&gt;

&lt;p&gt;There are plenty of good examples in Github but I’ll go forward with the &lt;a href="https://github.com/jackdbd/threejs-es6-webpack-starter"&gt;https://github.com/jackdbd/threejs-es6-webpack-starter&lt;/a&gt; because it has all of the features I need and more and also easy to understand.&lt;/p&gt;

&lt;h2&gt;
  
  
  DATA
&lt;/h2&gt;

&lt;p&gt;Mount Ağrı&lt;/p&gt;

&lt;p&gt;The data I am going to use is freely available and provided by the &lt;a href="https://twitter.com/usgs"&gt;USGS&lt;/a&gt;. Using earth explorer I downloaded DEM(Digital Elevation Model) and satellite image of Ağrı Mountain which is a passive volcano and also the highest mountain in Turkey.&lt;/p&gt;

&lt;p&gt;I downloaded a few images using USGS application then tried to find an image with cloud coverage of less than 10%&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--euNFmhkB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ajzwnafnyk05fkd7csh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--euNFmhkB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ajzwnafnyk05fkd7csh.png" alt="qgis" width="880" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Downloading image from &lt;a href="https://earthexplorer.usgs.gov/"&gt;https://earthexplorer.usgs.gov/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Good, The Bad and The Landsat 🛰️
&lt;/h2&gt;

&lt;p&gt;If you are not familiar with remote sensing and image processing you might not hear about the Landsat but, is a continuous satellite mission controlled by USGS and provides scientific satellite imagery for researchers with approx. 30m2 resolution for many years. One pixel of the image covers an area of 30m2 where the satellite’s camera is perpendicular to the earth. Nowadays some satellites have a resolution less than a meter but generally, they are not freely available. So, Landsat is not so good or bad, but it is enough for us, we are going to use this old loyal fella for our textures.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://earthexplorer.usgs.gov/"&gt;https://earthexplorer.usgs.gov/&lt;/a&gt; is the source for downloading free satellite imagery. The images should have a cloud coverage of less than 10% and it should be added to the criteria. It was hard to find a good one since the mountain is so high that it is cloudy every time. After finding a suitable image I realized that Landsat covers a huge area and I needed to crop my area of interest. After cropping this is going to be the texture of the model. But more importantly, I need an elevation model to visualize the mountain.&lt;/p&gt;

&lt;h2&gt;
  
  
  SRTM — I don’t give a DEM 🗻
&lt;/h2&gt;

&lt;p&gt;Yeah, actually it gives a DEM. DEM stands for Digital Elevation Model and it is raster based elevation data. SRTM which stands for “Shuttle Radar Topography Mission” is operated by NASA. (&lt;a href="https://www2.jpl.nasa.gov/srtm/"&gt;https://www2.jpl.nasa.gov/srtm/&lt;/a&gt;) The SRTM offers a DEM with 30m resolution. Let’s recall; it means one pixel covers the approximately 30m area and the average elevation of that area as the pixel value. This data is extremely valuable for generating our mountain model in three.js&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre Processing
&lt;/h2&gt;

&lt;p&gt;I used QGIS one of my favorite products for GIS. I cut and mask the DEM and related satellite image using QGIS raster tools and copy them to the working directory.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XYiFWZEY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sq35z6kom8ekrmcwokvj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XYiFWZEY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sq35z6kom8ekrmcwokvj.png" alt="qgis" width="880" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clipping image and DEM in QGISLooks kind of scary, digital elevation model over satellite image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Mt2f42fz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r5rxflf8xqhraemturc3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Mt2f42fz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r5rxflf8xqhraemturc3.png" alt="dem" width="880" height="617"&gt;&lt;/a&gt;&lt;br&gt;
Looks like the Mouth Doom but this is how the elevation model looks like in QGIS with default color palette. I clipped two different sizes concerning performance, you can find both at the repo. I use the small one in the demo to see results fast.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three.js
&lt;/h2&gt;

&lt;p&gt;Three.js is an excellent library for using WebGL easily. It might seem complicated at first glance, we will slice it into pieces to understand better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lights, Camera, Action
&lt;/h2&gt;

&lt;p&gt;In order to start three.js in beginner level this tutorial is very helpful. &lt;a href="https://aerotwist.com/tutorials/getting-started-with-three-js/"&gt;https://aerotwist.com/tutorials/getting-started-with-three-js/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Three.js world we need some basic setup. 4 basic components&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; A scene&lt;/li&gt;
&lt;li&gt; A renderer&lt;/li&gt;
&lt;li&gt; A camera&lt;/li&gt;
&lt;li&gt; An object or two (with materials)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A note about materials
&lt;/h2&gt;

&lt;p&gt;I don’t care about materials in this example because the satellite image is already enlightened by the sun itself when the image is acquired. Therefore we have natural cloud shadows according to sun angle. So, I don’t mind which angle the light is coming from also. If you wonder you can dig the metadata file of Landsat image to find out in which sun angle it has when the image is acquired. Then you can simulate the same light with shaders etc. If you want real reflections you can consider using some of the shapes above.&lt;/p&gt;

&lt;p&gt;Materials and reflections&lt;/p&gt;

&lt;h2&gt;
  
  
  Let’s start
&lt;/h2&gt;

&lt;p&gt;We’ll start with adding a scene, then we’ll set renderer, camera, controls, and light. Adding light is crucial otherwise you cannot see anything on the scene.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shaping The Mountain
&lt;/h2&gt;

&lt;p&gt;The geometry of our object is not modeled in Blender, Maya, or something similar. These kinds of models can be imported to three.js easily. But I am going to use DEM file to generate a model directly in js with the help of “geotiff” library.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading Image
&lt;/h2&gt;

&lt;p&gt;Inside setupTerrainModel after adding clipped images to the project we use geotiff library to read DEM file and add a new PlaneGeometry object passing size of the image. Ok let’s generate the big boy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/3o8doT5DaMjfH3paHC/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3o8doT5DaMjfH3paHC/giphy.gif" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then read pixel values that each pixel corresponding to an elevation value. I just heuristically divide it to “20” to make it look nice and multiplied it with -1 otherwise model will be upside down because of the z-coordinate direction of three.js, I’ll explain it later. Using console.time let us see the performance.&lt;/p&gt;

&lt;p&gt;From now on our model is ready to pop up in the browser but without a satellite image, it is only a 3D model and going to looks like the one above.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GPYSJey7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mw1skbvxg0la1q3xslmt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GPYSJey7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mw1skbvxg0la1q3xslmt.png" alt="3d mesh" width="880" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3D mesh of Mount Ağrı in three.js&lt;/p&gt;

&lt;h2&gt;
  
  
  Texture Fitting
&lt;/h2&gt;

&lt;p&gt;After generating the model, we are going to use an RGB satellite image which is also clipped with QGIS earlier.&lt;/p&gt;

&lt;p&gt;We are loading the satellite image and keep in a variable called “material” to use with Three.MESH just after. And don’t forget to rotate the object because three.js has start with the right-hand coordinate system which means, by default Z-axis is not towards upwards but you. For a detailed explanation: &lt;a href="https://tweedegolf.nl/blog/5/threejs-rotations"&gt;https://tweedegolf.nl/blog/5/threejs-rotations&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can either rotate the x-axis or rotate the camera at the beginning by &lt;code&gt;camera.up.set(0,0,1)&lt;/code&gt; Rotating x-axis and putting out mountain just above and moving down a little bit in y-axis let’s run and swish. It is ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo &amp;amp; Source Code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A9mAsixL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bvz7xhyj1ppvnz1ldoet.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9mAsixL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bvz7xhyj1ppvnz1ldoet.png" alt="Three.js Model" width="880" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are two versions of DEM model (one is very large) you can test it in your local environment. I’ve used the small version for the demo. &lt;a href="https://zhunor.github.io/threejs-dem-visualizer/"&gt;https://zhunor.github.io/threejs-dem-visualizer/&lt;/a&gt; &lt;a href="https://github.com/zhunor/threejs-dem-visualizer"&gt;https://github.com/zhunor/threejs-dem-visualizer&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits &amp;amp; Gains
&lt;/h2&gt;

&lt;p&gt;Well, it is hard to find a nice cloudless image first of all. Secondly generating a 3D model with all detail is extremely costly. Maybe the DEM should be downscaled to a reasonable resolution if someone really willing to do it in client-side.&lt;/p&gt;

&lt;p&gt;Tutorials of &lt;a href="https://github.com/jonathanlurie/ThreejsDEM"&gt;https://github.com/jonathanlurie/ThreejsDEM&lt;/a&gt; and &lt;a href="http://blog.mastermaps.com/2013/10/terrain-building-with-threejs.html"&gt;http://blog.mastermaps.com/2013/10/terrain-building-with-threejs.html&lt;/a&gt; was extremely helpful. Thank you guys.&lt;/p&gt;

</description>
      <category>threejs</category>
      <category>gis</category>
      <category>3d</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to bundle a tree-shakable typescript library with tsup and publish with npm</title>
      <dc:creator>Orhun Özer</dc:creator>
      <pubDate>Wed, 02 Nov 2022 13:15:41 +0000</pubDate>
      <link>https://forem.com/orabazu/how-to-bundle-a-tree-shakable-typescript-library-with-tsup-and-publish-with-npm-3c46</link>
      <guid>https://forem.com/orabazu/how-to-bundle-a-tree-shakable-typescript-library-with-tsup-and-publish-with-npm-3c46</guid>
      <description>&lt;p&gt;Header image is generated by &lt;a href="https://creator.nightcafe.studio/" rel="noopener noreferrer"&gt;Night Cafe's AI&lt;/a&gt; btw.&lt;/p&gt;

&lt;p&gt;Thinking of the vast frontend ecosystem, for the most part, I don’t need to implement stuff on my own. The majority of the time, I google a particular problem and most of the time I find a library or stack-overflow answer, Bingo. But there are times when I find myself lacking something unique, whether it is a company task or a hackathon project, a holistic approach, a whole new sexy vibe is needed indeed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/SgLc1OBmibrqBBSJJW/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/SgLc1OBmibrqBBSJJW/giphy.gif" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Recently I was trying to get my head around sports analytics and realized that like the majority of the data science ecosystem, all tools are written in python. While I was re-studying to sharpen my rusted python skills (no pun intended 🦀), I also tried to do some stuff with JS for fun as well, which turned into to a separate library based on D3. In this blog post, I won’t explain the library itself because that's another story (P.S watch this space). But this time I'll share a very basic setup to enable you to come up with your own with a minimum of fuss. &lt;strong&gt;Github link at the end 👇&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;For a JS/TS library you would need a transpiler/bundler, a module strategy, a published version of your lib, and optionally a demonstration app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bundler (esbuild &amp;amp; tsup)
&lt;/h2&gt;

&lt;p&gt;esbuild claimed to be the fastest in the town when it comes to bundlers, and it seems so according to benchmarks as well. Similar to &lt;code&gt;Parcel&lt;/code&gt;, tsup is a zero-config library(in case you don't want it) based on esbuild. Parcel is based on &lt;code&gt;Rust&lt;/code&gt; based &lt;a href="https://swc.rs/" rel="noopener noreferrer"&gt;swc&lt;/a&gt; compiler meanwhile esbuild is based on &lt;a href="https://esbuild.github.io/faq/#why-is-esbuild-fast" rel="noopener noreferrer"&gt;&lt;code&gt;Go&lt;/code&gt;&lt;/a&gt;. Tsup is tailored to work seamlessly with TS. Even though it is zero config you can change the configs if need be, so we do. Here is the config I used for this article.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tsup.config.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import type { Options } from 'tsup';

const env = process.env.NODE_ENV;

export const tsup: Options = {
  splitting: true,
  clean: true, // clean up the dist folder
  dts: true, // generate dts files
  format: ['cjs', 'esm'], // generate cjs and esm files
  minify: env === 'production',
  bundle: env === 'production',
  skipNodeModulesBundle: true,
  entryPoints: ['src/index.ts'],
  watch: env === 'development',
  target: 'es2020',
  outDir: env === 'production' ? 'dist' : 'lib',
  entry: ['src/**/*.ts'], //include all files under src
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are transpiling all our TS files into JS with the help of &lt;code&gt;tsup&lt;/code&gt;'s config. Afterwards we will publish it with &lt;code&gt;npm&lt;/code&gt; in JS format with type declarations so that both JS and TS apps can use it. &lt;/p&gt;

&lt;p&gt;I need to clarify a few things though. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;splitting&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This is flagged an experimental feature that only works for &lt;code&gt;esm&lt;/code&gt; right now. You need to specify &lt;code&gt;outDir&lt;/code&gt; as well. With this feature, we are enabling tree-shaking so that users don't have to download shared bits of code again and again when they switch between different pages for example. Look &lt;a href="https://esbuild.github.io/api/#splitting" rel="noopener noreferrer"&gt;here&lt;/a&gt; for further info. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;skipNodeModulesBundle&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Skips building dependencies for node modules, and use them as they are imported. As a library builder, you can even bundle and serve your dependencies but this is way beyond the scope of this article.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;dts&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Generates typescript declaration files (e.g. &lt;code&gt;index.d.ts&lt;/code&gt;), useful when you consume libraries with typescript.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;entry&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;See how we enable all files to be parsed by tsup using a simple regex pattern &lt;code&gt;['src/**/*.ts']&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Rest of the options pretty much does the stuff, as the names imply&lt;/p&gt;

&lt;h2&gt;
  
  
  Module Strategy
&lt;/h2&gt;

&lt;p&gt;Handling modules has been a pain in the neck for JS community for a long while. Therefore, there are some different strategies when you want to distribute your JS bundles. 4 major modules around are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;CommonJS&lt;/li&gt;
&lt;li&gt;AMD: Async Module Definition&lt;/li&gt;
&lt;li&gt;UMD: Universal Module Definition&lt;/li&gt;
&lt;li&gt;ES modules&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I won't get into the details of AMD and UMD in this post. But I'd like to talk about CJS and ESM which are the most common ones. There is a distinct difference between CommonJS and ES modules which is &lt;code&gt;Tree shaking&lt;/code&gt;. CommonJS modules are the original way to package JavaScript code for Node.js. Up-to-date versions of node.js support both. The major difference here is in a CommonJS module all of your pretty js files are bundled into a single file. You'll remember the syntax if you've worked on both ends.&lt;/p&gt;

&lt;p&gt;ESM (ES modules)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {john} from "doe";

export jane;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CJS (CommonJS)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const john = require("doe")

module.exports = jane;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tree-shaking
&lt;/h2&gt;

&lt;p&gt;Tree-shaking is eliminating dead code and unused exports from your bundle. With &lt;code&gt;CJS&lt;/code&gt; even if you only going to use a simple &lt;code&gt;Card&lt;/code&gt; component let's say, if it is not tree-shakable library, you need to download the whole library and add it to your vendor chunk eventually. For example one of the most used utility libraries around is lodash and there has been a lot of problem because of its huge bundle size in the &lt;a href="https://stackoverflow.com/questions/35250500/correct-way-to-import-lodash/50656694#50656694" rel="noopener noreferrer"&gt;past&lt;/a&gt; If you use es modules import/exports which are tree-shakable by its nature, bundlers can detect unused exports. Dead codes are eliminated that way. &lt;/p&gt;

&lt;p&gt;You can output different module formats with &lt;code&gt;tsup&lt;/code&gt; but &lt;code&gt;cjs&lt;/code&gt; file won't be tree-shakable. Don't forget you are just making the library tree-shakable. It is the app that uses the library actually shakes and eliminates the dead code. But in this article, I want to output two different formats for two different platforms (web &amp;amp; node) the former one would be tree-shakeable. The main motivation behind it was creating a UI library for me but you never know which platform your library is going to end with if it is not a UI library particularly. So why not provide it in both formats just for sake of doing it 🃏 Below line will handle that for us.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;format: ['cjs', 'esm']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will also change the package.json a bit.&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main&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;lib/index.cjs&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;module&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;lib/index.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;types&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;lib/index.d.ts&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;The module field is used to determine the ES version of the package. Also, we want to mark our library as an &lt;code&gt;es&lt;/code&gt; module. To do so, we'll add the below line to package.json.&lt;br&gt;
&lt;br&gt;
  &lt;code&gt;"type": "module",&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 which affects tsup compilation as well in terms of file extensions.&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="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;          &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;esm&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cjs&lt;/span&gt;         &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;cjs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;index.js is an es module now. The reason behind all this is for a UI library we want its components/classes to be importable separately so that the user can import a Component like the one below in an async manner.&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;script type="module"&lt;/code&gt; lets the browser treat this piece of import as a module&lt;/p&gt;

&lt;h3&gt;
  
  
  Output Directories
&lt;/h3&gt;

&lt;p&gt;If you ever investigated libraries like Ant Design you'll recognize that there will be a separate lib folder inside of the package, from which you can import particular components from. We would have both &lt;code&gt;lib&lt;/code&gt; and &lt;code&gt;dist&lt;/code&gt; libraries. &lt;code&gt;dist&lt;/code&gt; would stand for bundle version of your files and possibly could be used when you want to distribute your library over a CDN for example.&lt;/p&gt;

&lt;h4&gt;
  
  
  Used and Unused Exports 🤔
&lt;/h4&gt;

&lt;p&gt;Now try to look at this implementation the other way around.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/hbN2kKXzFqQuyEsFb6/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/hbN2kKXzFqQuyEsFb6/giphy.gif" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's assume an app has our library as a dependency and this app use webpack or a similar bundler that is ready to tree-shake our library. It can detect unused exported modules thanks to a feature called &lt;a href="https://webpack.js.org/configuration/optimization/#optimizationusedexports" rel="noopener noreferrer"&gt;usedExports&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;But if you bundle all your js into a single whole bundle will be imported anyway. There is another concept called &lt;code&gt;sideEffect&lt;/code&gt; pops out at this stage. According to webpack &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A "side effect" is defined as code that performs a special behavior when imported, other than exposing one or more exports. An example of this are polyfills, which affect the global scope and usually do not provide an export.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Webpack can identify if it should run this optimization by checking a custom field called &lt;code&gt;sideEffects&lt;/code&gt; inside &lt;code&gt;package.json&lt;/code&gt;. Preserving module structure and serving library with tiny modules enable bundlers to eliminate the dead code. &lt;br&gt;
If you have a particular module that you want to be bundled whether it is used or not, you should add it to the sideEffect list. This includes scss or other files as well. A possible sideEffects configuration that you can add to your package.json is&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sideEffects&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;dist/*&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;lib/**/style/*&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;*.scss&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;In the above example, you're telling webpack not to clean modules considered to be dead code and this makes sense because under a dist folder possibly you have a single minified bundle including all needed utility functions, etc. It can be even a CJS module in which tree-shaking is not possible. The same is true for your style files, you possibly need all of them, it might be misleading to tell webpack to skip the whole module/subtree of scss. &lt;/p&gt;

&lt;h3&gt;
  
  
  How to test if &lt;code&gt;sideEffects&lt;/code&gt;actually works
&lt;/h3&gt;

&lt;p&gt;Basically looking at the bundle. Let's assume a very basic library &lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;index.ts&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;sum&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;./Sum&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sampleJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;f5e7457f-467d-4e37-9652-f2fb1b51c712&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;sampleJson&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and inside &lt;code&gt;Sum&lt;/code&gt; we are just exporting a basic sum method&lt;br&gt;
&lt;code&gt;Sum/index.ts&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&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;number&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="nx"&gt;number&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;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After we transpile with &lt;code&gt;tsup&lt;/code&gt; all the files will be added to the bundle. Note that we are preserving folder structure under lib.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp4k52qo06b3ff84l2rqq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp4k52qo06b3ff84l2rqq.png" alt="Image description" width="415" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's jump into to the app and locally link the library for testing. I'll use this webpack starter &lt;a href="https://github.com/wbkd/webpack-starter" rel="noopener noreferrer"&gt;https://github.com/wbkd/webpack-starter&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing with npm link
&lt;/h3&gt;

&lt;p&gt;The easiest way to test your library is to register it locally with &lt;code&gt;npm link&lt;/code&gt; or &lt;code&gt;yarn link&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn link v1.22.19
success Registered "tsup-library-template".
info You can now run `npm link "tsup-library-template"` in the projects where you want to use this package and it will be used instead.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then go to the app you want to use the library then &lt;code&gt;yarn link &amp;lt;your-library&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn link v1.22.19
success Using linked package for "tsup-library-template".
✨  Done in 0.02s.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the quickest way to set you up. If you want to manage your lib and examples in the same monorepo have a look at the &lt;a href="https://yarnpkg.com/features/workspaces" rel="noopener noreferrer"&gt;yarn workspaces&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Let's use the library
&lt;/h3&gt;

&lt;p&gt;Inside the app we will use library like this &lt;/p&gt;

&lt;p&gt;&lt;code&gt;someApp.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {sum} from 'tsup-library-template';

console.log(sum);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;even though library has two expected members we only used one method which is &lt;code&gt;sum&lt;/code&gt; and that reflects on webpack bundler.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;someAppsBundle.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; !function(){"use strict";console.log(((o,c)=&amp;gt;o+c))}();
//# sourceMappingURL=app.5712c325.js.map
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now import the &lt;code&gt;sampleJson&lt;/code&gt; and use it as well&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {sum, sampleJson} from 'tsup-library-template';

console.log(sum, sampleJson);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look at the bundle generated by the webpack&lt;br&gt;
 it is larger because it know includes two imported members &lt;code&gt;sum&lt;/code&gt; and &lt;code&gt;sampleJson&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;!function(){"use strict";console.log(((e,f)=&amp;gt;e+f),[{id:"f5e7457f-467d-4e37-9652-f2fb1b51c712",first_name:"John",last_name:"Doe"}])}();
//# sourceMappingURL=app.b0051b82.js.map
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can even solely import a module inside using the below syntax&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {sum} from 'tsup-library-template/lib/Sum';

console.log(sum);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;output will be same with the first example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;!function(){"use strict";console.log(((o,c)=&amp;gt;o+c))}();
//# sourceMappingURL=app.5712c325.js.map
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some of you might think at this stage "isn't it just regular module import/export". Yes, you are absolutely right, the only difference here is we let the bundler to do that inside of an npm package. We're done with the building, time to send it to the npm 🚀&lt;/p&gt;

&lt;h3&gt;
  
  
  Versioning and Releasing
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm version major  // increase major version

npm version minor  // increase minor version

npm version patch // increase patch version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All of the above comments set the new version, updates the package json and commits to git&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to login your npm account, then run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm publish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;on terminal. Check you npm account to see package is ready with the version you specify in&lt;code&gt;package.json&lt;/code&gt;&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;tsup is a bundler based on arguably the fastest bundler: esbuild. You don't have to modify configs, but you can compose the way you want for different outputs. ESM is the preferred module strategy for web and UI libraries. The main difference between a CJS and ES module is that the latter is tree-shakable makes it more efficient and requires less time to download, parse and execute for browsers. We provide the library with type declarations in JS format. Add &lt;code&gt;sideEffects:false&lt;/code&gt; to your package.json for further optimization when other bundlers use the library. Quickly test with &lt;code&gt;npm link&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Further Reading
&lt;/h3&gt;

&lt;p&gt;I've found all of these resources very useful. Shout out to all of them 🙌&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.theodo.com/2021/04/library-tree-shaking/#:~:text=ESM%20is%20a%20requirement%20for,them%20both%20through%20the%20package." rel="noopener noreferrer"&gt;How to make tree-shakable libraries&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.freecodecamp.org/news/anatomy-of-js-module-systems-and-building-libraries-fadcd8dbd0e/" rel="noopener noreferrer"&gt;JS module system&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/lukasbombach/how-to-write-a-tree-shakable-component-library-4ied"&gt;React based tree shakeable library with Rollup&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
   Github Link
&lt;/h3&gt;

&lt;p&gt;In case you want to use this approach as a template &lt;br&gt;
👉 &lt;a href="https://github.com/orabazu/tsup-library-template" rel="noopener noreferrer"&gt;https://github.com/orabazu/tsup-library-template&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Webpack Error
&lt;/h4&gt;

&lt;p&gt;If you see this error when you use the library&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="nx"&gt;ModuleNotFoundError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Module&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;found&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Can&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;t resolve &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;Sum&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; in &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;Users&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;hunor&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;workspace&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;zhunor&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;tsup&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;
Did you mean &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;?
BREAKING CHANGE: The request &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;Sum&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; failed to resolve only because it was resolved as fully specified
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default webpack expects you to provide the file extension when importing a module in .mjs files or any other .js files when their nearest parent package.json file contains a "type" field with a value of "module", otherwise webpack would fail the compiling with a Module not found error. &lt;/p&gt;

&lt;p&gt;In order to skip this you might need to set &lt;code&gt;fullySpecified: false&lt;/code&gt; in webpack configuration similar to below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;m&lt;/span&gt;&lt;span class="se"&gt;?&lt;/span&gt;&lt;span class="sr"&gt;js/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;fullySpecified&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>typescript</category>
      <category>esbuild</category>
      <category>tsup</category>
      <category>treeshaking</category>
    </item>
  </channel>
</rss>
