<?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: Tobias Barth</title>
    <description>The latest articles on Forem by Tobias Barth (@4nduril).</description>
    <link>https://forem.com/4nduril</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%2F17489%2Fed8dd6a2-966a-4ff7-8a6b-689abe945377.jpg</url>
      <title>Forem: Tobias Barth</title>
      <link>https://forem.com/4nduril</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/4nduril"/>
    <language>en</language>
    <item>
      <title>Bundling your library with Webpack</title>
      <dc:creator>Tobias Barth</dc:creator>
      <pubDate>Wed, 13 May 2020 14:01:19 +0000</pubDate>
      <link>https://forem.com/4nduril/bundling-your-library-with-webpack-12ig</link>
      <guid>https://forem.com/4nduril/bundling-your-library-with-webpack-12ig</guid>
      <description>&lt;h2&gt;
  
  
  Preface
&lt;/h2&gt;

&lt;p&gt;This article is part 7 of the series "Publish a modern JavaScript (or TypeScript) library". Check out the motivation and links to other parts &lt;a href="https://dev.to/4nduril/publish-a-modern-javascript-or-typescript-library-3hc3"&gt;in the introduction&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you are not interested in the background and reasoning behind the setup, jump directly to the conclusion.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;In the last post we have established in which cases we may need to bundle our library – instead of just delivering transpiled files /modules. There are a few tools which help us to do so and we will look at the most important ones of them one after another.&lt;/p&gt;

&lt;p&gt;As promised I will make the start with Webpack. Probably most of you have already had contact with Webpack. And probably in the context of website/application bundling. Anyway, a short intro to what it is and does. It is a very versatile tool that was originally build around the concept of code-splitting. Of course it can do (and does) many more things than that but that was the initial, essential idea: make it possible and make it easy to split all of your application code into chunks of code that belong together. So that the browser (the user) does not have to first download, parse and execute &lt;strong&gt;all&lt;/strong&gt; of the app code before anything works. But instead to load only the right amount of code needed at the moment. Webpack is awesome at that.&lt;/p&gt;

&lt;p&gt;The thing is, we don't want to do that. We do not have an application, we have a library. There is either no need for splitting because our code really does only one thing (even if it is a complex thing). Or, we provide rather independent code blocks but then it's the &lt;em&gt;application's&lt;/em&gt; job to put the right things in the right chunks. We can not assume anything about the library-user's needs so they get to decide about splitting.&lt;/p&gt;

&lt;p&gt;Then, what can Webpack do for us? It can take all of our carefully crafted modules, walk through their dependency structure like a tree and put them all together in one module – a bundle. Plus, it adds a tiny bit of runtime code to make sure everything is consumable as we expect it to.&lt;/p&gt;

&lt;p&gt;Webpack, like all bundlers I can think of right now, can work directly with the source code. It's not like you have to, say, transpile it first and then Webpack starts its thing. But for Webpack to be able to understand your code and also to apply any transformation you may want, you need to use so-called &lt;em&gt;loaders&lt;/em&gt;. There is a &lt;code&gt;babel-loader&lt;/code&gt; that we can use for transpiling, TypeScript-loaders, even things like SVG- or CSS-loaders which allow us to import things in our JS/TS files that aren't even related to JavaScript.&lt;/p&gt;

&lt;p&gt;This article does not want and is not able to cover all the possibilities of what you can achieve with Webpack. If you want to learn more, consult the official &lt;a href="https://webpack.js.org/"&gt;documentation&lt;/a&gt;. It's really good these days. (Back in my time … but anyway.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Our goal
&lt;/h2&gt;

&lt;p&gt;We have library code, written in plain JavaScript or TypeScript, no fancy imports. It needs to get transpiled according to our rules and result in one consumable file which people can import in their applications. Also, we want people to be able to just drop it in their HTML in form of a script tag. That is, we want to get a UMD module.&lt;/p&gt;




&lt;h3&gt;
  
  
  What are UMD modules?
&lt;/h3&gt;

&lt;p&gt;(If you already know our if you don't want to know more than I mentioned in the paragraph before, feel free to skip to Starting with Webpack or even to the Conclusion and final config.)&lt;/p&gt;

&lt;p&gt;UMD stands for Universal Module Definition. It combines the module systems Asynchronous Module Definition (AMD), CommonJS and exposure via a global variable for cases where no module system is in place. You can read the &lt;a href="https://github.com/umdjs/umd"&gt;specification and its variants here&lt;/a&gt;. Basically, a UMD module wraps the actual library code with a thin detection layer that tries to find out if it's currently being executed in the context of one of the two mentioned module systems. In case it is, it exposes the library within that system (with &lt;code&gt;define&lt;/code&gt; or &lt;code&gt;module.exports&lt;/code&gt;). If not, it will assign the library's exports to a global variable.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Starting with Webpack
&lt;/h2&gt;

&lt;p&gt;This will be roughly the same as in the &lt;a href="https://webpack.js.org/guides/author-libraries/"&gt;official documentation&lt;/a&gt; of Webpack. But I will try to provide the complete configuration including optimizations andcomments. Also note that I will omit many possibilities Webpack offers or simplify a few things here and there. That's because this is not a deep dive into Webpack but a what-you-should-know-when-bundling-a-library piece.&lt;/p&gt;

&lt;p&gt;First we install Webpack and its command line interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; webpack webpack-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we create a file called &lt;code&gt;webpack.config.js&lt;/code&gt; within the root directory of our library. Let's start with the absolute basics:&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;// webpack.config.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/index.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// or './src/index.ts' if TypeScript&lt;/span&gt;
  &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&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="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;library-starter.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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;entry&lt;/code&gt; we are defining the entry point into our library. Webpack will load this file first and build a tree of dependent modules from that point on. Also, together with a few other options that we will see in a bit, Webpack will expose all exports from that entry module to the outside world – our library's consumers. The value is, as you can see, a string with a path that is relative to the config file location.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;output&lt;/code&gt; key allows us to define what files Webpack should create. The &lt;code&gt;filename&lt;/code&gt; prop makes running Webpack result in a bundle file with this name. The &lt;code&gt;path&lt;/code&gt; is the folder where that output file will be put in. Webpack also defaults to the &lt;code&gt;dist&lt;/code&gt; folder that we defined here but you could change it, e.g. to &lt;code&gt;path.resolve(__dirname, 'output')&lt;/code&gt;or something completely different. But ensure to provide an absolute path – it will not get expanded like the &lt;code&gt;entry&lt;/code&gt; value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem 1: custom syntax like JSX
&lt;/h2&gt;

&lt;p&gt;When we now run &lt;code&gt;npx webpack&lt;/code&gt; on the command line, we expect it to result in a generated &lt;code&gt;dist/library-starter.js&lt;/code&gt; file. Instead it fails with an error. In my &lt;a href="https://github.com/4nduril/library-starter"&gt;library-starter example code&lt;/a&gt; I use React's JSX. As it is configured now, Webpack will refuse to bundle it because it encounters an "unexpected token" when it tries to parse the code. You see that Webpack needs to understand your code. We help with configuring an appropriate "loader".&lt;/p&gt;

&lt;p&gt;If you use Babel for transpiling, install the Babel loader:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; babel-loader
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rest of the Babel setup we need is already installed in our project.&lt;/p&gt;

&lt;p&gt;If you instead are using TSC you'll need &lt;code&gt;ts-loader&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; ts-loader
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I know there is also the &lt;a href="https://github.com/s-panferov/awesome-typescript-loader"&gt;Awesome TypeScript Loader&lt;/a&gt; but the repository has been archived by the author and has not seen any updates for two years (as the time of writing this). Even the author writes in the README: "The world is changing, other solutions are evolving and ATL may work slower for some workloads." Recently it seems to be the case that TS-Loader is faster and is the default choice for most users. Also more information on &lt;a href="https://github.com/TypeStrong/ts-loader#parallelising-builds"&gt;"Parallelising Builds"&lt;/a&gt; is found in the README of &lt;code&gt;ts-loader&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We now add the following to the &lt;code&gt;webpack.config.js&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// webpack.config.js (Babel)&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="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;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;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;.jsx&lt;/span&gt;&lt;span class="se"&gt;?&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// If you are using TypeScript: /\\.tsx?$/&lt;/span&gt;
        &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&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="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;babel-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;cacheDirectory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or:&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;// webpack.config.js (TSC)&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="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;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;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;.tsx&lt;/span&gt;&lt;span class="se"&gt;?&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&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="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ts-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;transpileOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Problem 2: Babels runtime helpers
&lt;/h2&gt;

&lt;p&gt;In case we are using Babel for transpiling, Webpack now runs into the next error. It tries to resolve the helper and polyfill imports that Babel created for us but as &lt;a href="https://dev.to/4nduril/transpile-modern-language-features-with-babel-4fcp"&gt;we only declared them&lt;/a&gt; as a &lt;code&gt;peerDependency&lt;/code&gt; we haven't installed them yet and so Webpack can't put them into the bundle.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bundling helpers?
&lt;/h3&gt;

&lt;p&gt;As you remember, we deliberately did define &lt;code&gt;@babel/runtime-corejs3&lt;/code&gt; as a peer dependency to make sure our delivered library is as small as possible and also to allow the user to have at best only one version of it installed, keeping their application bundle smaller. Now, if we install it by ourselves and bundle it with Webpack, then all the benefit is gone. Yes, that's right. We can of course tell Webpack that certain imports should be treated as "external" and we will in fact do that later on for the "react" dependency that our specific library has. But not for the runtime helpers.&lt;/p&gt;

&lt;p&gt;Because remember why we are bundling: One of the reasons was to make it possible for a user to drop the bundle in a &lt;code&gt;script&lt;/code&gt; tag into their page. To be able to do that with deps declared as external, also &lt;em&gt;those&lt;/em&gt; have to be available as separate UMD package. This is the case for many things like React or Lodash but not for this runtime package. That means we have to bundle it together with our code. We could make a very sophisticated setup with several Webpack configs, one resulting in a bigger bundle for that specific use case and one for usual importing in an application. But &lt;em&gt;we already reached&lt;/em&gt; the second goal: with our non-bundled build.&lt;/p&gt;

&lt;p&gt;If your library uses non-JS/TS imports like CSS or SVGs, then of course you can think about how much it will save the users of your library if you go that extra mile. I am not going to cover that in this article. Maybe at a later point when we have all of our foundations in place.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bundling helpers!
&lt;/h3&gt;

&lt;p&gt;Install &lt;code&gt;@babel/runtime-corejs3&lt;/code&gt; as a development dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; @babel/runtime-corejs3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Problem 3: Externals
&lt;/h2&gt;

&lt;p&gt;The next thing we will cover is dependencies that we really don't want to have in our bundle but instead should be provided by the using environment. The next error Webpack throws is about the &lt;code&gt;'react'&lt;/code&gt; dependency. To solve this we make use of the &lt;code&gt;externals&lt;/code&gt; key:&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;// webpack.config.js&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;externals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;react&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;React&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;commonjs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;commonjs2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;amd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because some libraries expose themselves differently depending on the module system that is being used, we can (and must) declare the name under which the external can be found for each of these systems. &lt;code&gt;root&lt;/code&gt; denotes the name of a global accessible variable. Deeper explanation can be found in the &lt;a href="https://webpack.js.org/configuration/externals/#object"&gt;Webpack docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem 4: File extensions
&lt;/h2&gt;

&lt;p&gt;This is of course only an issue if you are writing TypeScript or if you name files containing JSX &lt;code&gt;*.jsx&lt;/code&gt; instead of &lt;code&gt;*js&lt;/code&gt; (which we don't in the example library). Do you remember when we had to tell the Babel CLI which file extensions it should accept? If not, read again &lt;a href="https://dev.to/4nduril/building-your-library-part-1-5cii"&gt;about building our library&lt;/a&gt;. Now, Webpack has to find all the files we are trying to import in our code. And like Babel by default it looks for files with a &lt;code&gt;.js&lt;/code&gt; extension. If we want Webpack to find other files as well we have to give it a list of valid 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="c1"&gt;// webpack.config.js&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extensions&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="s1"&gt;.tsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.jsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;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="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;If you are not writing TypeScript the list of extensions can be as short as &lt;code&gt;['.jsx', '.js']&lt;/code&gt;. We didn't need to specify the &lt;code&gt;*.jsx&lt;/code&gt; extension for the normal Babel call because Babel recognizes it already (as opposed to &lt;code&gt;*.tsx&lt;/code&gt; for example).&lt;/p&gt;

&lt;h2&gt;
  
  
  Mode
&lt;/h2&gt;

&lt;p&gt;Now when we run &lt;code&gt;npx webpack&lt;/code&gt; our bundle is made without errors and put into &lt;code&gt;/dist&lt;/code&gt;. But there is still a warning from Webpack about the fact that we didn't set the &lt;code&gt;mode&lt;/code&gt; option in our config. The mode can be &lt;code&gt;'development'&lt;/code&gt; or &lt;code&gt;'production'&lt;/code&gt; and will default to the latter. (There is also the value &lt;code&gt;'none'&lt;/code&gt; but we will not cover it here.) It's kind of a shorthand for several settings and activation of plugins. &lt;code&gt;'development'&lt;/code&gt; will keep the output readable (besides other things) while &lt;code&gt;'production'&lt;/code&gt; will compress the code as much as possible.&lt;/p&gt;

&lt;p&gt;Since we mainly bundle for users to be able to use it in script tags, i.e. additionally to providing single module files, we will not bother to differentiate between the two modes. We only use &lt;code&gt;'production'&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// webpack.config.js&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And thus the warning is gone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Library
&lt;/h2&gt;

&lt;p&gt;Everything is fine now. Or, is it?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# node repl

&amp;gt; const lib = require('./dist/library-starter')
&amp;gt; lib
{}
&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We get only an empty module. That is because Webpack by default creates application bundles that should get executed. If we want to get a module with exports than we have to explicitly tell it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// webpack.config.js&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="na"&gt;library&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;libraryStarter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this is still not enough because we now get an executable script that creates a global variable named &lt;code&gt;libraryStarter&lt;/code&gt; which contains our library. Actually, this would be enough to drop it into a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag. We could use it on a web page like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/library-starter.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;script&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;libraryStarter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;usePropsThatChanged&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But come on, we wanted a real UMD module. If we do this, we do it right. So back in our &lt;code&gt;webpack.config.js&lt;/code&gt; we add two more options:&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;// webpack.config.js&lt;/span&gt;

&lt;span class="nx"&gt;output&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;library&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;libraryStarter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;libraryTarget&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;umd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;globalObject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;this&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's run &lt;code&gt;npx webpack&lt;/code&gt; again and try it out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# node repl

&amp;gt; const lib = require('./dist/library-starter.js')
&amp;gt; lib
Object [Module] {
   ExampleComponent: [Getter],
   usePropsThatChanged: [Getter]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally. If you wonder, why we added the &lt;code&gt;globalObject&lt;/code&gt; key: It makes sure that in the case of using the bundle file without a module system like AMD or CommonJS it works in the browser as well as in a Node context. The return value of the entry point will get assigned to the current &lt;code&gt;this&lt;/code&gt; object which is &lt;code&gt;window&lt;/code&gt; in browsers and the global object in Node.&lt;/p&gt;

&lt;p&gt;There are more nuanced ways to set &lt;code&gt;libraryTarget&lt;/code&gt; than explained here. If you are interested please read the &lt;a href="https://webpack.js.org/configuration/output/#outputlibrarytarget"&gt;documentation&lt;/a&gt;. But for our purposes this should set a solid base.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build and expose
&lt;/h2&gt;

&lt;p&gt;We are done with the configuration part. (Unbelievable, right?!) The only thing that's left is changing the &lt;code&gt;package.json&lt;/code&gt; so that the bundle can be imported from outside as an addition to our ES modules and that users can get it automatically from &lt;a href="https://unpkg.com/"&gt;unpkg.com&lt;/a&gt; as well.&lt;/p&gt;

&lt;p&gt;Right now both, the &lt;code&gt;main&lt;/code&gt; and the &lt;code&gt;module&lt;/code&gt; key are pointing to &lt;code&gt;dist/index.js&lt;/code&gt;. While only the latter is correct. As &lt;a href="https://dev.to/4nduril/building-your-library-part-1-5cii"&gt;I mentioned before&lt;/a&gt; &lt;code&gt;main&lt;/code&gt; should point to a ES5-compatible file and not to an ES module. Now we can safely change it to our new bundle file.&lt;/p&gt;

&lt;p&gt;Of course we also have to actually build the bundle. For this we add an npm script named "bundle" to our script section and add it to the "build" script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.json&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="err"&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;"dist/library-starter.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;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist/index.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;"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="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"bundle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webpack"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;our build commands up until now&amp;gt; &amp;amp;&amp;amp; npm run bundle"&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="err"&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;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt; Conclusion
&lt;/h2&gt;

&lt;p&gt;Install webpack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; webpack webpack-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install babel-loader or ts-loader:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; babel-loader &lt;span class="c"&gt;# or ts-loader&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If using Babel, install its runtime helpers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; @babel/runtime-corejs3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a &lt;code&gt;webpack.config.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/index.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// or './src/index.ts' if TypeScript&lt;/span&gt;
  &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;library-starter.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Desired file name. Same as in package.json's "main" field.&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&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="nx"&gt;__dirname&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="na"&gt;library&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;libraryStarter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Desired name for the global variable when using as a drop-in script-tag.&lt;/span&gt;
    &lt;span class="na"&gt;libraryTarget&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;umd&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;globalObject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;this&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;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;.jsx&lt;/span&gt;&lt;span class="se"&gt;?&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// If you are using TypeScript: /\\.tsx?$/&lt;/span&gt;
        &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&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="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="c1"&gt;// If using babel-loader&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;babel-loader&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;cacheDirectory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="c1"&gt;// If _instead_ using ts-loader&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ts-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;transpileOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="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="c1"&gt;// If using TypeScript&lt;/span&gt;
  &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extensions&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="s1"&gt;.tsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.jsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;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="c1"&gt;// If using an external dependency that should not get bundled, e.g. React&lt;/span&gt;
  &lt;span class="na"&gt;externals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;react&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;React&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;commonjs2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;commonjs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;amd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change the &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.json&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="err"&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;"dist/library-starter.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;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist/index.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;"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="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"bundle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webpack"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;our build commands up until now&amp;gt; &amp;amp;&amp;amp; npm run bundle"&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="err"&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;That's all there is to bundling libraries with Webpack.&lt;br&gt;
Next article's topic: Rollup.&lt;/p&gt;




&lt;p&gt;As always many thanks to my friend &lt;a href="https://twitter.com/Tim_Kraut"&gt;Tim Kraut&lt;/a&gt; for proof-reading this article!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webpack</category>
      <category>typescript</category>
      <category>umd</category>
    </item>
    <item>
      <title>How to bundle your library and why</title>
      <dc:creator>Tobias Barth</dc:creator>
      <pubDate>Mon, 18 Nov 2019 21:02:14 +0000</pubDate>
      <link>https://forem.com/4nduril/how-to-bundle-your-library-and-why-1gao</link>
      <guid>https://forem.com/4nduril/how-to-bundle-your-library-and-why-1gao</guid>
      <description>&lt;h2&gt;
  
  
  Preface
&lt;/h2&gt;

&lt;p&gt;This article is part 6 of the series "Publish a modern JavaScript (or TypeScript) library". Check out the motivation and links to other parts &lt;a href="https://dev.to/4nduril/publish-a-modern-javascript-or-typescript-library-3hc3"&gt;in the introduction&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Publishing formats – do you even need a bundle?
&lt;/h2&gt;

&lt;p&gt;At this point in our setup we deliver our library as separate modules. ES Modules to be exact. Let's discuss what we achieve with that and what could be missing.&lt;/p&gt;

&lt;p&gt;Remember, we are publishing a library that is to be used within other applications. Depending on your concrete use case the library will be used in web applications in browsers or in NodeJS applications on servers or locally.&lt;/p&gt;

&lt;h3&gt;
  
  
  Web applications (I)
&lt;/h3&gt;

&lt;p&gt;In the case of web applications we can assume that they will get bundled with any of the current solutions, Webpack for example. These bundlers can understand ES Module syntax and since we deliver our code in several modules, the bundler can optimize what code needs to be included and which code doesn't (tree-shaking). In other words, for this use case we already have everything we need. In fact, bundling our modules together into one blob could defeat our goal to enable end-users to end up with only the code they need. The final application bundlers could maybe no longer differentiate which parts of the library code is being used.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion: No bundle needed.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  NodeJS applications
&lt;/h3&gt;

&lt;p&gt;What about NodeJS? It is standard for Node applications to consist of several independent files; source files and their dependencies (&lt;code&gt;node_modules&lt;/code&gt;). The modules will get imported during runtime when they are needed. But does it work with ES Modules? Sort of.&lt;/p&gt;

&lt;p&gt;NodeJS v12 has &lt;a href="https://nodejs.org/dist/latest-v12.x/docs/api/esm.html"&gt;experimental support for ES Modules&lt;/a&gt;. "Experimental" means we must "expect major changes in the implementation including interoperability support, specifier resolution, and default behavior." But yes, it works and it will work even better and smoother in future versions.&lt;/p&gt;

&lt;p&gt;Since Node has to support CommonJS modules for the time being and since the two module types are not 100% compatible, there are a few things we have to respect if we want to support both ways of usage. First of all, things &lt;strong&gt;will&lt;/strong&gt; change. The NodeJS team even &lt;a href="https://medium.com/@nodejs/announcing-a-new-experimental-modules-1be8d2d6c2ff"&gt;warns&lt;/a&gt; to "publish any ES module packages intended for use by Node.js until [handling of packages that support CJS and ESM] is resolved."&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;That means, if your library is intended &lt;em&gt;only&lt;/em&gt; for Node (so no browser optimization necessary), you don't want to rely on your library's users reading your installation notes (they will have to know &lt;em&gt;what&lt;/em&gt; to import/require) or you are not interested in investing in features that are only &lt;em&gt;almost&lt;/em&gt; there: Please just don't publish ES Modules. Change the &lt;a href="https://dev.to/4nduril/transpile-modern-language-features-with-babel-4fcp"&gt;configuration&lt;/a&gt; of Babel's &lt;code&gt;env&lt;/code&gt; preset to &lt;code&gt;{ modules: 'commonjs' }&lt;/code&gt; and ship only CommonJS modules.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But with a bit of work we can make sure everthing will be fine. &lt;del&gt;For now the ESM support is behind a flag (&lt;code&gt;--experimental-modules&lt;/code&gt;). When the implementation changes, I will hopefully update this post as soon as possible.&lt;/del&gt; &lt;strong&gt;As of Nov. 21 2019 the feature is unflagged: &lt;a href="https://nodejs.org/en/blog/release/v13.2.0/"&gt;Changelog&lt;/a&gt;. So your users do not have to start their app with the flag with Node version 13.2.0 upwards.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;NodeJS uses a combination of a declaration of module &lt;code&gt;type&lt;/code&gt; inside of &lt;code&gt;package.json&lt;/code&gt; and filename extensions. I won't lay out every detail and combination of these variants but rather show the (in my opinion) most future-proof and easiest approach.&lt;/p&gt;

&lt;p&gt;Right now we have created &lt;code&gt;.js&lt;/code&gt; files that are in ES Module syntax. Therefore, we will add the &lt;code&gt;type&lt;/code&gt; key to our &lt;code&gt;package.json&lt;/code&gt; and set it to &lt;code&gt;"module"&lt;/code&gt;. This is the signal to NodeJS that it should parse every &lt;code&gt;.js&lt;/code&gt; file in this package scope as ES Module:&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="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&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="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that you oftentimes will come across the advice to use &lt;code&gt;*.mjs&lt;/code&gt; file extensions. Don't do that. &lt;code&gt;*.js&lt;/code&gt; is &lt;em&gt;the&lt;/em&gt; extension for JavaScript files and will probably always be. Let's use the default naming for the current standards like ESM syntax. If you have for whatever reason files inside your package that must use CommonJS syntax, give &lt;em&gt;them&lt;/em&gt; another extension: &lt;code&gt;*.cjs&lt;/code&gt;. Node will know what to do with it.&lt;/p&gt;

&lt;p&gt;There are a few caveats:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using third party dependencies

&lt;ol&gt;
&lt;li&gt;If the external module is (only) in CommonJS syntax, you can import it only as default import. Node says that will hopefully change in the future but for now you can't have named imports on a CommonJS module.&lt;/li&gt;
&lt;li&gt;If the external module is published in ESM syntax, check if it follows Node's rules: If there is ESM syntax in a &lt;code&gt;*.js&lt;/code&gt; file &lt;strong&gt;and&lt;/strong&gt; there is no &lt;code&gt;"type": "module"&lt;/code&gt; in the &lt;code&gt;package.json&lt;/code&gt;, the package is broken and you can not use it with ES Modules. (Example: &lt;a href="https://github.com/reactjs/react-lifecycles-compat"&gt;react-lifecycles-compat&lt;/a&gt;). Webpack would make it work but not Node. An example for a properly configured package is &lt;a href="https://github.com/graphql/graphql-js"&gt;graphql-js&lt;/a&gt;. It uses the &lt;code&gt;*.mjs&lt;/code&gt; extension for ESM files.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;Imports need file extensions. You can import from a package name (&lt;code&gt;import _ from 'lodash'&lt;/code&gt;) like before but you can not import from a file (or a folder containing an &lt;code&gt;index.(m)js&lt;/code&gt;) without the &lt;em&gt;complete&lt;/em&gt; path: &lt;code&gt;import x from './otherfile.js'&lt;/code&gt; will work but &lt;code&gt;import x from './otherfile'&lt;/code&gt; won't. &lt;code&gt;import y from './that-folder/index.js'&lt;/code&gt; will work but &lt;code&gt;import y from './that-folder'&lt;/code&gt; won't.&lt;/li&gt;
&lt;li&gt;There is a way around the file extension rule but you have to force your users do it: They must run their program with a second flag: &lt;code&gt;--es-module-specifier-resolution=node&lt;/code&gt;. That will restore the resolution pattern Node users know from CommonJS. &lt;strong&gt;Unfortunately that is also necessary if you have Babel runtime helpers included by Babel.&lt;/strong&gt; Babel will inject default imports which is good, but it omits the file extensions. So if your library depends on Babel transforms, you have to tell your users that they will have to use that flag. &lt;del&gt;(Not too bad because they already know how to pass ESM related flags when they want to opt into ESM.)&lt;/del&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For all other users that are not so into experimental features we also publish in CommonJS. To support CommonJS we do something, let's say, non-canonical in the NodeJS world: we deliver a single-file bundle. Normally, people don't bundle for Node because it's not necessary. But because we need a second compile one way or the other, it's the easiest path. Also note that other than in the web we don't have to care to much for size as everything executes locally and is installed beforehand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion: Bundle needed if we want to ship both, CommonJS and ESM.&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Web applications (II)
&lt;/h4&gt;

&lt;p&gt;There is another use case regarding web applications. Sometimes people want to be able to include a library by dropping a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag into their HTML and refer to the library via a global variable. (There are also other scenarios that may need such a kind of package.) To make that possible without additional setup by the user, all of your library's code must be bundled together in one file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion: Bundle needed to make usage as easy as possible.&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Special "imports"
&lt;/h4&gt;

&lt;p&gt;There is a class of use cases that came up mainly with the rise of Webpack and its rich "loader" landscape. And that is: importing every file type that you can imagine &lt;em&gt;into your JavaScript&lt;/em&gt;. It probably started with requiring accompanying CSS files into JS components and went over images and what not. &lt;strong&gt;If you do something like that in your library, you have to use a bundler.&lt;/strong&gt; Because otherwise the consumers of your library would have to use a bundler themselves that is at least configured exactly in a way that handles all strange (read: not JS-) imports in your library. Nobody wants to do that.&lt;/p&gt;

&lt;p&gt;If you deliver stylings alongside with your JS code, you should do it with a separate CSS file that comes with the rest of the code. And if you write a whole component library like Bootstrap then you probably don't want to ask your users for importing hundreds of CSS files but one compiled file. And the same goes for other non-JS file types.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion: Bundle needed&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Ok, ok, now tell me how to do it!
&lt;/h3&gt;

&lt;p&gt;Alright. Now you can decide if you really need to bundle your library. Also, you have an idea of what the bundle should "look" like from outside: For classic usage with Node.js it should be a big CommonJS module, consumable with &lt;code&gt;require()&lt;/code&gt;. For further bundling in web applications it may be better to have a big ES module that is tree-shakable.&lt;/p&gt;

&lt;p&gt;And here is the cliffhanger: Each of the common bundling tools will get their own article in this series. This post is already long enough.&lt;/p&gt;

&lt;p&gt;Next up: Use Webpack for bundling your library.&lt;/p&gt;




&lt;p&gt;As always many thanks to my friend &lt;a href="https://twitter.com/Tim_Kraut"&gt;Tim Kraut&lt;/a&gt; for proof-reading this article!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webpack</category>
      <category>rollup</category>
      <category>parcel</category>
    </item>
    <item>
      <title>Check types and emit type declarations</title>
      <dc:creator>Tobias Barth</dc:creator>
      <pubDate>Thu, 31 Oct 2019 19:07:23 +0000</pubDate>
      <link>https://forem.com/4nduril/check-types-and-emit-type-declarations-1i29</link>
      <guid>https://forem.com/4nduril/check-types-and-emit-type-declarations-1i29</guid>
      <description>&lt;h2&gt;
  
  
  Preface
&lt;/h2&gt;

&lt;p&gt;This article is part 5 of the series "Publish a modern JavaScript (or TypeScript) library". Check out the motivation and links to other parts &lt;a href="https://dev.to/4nduril/publish-a-modern-javascript-or-typescript-library-3hc3"&gt;in the introduction&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting the types out of TypeScript
&lt;/h2&gt;

&lt;p&gt;Ok, this is a quick one. When we build our library, we want two things from TypeScript: First we want to know that there are no type errors in our code (or types missing, e.g. from a dependency). Second, since we are publishing a library for other fellow coders to use, not an application, we want to export type declarations. We will start with type-checking.&lt;/p&gt;

&lt;h2&gt;
  
  
  Type-checking
&lt;/h2&gt;

&lt;p&gt;Type-checking can be seen as a form of testing. Take the code and check if certain assertions hold. Therefore, we want to be able to execute it as a separate thing that we can add to our build chain or run it in a pre-commit hook for example. You don't necessarily want to generate type definition files every time you (or your CI tool) run your tests.&lt;/p&gt;

&lt;p&gt;If you want to follow along with my &lt;a href="https://github.com/4nduril/library-starter/tree/typescript"&gt;little example library&lt;/a&gt;, be sure to check out one of the &lt;code&gt;typescript&lt;/code&gt; branches.&lt;/p&gt;

&lt;p&gt;The TypeScript Compiler always checks the types of a project it runs on. And it will fail and report errors if there are any. So in principle we could just run &lt;code&gt;tsc&lt;/code&gt; to get what we want. Now, to separate creating output files from the pure checking process, we must give &lt;code&gt;tsc&lt;/code&gt; a handy option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tsc --noEmit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Regardless if we use Babel or TSC for transpiling, for checking types there is just this one way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create type declaration files
&lt;/h2&gt;

&lt;p&gt;This is something pretty library-specific. When you build an application in TypeScript, you only care about correct types and an executable output. But when you provide a library, your users (i.e. other programmers) can directly benefit from the fact that you wrote it in TypeScript. When you provide type declaration files (&lt;code&gt;*.d.ts&lt;/code&gt;) the users will get better auto-completion, type-hints and so on when they use your lib.&lt;/p&gt;

&lt;p&gt;Maybe you have heard about &lt;a href="https://www.definitelytyped.org/"&gt;DefinitelyTyped&lt;/a&gt;. Users can get types from there for libraries that don't ship with their own types. So, in our case we won't need to do anything with or for DefinitelyTyped. Consumers of our library will have everything they need when we deliver types directly with our code.&lt;/p&gt;

&lt;p&gt;Again, because these things are core functionality of TypeScript, we use &lt;code&gt;tsc&lt;/code&gt;. But this time the calls are slightly different depending on how we transpile – with Babel or TSC.&lt;/p&gt;

&lt;h3&gt;
  
  
  With Babel
&lt;/h3&gt;

&lt;p&gt;As you probably remember, to create our output files with Babel, we call the Babel command line interface, &lt;code&gt;babel&lt;/code&gt;. To also get declaration files we add a call to &lt;code&gt;tsc&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;tsc --declaration --emitDeclarationOnly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--declaration&lt;/code&gt; flag ensures that TSC generates the type declaration files and since we defined the &lt;code&gt;outputDir&lt;/code&gt; in &lt;code&gt;tsconfig.json&lt;/code&gt;, they land in the correct folder &lt;code&gt;dist/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The second flag, &lt;code&gt;--emitDeclarationOnly&lt;/code&gt;, prevents TSC from outputting transpiled JavaScript files. We use Babel for that.&lt;/p&gt;

&lt;p&gt;You may ask yourself why we effectively transpile all of our code twice, once with Babel and once with TSC. It looks like a waste of time if TSC can do both. But &lt;a href="https://dev.to/4nduril/compiling-modern-language-features-with-the-typescript-compiler-36m3"&gt;I discussed before&lt;/a&gt; the advantages of Babel. And having a very fast transpile step separate from a slower declaration generation step can translate to a much better developer experience. The output of declarations can occur only once shortly before publishing – transpiling is something that you do all the time.&lt;/p&gt;

&lt;h3&gt;
  
  
  With TSC
&lt;/h3&gt;

&lt;p&gt;When we use TSC to generate the published library code, we can use it &lt;em&gt;in the same step&lt;/em&gt; to spit out the declarations. Instead of just &lt;code&gt;tsc&lt;/code&gt;, we call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tsc --declaration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alias All The Things
&lt;/h2&gt;

&lt;p&gt;To make it easier to use and less confusing to find out what our package can do, we will create NPM scripts for all steps that we define. Then we can glue them together so that for example &lt;code&gt;npm run build&lt;/code&gt; will always do everything we want from our build.&lt;/p&gt;

&lt;p&gt;In the case of using Babel, in our &lt;code&gt;package.json&lt;/code&gt; we make sure that &lt;code&gt;"scripts"&lt;/code&gt; contains at least:&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="p"&gt;...&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&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;check-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;tsc --noEmit&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;emitDeclarations&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;tsc --declaration --emitDeclarationOnly&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;transpile&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;babel -d dist/ --extensions .ts,.tsx src/&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;build&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;npm run emitDeclarations &amp;amp;&amp;amp; npm run transpile&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if you are just using TSC, it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="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;scripts&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;check-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;tsc --noEmit&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;build&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;tsc --declaration&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that we don't add &lt;code&gt;check-types&lt;/code&gt; to &lt;code&gt;build&lt;/code&gt;. First of all building and testing are two very different things. We don't want to mix them explicitly. And second, in both cases we &lt;em&gt;do&lt;/em&gt; check the types on build. Because as I said: that happens every time you call &lt;code&gt;tsc&lt;/code&gt;. So even if you are slightly pedantic about type-checking on build, you don't have to call &lt;code&gt;check-types&lt;/code&gt; within the build script.&lt;/p&gt;

&lt;p&gt;One great advantage of aliasing every action to a NPM script is that everyone working on your library (including you) can just run &lt;code&gt;npm run&lt;/code&gt; and will get a nice overview of what scripts are available and what they do.&lt;/p&gt;

&lt;p&gt;That's it for using types.&lt;/p&gt;

&lt;p&gt;Next up: All about bundling.&lt;/p&gt;




&lt;p&gt;As always many thanks to my friend &lt;a href="https://twitter.com/Tim_Kraut"&gt;Tim Kraut&lt;/a&gt; for proof-reading this article!&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>library</category>
      <category>howto</category>
    </item>
    <item>
      <title>Building your library: Part 1</title>
      <dc:creator>Tobias Barth</dc:creator>
      <pubDate>Wed, 24 Jul 2019 09:11:58 +0000</pubDate>
      <link>https://forem.com/4nduril/building-your-library-part-1-5cii</link>
      <guid>https://forem.com/4nduril/building-your-library-part-1-5cii</guid>
      <description>&lt;h2&gt;
  
  
  Preface
&lt;/h2&gt;

&lt;p&gt;This article is part 4 of the series "Publish a modern JavaScript (or TypeScript) library". Check out the motivation and links to other parts &lt;a href="https://dev.to/4nduril/publish-a-modern-javascript-or-typescript-library-3hc3"&gt;in the introduction&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; I have promised in &lt;a href="https://dev.to/4nduril/compiling-modern-language-features-with-the-typescript-compiler-36m3"&gt;part 3 of this series&lt;/a&gt; that the next post would be about exporting types. But bear with me. First we will use what we have. Types are coming up next.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our first build
&lt;/h2&gt;

&lt;p&gt;Up until now we have discussed how to set up Babel or the TypeScript Compiler, respectively, for transpiling our thoughtfully crafted library code. But we didn't actually use them. After all, the goal for our work here should be a fully functioning build chain that does everything we need for publishing our library.&lt;/p&gt;

&lt;p&gt;So let's start this now. As you can tell from the title of this article, we will refine our build with every item in our tool belt that we installed and configured. While the "normal" posts each focus on one tool for one purpose, these "build" articles will gather all configurations of our various tool combinations that we have at our disposal.&lt;/p&gt;

&lt;p&gt;We will leverage NPM scripts to kick off everything we do. For JavaScript/TypeScript projects it's the natural thing to do: You &lt;code&gt;npm install&lt;/code&gt; and &lt;code&gt;npm test&lt;/code&gt; and &lt;code&gt;npm start&lt;/code&gt; all the time, so we will &lt;code&gt;npm run build&lt;/code&gt; also.&lt;/p&gt;

&lt;p&gt;For today we will be done with it relatively quickly. We only have the choice between Babel and TSC and transpiling is the only thing that we do when we build.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build JavaScript with Babel
&lt;/h2&gt;

&lt;p&gt;You define a &lt;code&gt;build&lt;/code&gt; script as you may now in the &lt;code&gt;package.json&lt;/code&gt; file inside of the root of your project. The relevant keys are &lt;code&gt;scripts&lt;/code&gt; and &lt;code&gt;module&lt;/code&gt; and we change it so that they contain at least the following:&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="c1"&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;dist/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;scripts&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;build&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;babel -d dist/ src/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using &lt;code&gt;module&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The standard key to point to the entry file of a package is &lt;code&gt;main&lt;/code&gt;. But we are using &lt;code&gt;module&lt;/code&gt; here. This goes back to a &lt;a href="https://github.com/rollup/rollup/wiki/pkg.module"&gt;proposal by the bundler Rollup&lt;/a&gt;. The idea here is that the entry point under a &lt;code&gt;main&lt;/code&gt; key is valid ES5 only. Especially regarding module syntax. The code there should use things like CommonJS, AMD or UMD but not ESModules. While bundlers like Webpack and Rollup can deal with legacy modules they can't tree-shake them. (Read &lt;a href="https://dev.to/4nduril/transpile-modern-language-features-with-babel-4fcp"&gt;the article on Babel&lt;/a&gt; again if you forgot why that is.)&lt;/p&gt;

&lt;p&gt;Therefore the proposal states that you can provide an entry point under &lt;code&gt;module&lt;/code&gt; to indicate that the code there is using modern ESModules. The bundlers will always look first if there is a &lt;code&gt;module&lt;/code&gt; key in your package.json and in that case just use it. Only when they don't find it they will fall back to &lt;code&gt;main&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Call Babel
&lt;/h3&gt;

&lt;p&gt;The "script" under the name of &lt;code&gt;build&lt;/code&gt; is just a single call to the Babel command line interface (CLI) with one option &lt;code&gt;-d dist&lt;/code&gt; which tells Babel where to put the transpiled files (&lt;code&gt;-d&lt;/code&gt; : &lt;code&gt;--out-dir&lt;/code&gt;). Finally we tell it where to find the source files. When we give it a directory like &lt;code&gt;src&lt;/code&gt; Babel will transpile every file it understands. That is, every file with an extension from the following list: &lt;code&gt;.es6,.js,.es,.jsx,.mjs&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build TypeScript with Babel
&lt;/h2&gt;

&lt;p&gt;This is almost the same as above. The only difference is the options we pass to the Babel CLI. The relevant parts in &lt;code&gt;package.json&lt;/code&gt; look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&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;dist/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;scripts&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;build&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;babel -d dist/ --extensions .ts,.tsx src/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As I mentioned above, Babel wouldn't know that it should transpile the &lt;code&gt;.ts&lt;/code&gt; and &lt;code&gt;.tsx&lt;/code&gt; files in &lt;code&gt;src&lt;/code&gt;. We have to explicitly tell it to with the &lt;code&gt;--extensions&lt;/code&gt; option.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build TypeScript with TSC
&lt;/h2&gt;

&lt;p&gt;For using the TypeScript Compiler we configure our build in the &lt;code&gt;package.json&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&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;dist/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;scripts&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;build&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;tsc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We don't have to tell TSC where to find and where to put files because it's all in the tsconfig.json. The only thing our build script has to do is calling &lt;code&gt;tsc&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ready to run
&lt;/h2&gt;

&lt;p&gt;And that is it. All you have to do now to get production-ready code is typing&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;And you have your transpiled library code inside of the &lt;code&gt;dist&lt;/code&gt; directory. It may not seem to be much but I tell you, if you were to &lt;code&gt;npm publish&lt;/code&gt; that package or install it in &lt;a href="https://docs.npmjs.com/cli/install.html"&gt;one of the other ways aside from the registry&lt;/a&gt; it could be used in an application. And it would not be that bad. It may have no exported types, no tests, no contribution helpers, no semantic versioning and no build automation, &lt;strong&gt;BUT&lt;/strong&gt; it ships modern code that is tree-shakable – which is more than many others have.&lt;/p&gt;

&lt;p&gt;Be sure to check out the &lt;a href="https://github.com/4nduril/library-starter"&gt;example code repository&lt;/a&gt; that I set up for this series. There are currently three branches: &lt;code&gt;master&lt;/code&gt;, &lt;code&gt;typescript&lt;/code&gt; and &lt;code&gt;typescript-tsc&lt;/code&gt;. Master reflects my personal choice of tools for JS projects, &lt;code&gt;typescript&lt;/code&gt; is my choice in TS projects and the third one is an alternative to the second. The README has a table with branches and their features.&lt;/p&gt;

&lt;p&gt;Next up: Type-Checking and providing type declarations (and this time for real ;) )&lt;/p&gt;




&lt;p&gt;As always many thanks to my friend &lt;a href="https://twitter.com/Tim_Kraut"&gt;Tim Kraut&lt;/a&gt; for proof-reading this article!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>library</category>
      <category>howto</category>
    </item>
    <item>
      <title>Compiling modern language features with the TypeScript compiler</title>
      <dc:creator>Tobias Barth</dc:creator>
      <pubDate>Thu, 18 Jul 2019 12:26:33 +0000</pubDate>
      <link>https://forem.com/4nduril/compiling-modern-language-features-with-the-typescript-compiler-36m3</link>
      <guid>https://forem.com/4nduril/compiling-modern-language-features-with-the-typescript-compiler-36m3</guid>
      <description>&lt;h2&gt;
  
  
  Preface
&lt;/h2&gt;

&lt;p&gt;This article is part 3 of the series "Publish a modern JavaScript (or TypeScript) library". Check out the motivation and links to other parts &lt;a href="https://dev.to/4nduril/publish-a-modern-javascript-or-typescript-library-3hc3"&gt;in the introduction&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use the TypeScript compiler &lt;code&gt;tsc&lt;/code&gt; to transpile your code
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;If you are not interested in the background and reasoning behind the setup, jump directly to the conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the last article we set up Babel to transpile modern JavaScript or even TypeScript to a form which is understood by our target browsers. But we can also instead use the TypeScript compiler &lt;code&gt;tsc&lt;/code&gt; to do that. For illustrating purposes I have rewritten my small &lt;a href="https://github.com/4nduril/library-starter/tree/rewrite-in-typescript"&gt;example library&lt;/a&gt; in TypeScript. Be sure to look at one of the &lt;code&gt;typescript-&lt;/code&gt; prefixed branches. The &lt;code&gt;master&lt;/code&gt; is still written in JavaScript.&lt;/p&gt;

&lt;p&gt;I will assume that you already know how to setup a TypeScript project. How else would you have been able to write your library in TS? Rather, I will focus only on the best configuration possible for transpiling for the purposes of delivering a library.&lt;/p&gt;

&lt;p&gt;You already know, the configuration is done via a &lt;code&gt;tsconfig.json&lt;/code&gt; in the root of your project. It should contain the following options that I will discuss further 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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;include&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;./src/**/*&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;compilerOptions&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;outDir&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;./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;target&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;es2017&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;esnext&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;moduleResolution&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&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;importHelpers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;include&lt;/code&gt; and &lt;code&gt;outDir&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;These options tell &lt;code&gt;tsc&lt;/code&gt; where to find the files to compile and where to put the result. When we discuss how to emit type declaration files along with your code, &lt;code&gt;outDir&lt;/code&gt; will be used also for their destination. &lt;/p&gt;

&lt;p&gt;Note that these options allow us to just run &lt;code&gt;tsc&lt;/code&gt; on the command line without anything else and it will find our files and put the output where it belongs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Target environment
&lt;/h2&gt;

&lt;p&gt;Remember when we discussed &lt;code&gt;browserslist&lt;/code&gt; in the "Babel" article? (If not, &lt;a href="https://dev.to/4nduril/transpile-modern-language-features-with-babel-4fcp"&gt;check it out here&lt;/a&gt;.) We used an array of queries to tell Babel exactly which environments our code should be able to run in. Not so with &lt;code&gt;tsc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you are interested, read this intriguing &lt;a href="https://github.com/Microsoft/TypeScript/issues/19183"&gt;issue&lt;/a&gt; in the TypeScript GitHub repository. Maybe some day in the future we will have such a feature in &lt;code&gt;tsc&lt;/code&gt; but for now, we have to use "JavaScript versions" as targets.&lt;/p&gt;

&lt;p&gt;As you may know, since 2015 every year the TC39 committee ratifies a new version of ECMAScript consisting of all the new features that have reached the "Finished" stage before that ratification. (See &lt;a href="https://tc39.es/process-document/"&gt;The TC39 process&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;Now &lt;code&gt;tsc&lt;/code&gt; allows us (only) to specify which version of ECMAScript we are targeting. To reach a more or less similar result as with Babel and my opinionated &lt;code&gt;browserslist&lt;/code&gt; config, I decided to go with &lt;code&gt;es2017&lt;/code&gt;. I have used the &lt;a href="https://kangax.github.io/compat-table/es2016plus/"&gt;ECMAScript compatibility table&lt;/a&gt; and checked until which version it would be "safe" to assume that the last 2 versions of Edge/Chrome/Firefox/Safari/iOS can handle it. Your mileage may vary here! You have basically at least three options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go with my suggestion and use &lt;code&gt;es2017&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Make your own decision based on the compatibility table.&lt;/li&gt;
&lt;li&gt;Go for the safest option and use &lt;code&gt;es5&lt;/code&gt;. This will produce code that can also run in Internet Explorer 11 but also will it be much bigger in size — for all browsers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just like with my &lt;code&gt;browserslist&lt;/code&gt; config, I will discuss in a future article how to provide more than one bundle: one for modern environments and one for older ones.&lt;/p&gt;

&lt;p&gt;Another thing to note here: The &lt;code&gt;target&lt;/code&gt; does not directly set which module syntax should be used in the output! You may think it does, because if you don't explicitly set &lt;code&gt;module&lt;/code&gt; (see next section), &lt;code&gt;tsc&lt;/code&gt; will choose it dependent of your &lt;code&gt;target&lt;/code&gt; setting. If your &lt;code&gt;target&lt;/code&gt; is &lt;code&gt;es3&lt;/code&gt; or &lt;code&gt;es5&lt;/code&gt;, &lt;code&gt;module&lt;/code&gt; will be set implicitly to &lt;code&gt;CommonJS&lt;/code&gt;. Otherwise it will be set to &lt;code&gt;es6&lt;/code&gt;. To make sure you don't get surprised by what &lt;code&gt;tsc&lt;/code&gt; chooses for you, you should always set &lt;code&gt;module&lt;/code&gt; explicitly as described in the following section.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;module&lt;/code&gt; and &lt;code&gt;moduleResolution&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Setting &lt;code&gt;module&lt;/code&gt; to &lt;code&gt;"esnext"&lt;/code&gt; is roughly the same as the &lt;code&gt;modules: false&lt;/code&gt; option of the &lt;code&gt;env&lt;/code&gt; preset in our &lt;code&gt;babel.config.js&lt;/code&gt;: We make sure that the module syntax of our code stays as ESModules to enable treeshaking.&lt;/p&gt;

&lt;p&gt;If we set &lt;code&gt;module: "esnext"&lt;/code&gt;, we have to also set &lt;code&gt;moduleResolution&lt;/code&gt; to &lt;code&gt;"node"&lt;/code&gt;. The TypeScript compiler has two modes for finding non-relative modules (i.e. &lt;code&gt;import {x} from 'moduleA'&lt;/code&gt; as opposed to &lt;code&gt;import {y} from './moduleB'&lt;/code&gt;): These modes are called &lt;code&gt;node&lt;/code&gt; and &lt;code&gt;classic&lt;/code&gt;. The former works similar to the resolution mode of NodeJS (hence the name). The latter does not know about &lt;code&gt;node_modules&lt;/code&gt; which is strange and almost never what you want. But &lt;code&gt;tsc&lt;/code&gt; enables the &lt;code&gt;classic&lt;/code&gt; mode when &lt;code&gt;module&lt;/code&gt; is set to &lt;code&gt;"esnext"&lt;/code&gt; so you have to explicitly tell it to behave.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;target&lt;/code&gt; section above I mentioned that &lt;code&gt;tsc&lt;/code&gt; will set &lt;code&gt;module&lt;/code&gt; implicitly to &lt;code&gt;es6&lt;/code&gt; if &lt;code&gt;target&lt;/code&gt; is something other than &lt;code&gt;es3&lt;/code&gt; or &lt;code&gt;es5&lt;/code&gt;. There is a subtle difference between &lt;code&gt;es6&lt;/code&gt; and &lt;code&gt;esnext&lt;/code&gt;. According to the answers in &lt;a href="https://github.com/Microsoft/TypeScript/issues/24082"&gt;this GitHub issue&lt;/a&gt; &lt;code&gt;esnext&lt;/code&gt; is meant for all the features that are "on the standard track but not in an official ES spec" (yet). That includes features like dynamic import syntax (&lt;code&gt;import()&lt;/code&gt;) which is definitely something you should be able to use because it enables code splitting with Webpack. (Maybe a bit more important for applications than for libraries, but just that you know.)&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;importHelpers&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;You can compare &lt;code&gt;importHelpers&lt;/code&gt; to Babel's &lt;code&gt;transform-runtime&lt;/code&gt; plugin: Instead of inlining the same helper functions over and over again and making your library bigger and bigger, &lt;code&gt;tsc&lt;/code&gt; now injects imports to &lt;code&gt;tslib&lt;/code&gt; which contains all these helpers just like &lt;code&gt;@babel/runtime&lt;/code&gt;. But this time we will install the production dependency and not leave it to our users:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i tslib&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The reason for that is that &lt;code&gt;tsc&lt;/code&gt; will not compile without it. &lt;code&gt;importHelpers&lt;/code&gt; creates imports in our code and if &lt;code&gt;tsc&lt;/code&gt; does not find the module that gets imported it aborts with an error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should you use &lt;code&gt;tsc&lt;/code&gt; or Babel for transpiling?
&lt;/h2&gt;

&lt;p&gt;This is a bit opinion-based. But I think that you are better off with Babel then with &lt;code&gt;tsc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;TypeScript is great and can have many benefits (even if I &lt;strong&gt;personally&lt;/strong&gt; think JavaScript as a language is more powerful without it and the hassle you get with TypeScript outweighs its benefits). And if you want, you should use it! But let Babel produce the final JavaScript files that you are going to deliver. Babel allows for a better configuration and is highly optimized for exactly this purpose. TypeScript's aim is to provide type-safety so you should use it (separately) for that. And there is another issue: Polyfills.&lt;/p&gt;

&lt;p&gt;With a good Babel setup you get everything you need for running your code in the target environments. Not with &lt;code&gt;tsc&lt;/code&gt;! It's now your task to provide all the polyfills that your code needs. And first, to figure out which these are. Even if you don't agree with my opinion about the different use-cases of Babel and TypeScript, the polyfill issue alone should be enough to follow me on this.&lt;/p&gt;

&lt;p&gt;There is a wonderful blog post about using Babel instead of &lt;code&gt;tsc&lt;/code&gt; for transpiling: &lt;a href="https://iamturns.com/typescript-babel/"&gt;TypeScript With Babel: A Beautiful Marriage&lt;/a&gt;. And it lists also the caveats of using Babel for TS: There are four small things that are possible in TypeScript but are not understood correctly by Babel: Namespaces (Don't use them. They are outdated.), type casting with angle brackets (Use &lt;code&gt;as&lt;/code&gt; syntax instead.), &lt;code&gt;const enum&lt;/code&gt; (Use normal enums by omitting &lt;code&gt;const&lt;/code&gt;.) and legacy style import/export syntax (It's &lt;strong&gt;legacy&lt;/strong&gt; — let it go). I think the only important constraint here is the &lt;code&gt;const enum&lt;/code&gt; because it leads to a little bit more code in the output if you use standard enums. But unless you introduce enums with hundreds and hundreds of members, that problem should be negligible.&lt;/p&gt;

&lt;p&gt;Also, it's way faster to just discard all type annotations than checking the types first. This enables for example a faster compile cycle in development-/watch-mode. The example project that I use for this series is maybe not doing enough to be seen as a good compile time example. But also in another library project of mine which consists of ~25 source files and several third-party dependencies, Babel is five times faster than &lt;code&gt;tsc&lt;/code&gt;. That is annoying enough when you are coding and have to wait after every save to see the results.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Conclusion and final notes for the &lt;code&gt;tsc&lt;/code&gt; setup
&lt;/h2&gt;

&lt;p&gt;(If you really want to use &lt;code&gt;tsc&lt;/code&gt; for this task (see the last paragraphs above): )&lt;/p&gt;

&lt;p&gt;Install &lt;code&gt;tslib&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i tslib&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Make sure your &lt;code&gt;tsconfig.json&lt;/code&gt; contains at least the following options:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;compilerOptions&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;outDir&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;./dist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// where should tsc put the transpiled files&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;target&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;es2017&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// set of features that we assume our targets can handle themselves&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;esnext&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// emit ESModules to allow treeshaking&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;moduleResolution&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&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// necessary with 'module: esnext'&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;importHelpers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;// use tslib for helper deduplication&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;include&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;./src/**/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// which files to compile&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are sure you want or need to support older browsers like Android/Samsung 4.4 or Internet Explorer 11 with only one configuration, replace the &lt;code&gt;es2017&lt;/code&gt; target with &lt;code&gt;es5&lt;/code&gt;. In a future article I will discuss how to create and publish more than one package: One as small as possible for more modern targets and one to support older engines with more helper code and therefore bigger size.&lt;/p&gt;

&lt;p&gt;And remember: In this article I talked only about using &lt;code&gt;tsc&lt;/code&gt; as transpiler. We will of course use it for type-checking, but this is another chapter.&lt;/p&gt;

&lt;p&gt;Next up: Type-Checking and providing type declarations&lt;/p&gt;




&lt;p&gt;As always many thanks to my friend &lt;a href="https://twitter.com/Tim_Kraut"&gt;Tim Kraut&lt;/a&gt; for proof-reading this article!&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>library</category>
      <category>howto</category>
    </item>
    <item>
      <title>Transpile modern language features with Babel</title>
      <dc:creator>Tobias Barth</dc:creator>
      <pubDate>Sun, 07 Jul 2019 11:47:46 +0000</pubDate>
      <link>https://forem.com/4nduril/transpile-modern-language-features-with-babel-4fcp</link>
      <guid>https://forem.com/4nduril/transpile-modern-language-features-with-babel-4fcp</guid>
      <description>&lt;h2&gt;
  
  
  Preface
&lt;/h2&gt;

&lt;p&gt;This article is part 2 of the series "Publish a modern JavaScript (or TypeScript) library". Check out the motivation and links to other parts &lt;a href="https://dev.to/4nduril/publish-a-modern-javascript-or-typescript-library-3hc3"&gt;in the introduction&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Babel and how should you use it in a library?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;If you are not interested in the background and reasoning behind the setup, jump directly to the conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Babel can transpile JavaScript as well as TypeScript. I would argue that it's even better to use Babel instead of the TypeScript compiler for compiling the code (down) to compatible JavaScript because it is faster. What Babel does when it compiles TypeScript is it just discards everything that isn't JavaScript. &lt;strong&gt;Babel does no type checking.&lt;/strong&gt; Which we don't need at this point.&lt;/p&gt;

&lt;p&gt;To use Babel you have to install it first: Run &lt;code&gt;npm install -D @babel/core @babel/cli @babel/preset-env&lt;/code&gt;. This will install the core files, the preset you are going to need always and the command line interface so that you can run Babel in your terminal. Additionally, you should install &lt;code&gt;@babel/preset-typescript&lt;/code&gt; and/or &lt;code&gt;@babel/preset-react&lt;/code&gt;, both according to your needs. I will explain in a bit what each of is used for but you can imagine from their names in which situations you need them.&lt;/p&gt;

&lt;p&gt;So, setup time! Babel is configured via a configuration file. (For details and special cases see &lt;a href="https://babeljs.io/docs/en/config-files"&gt;the documentation&lt;/a&gt;.) The project-wide configuration file should be &lt;code&gt;babel.config.js&lt;/code&gt;. It looks at least very similar to this one:&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;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;presets&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/env&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;modules&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;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/preset-typescript&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/preset-react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;plugins&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/plugin-transform-runtime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;corejs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;presets&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="s1"&gt;@babel/env&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's go through it because there are a few assumptions used in this config which we will need for other features in our list.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;module.exports = {…}&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The file is treated as a CommonJS module and is expected to return a configuration object. It is possible to export a function instead but we'll stick to the static object here. For the function version look into the &lt;a href="https://babeljs.io/docs/en/config-files#config-function-api"&gt;docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;presets&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Presets are (sometimes configurable) sets of Babel plugins so that you don't have to manage yourself which plugins you need. The one you should definitely use is &lt;code&gt;@babel/preset-env&lt;/code&gt;. You have already installed it. Under the &lt;code&gt;presets&lt;/code&gt; key in the config you list every preset your library is going to use along with any preset configuration options.&lt;/p&gt;

&lt;p&gt;In the example config above there are three presets: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;env&lt;/code&gt; is the mentioned standard one. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;typescript&lt;/code&gt; is obviously only needed to compile files that contain TypeScript syntax. As already mentioned it works by &lt;strong&gt;throwing away&lt;/strong&gt; anything that isn't JavaScript. It does not interpret or even check TypeScript. &lt;em&gt;And that's a Good Thing.&lt;/em&gt; We will talk about that point later. If your library is not written in TypeScript, you don't need this preset. But if you need it, you have to install it of course: &lt;code&gt;npm install -D @babel/preset-typescript&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;react&lt;/code&gt; is clearly only needed in React projects. It brings plugins for JSX syntax and transforming. If you need it, install it with: &lt;code&gt;npm i -D @babel/preset-react&lt;/code&gt;. Note: With the config option &lt;code&gt;pragma&lt;/code&gt; (and probably &lt;code&gt;pragmaFrag&lt;/code&gt;) you can transpile JSX to other functions than &lt;code&gt;React.createElement&lt;/code&gt;. See &lt;a href="https://babeljs.io/docs/en/babel-preset-react#pragma"&gt;documentation&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let us look at the &lt;code&gt;env&lt;/code&gt; preset again. Notable is the &lt;code&gt;modules: false&lt;/code&gt; option for &lt;code&gt;preset-env&lt;/code&gt;. The effect is this: As per default Babel transpiles ESModules (&lt;code&gt;import&lt;/code&gt; / &lt;code&gt;export&lt;/code&gt;) to CommonJS modules (&lt;code&gt;require()&lt;/code&gt; / &lt;code&gt;module.export(s)&lt;/code&gt;). With &lt;code&gt;modules&lt;/code&gt; set to &lt;code&gt;false&lt;/code&gt; Babel will output the transpiled files with their ESModule syntax untouched. The rest of the code will be transformed, just the module related statements stay the same. This has (at least) two benefits:&lt;/p&gt;

&lt;p&gt;First, this is a library. If you publish it as separate files, users of your library can import exactly the modules they need. And if they use a bundler that has the ability to treeshake (that is: to remove unused modules on bundling), they will end up with only the code bits they need from your library. With CommonJS modules that would not be possible and they would have your whole library in their bundle.&lt;/p&gt;

&lt;p&gt;Furthermore, if you are going to provide your library as a bundle (for example a UMD bundle that one can use via &lt;a href="http://unpkg.com"&gt;unpkg.com&lt;/a&gt;), you can make use of treeshaking and shrink your bundle as much as possible.&lt;/p&gt;

&lt;p&gt;There is another, suspiciously absent option for &lt;code&gt;preset-env&lt;/code&gt; and that is the &lt;code&gt;targets&lt;/code&gt; option. If you omit it, Babel will transpile your code down to ES5. That is most likely not what you want—unless you live in the dark, medieval times of JavaScript (or you know someone who uses IE). Why transpiling something (and generating much more code) if the runtime environment can handle your modern code? What you could do is to provide said &lt;code&gt;targets&lt;/code&gt; key and give it a &lt;a href="https://github.com/ai/browserslist"&gt;Browserslist&lt;/a&gt; compatible query (see &lt;a href="https://babeljs.io/docs/en/babel-preset-env#targets"&gt;Babel documentation&lt;/a&gt;). For example something like &lt;code&gt;"last 2 versions"&lt;/code&gt; or even &lt;code&gt;"defaults"&lt;/code&gt;. In that case Babel would use the browserslist tool to find out which features it has to transpile to be able to run in the environments given with &lt;code&gt;targets&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But we will use another place to put this configuration than the &lt;code&gt;babel.config.js&lt;/code&gt; file. You see, Babel is not the only tool that can make use of browserslist. But any tool, including Babel, will find the configuration if it's in the right place. The documentation of browserslist recommends to put it inside &lt;code&gt;package.json&lt;/code&gt; so we will do that. Add something like the following to your library's &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"browserslist"&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="s2"&gt;"last 2 Chrome versions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"last 2 Firefox versions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"last 2 Edge versions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"last 2 Opera versions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"last 2 FirefoxAndroid versions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"last 2 iOS version"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"last 2 safari version"&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;I will admit this query is a bit opinionated, maybe not even good for you. You can of course roll your own, or if you are unsure, just go with this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"browserslist"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"defaults"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt; 0.5%, last 2 versions, Firefox ESR, not dead"&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;contains&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ie&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason I propose the query array above is that I want to get an optimized build for modern browsers. &lt;code&gt;"defaults"&lt;/code&gt;, &lt;code&gt;"last 2 versions"&lt;/code&gt; (without specific browser names) and the like will include things like Internet Explorer 11 and Samsung Internet 4. These ancient browsers do not support so much even of ES2015. We would end up with a much much bigger deliverable than modern browsers would need. But there is something you can do about it. You can deliver modern code to modern browsers and still support The Ancients™. We will go into further details in a future section but as a little cliffhanger: browserslist supports multiple configurations. For now we will target only modern browsers.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;plugins&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The Babel configuration above defines one extra plugin: &lt;code&gt;plugin-transform-runtime&lt;/code&gt;. The main reason to use this is deduplication of helper code. When Babel transpiles your modules, it injects little (or not so little) helper functions. The problem is that it does so in every file where they are needed. The &lt;code&gt;transform-runtime&lt;/code&gt; plugin replaces all those injected functions with &lt;code&gt;require&lt;/code&gt; statements to the &lt;code&gt;@babel/runtime&lt;/code&gt; package. That means &lt;strong&gt;in the final application there has to be this runtime package&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To make that happen you could just add &lt;code&gt;@babel/runtime&lt;/code&gt; to the prod dependencies of your library (&lt;code&gt;npm i @babel/runtime&lt;/code&gt;). That would definitely work. But here we will add it to the &lt;code&gt;peerDependencies&lt;/code&gt; in &lt;code&gt;package.json&lt;/code&gt;. That way the user of your library has to install it themselves but on the other hand, they have more control over the version (and you don't have to update the dependency too often). And maybe they have it installed already anyway. So we just push it out of our way and just make sure that it is there when needed.&lt;/p&gt;

&lt;p&gt;Back to the Babel plugin. To use that plugin you have to install it: &lt;code&gt;npm i -D @babel/plugin-transform-runtime&lt;/code&gt;. Now you're good to go.&lt;/p&gt;

&lt;p&gt;Before we go on to the &lt;code&gt;env&lt;/code&gt; key, this is the right place to talk about polyfills and how to use them with Babel.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use polyfills in the best way possible
&lt;/h2&gt;

&lt;p&gt;It took me a few hours reading and understanding the problem, the current solutions and their weaknesses. If you want to read it up yourself, start at &lt;a href="https://babeljs.io/docs/en/babel-polyfill"&gt;Babel polyfill&lt;/a&gt;, go on with &lt;a href="https://babeljs.io/docs/en/babel-plugin-transform-runtime"&gt;Babel transform-runtime&lt;/a&gt; and then read &lt;a href="https://github.com/zloirock/core-js/blob/master/docs/2019-03-19-core-js-3-babel-and-a-look-into-the-future.md"&gt;core-js@3, babel and a look into the future&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But because I already did you don't have to if you don't want to. Ok, let's start with the fact that there two standard ways to get polyfills into your code. Wait, one step back: Why polyfills?&lt;/p&gt;

&lt;p&gt;If you already know, skip to Import core-js. When Babel transpiles your code according to the target environment that you specified, it just changes syntax. Code that the target (the browser) does not understand is changed to (probably longer and more complicated) code that does the same and is understood. But there are things beyond syntax that are possibly not supported: features. Like for example Promises. Or certain features of other builtin types like &lt;code&gt;Object.is&lt;/code&gt; or &lt;code&gt;Array.from&lt;/code&gt; or whole new types like &lt;code&gt;Map&lt;/code&gt; or &lt;code&gt;Set&lt;/code&gt;. Therefore we need polyfills that recreate those features for targets that do not support them natively. &lt;/p&gt;

&lt;p&gt;Also note that we are talking here only about polyfills for ES-features or some closely related Web Platform features (see the &lt;a href="https://github.com/zloirock/core-js/blob/master/README.md#features"&gt;full list here&lt;/a&gt;). There are browser features like for instance the global &lt;code&gt;fetch&lt;/code&gt; function that need separate polyfills.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Import core-js
&lt;/h2&gt;

&lt;p&gt;Ok, so there is a Babel package called &lt;code&gt;@babel/polyfill&lt;/code&gt; that you can import at the entry point of your application and it adds all needed polyfills from a library called &lt;a href="https://github.com/zloirock/core-js"&gt;&lt;code&gt;core-js&lt;/code&gt;&lt;/a&gt; as well as a separate runtime needed for &lt;code&gt;async/await&lt;/code&gt; and generator functions. &lt;strong&gt;But since Babel 7.4.0 this wrapper package is deprecated.&lt;/strong&gt; Instead you should install and import two separate packages: &lt;code&gt;core-js/stable&lt;/code&gt; and &lt;code&gt;regenerator-runtime/runtime&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then, we can get a nice effect from our &lt;code&gt;env&lt;/code&gt; preset from above. We change the configuration to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/env&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;modules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;corejs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;useBuiltIns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;usage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will transform our code so that the import of the whole &lt;code&gt;core-js&lt;/code&gt; gets removed and instead Babel injects specific polyfills in each file where they are needed. And only those polyfills that are needed in the target environment which we have defined via &lt;code&gt;browserslist&lt;/code&gt;. So we end up with the bare minimum of additional code.&lt;/p&gt;

&lt;p&gt;Two additional notes here: (1) &lt;a&gt;&lt;/a&gt;You have to explicitly set &lt;code&gt;corejs&lt;/code&gt; to &lt;code&gt;3&lt;/code&gt;. If the key is absent, Babel will use version 2 of &lt;code&gt;corejs&lt;/code&gt; and you don't want that. Much has changed for the better in version 3, especially feature-wise. But also bugs have been fixed and the package size is dramatically smaller. If you want, read it all up &lt;a href="https://github.com/zloirock/core-js/blob/master/docs/2019-03-19-core-js-3-babel-and-a-look-into-the-future.md#what-changed-in-core-js3"&gt;here (overview)&lt;/a&gt; and &lt;a href="https://github.com/zloirock/core-js/blob/master/CHANGELOG.md#300---20190319"&gt;here (changelog for version 3.0.0)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And (2), there is another possible value for &lt;code&gt;useBuiltIns&lt;/code&gt; and that is &lt;code&gt;entry&lt;/code&gt;. This variant will not figure out which features your code actually needs. Instead, it will just add &lt;em&gt;all&lt;/em&gt; polyfills that exist for the given target environment. It works by looking for &lt;code&gt;corejs&lt;/code&gt; imports in your source (like &lt;code&gt;import corejs/stable&lt;/code&gt;) which should only appear once in your codebase, probably in your entry module. Then, it replaces this "meta" import with all of the specific imports of polyfills that match your targets. This approach will likely result in a much, much larger package with much of unneeded code. So we just use &lt;code&gt;usage&lt;/code&gt;. (With &lt;code&gt;corejs@2&lt;/code&gt; there were a few problems with &lt;code&gt;usage&lt;/code&gt; that could lead to wrong assumptions about which polyfills you need. So in some cases &lt;code&gt;entry&lt;/code&gt; was the more safe option. But these problems are appearently fixed with version 3.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Tell transform-runtime to import core-js
&lt;/h2&gt;

&lt;p&gt;The second way to get the polyfills that your code needs is via the &lt;code&gt;transform-runtime&lt;/code&gt; plugin from above. You can configure it to inject not only imports for the Babel helpers but also for the &lt;code&gt;core-js&lt;/code&gt; modules that your code needs:&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;plugins&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/plugin-transform-runtime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;corejs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells the plugin to insert import statements to corejs version 3. The reason for this version I have mentioned &lt;a href="https://github.com/zloirock/core-js/blob/master/docs/2019-03-19-core-js-3-babel-and-a-look-into-the-future.md#what-changed-in-core-js3"&gt;above&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you configure the plugin to use &lt;code&gt;core-js&lt;/code&gt;, you have to change the runtime dependency: The &lt;code&gt;peerDependencies&lt;/code&gt; should now contain not &lt;code&gt;@babel/runtime&lt;/code&gt; but &lt;code&gt;@babel/runtime-corejs3&lt;/code&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Which way should you use?
&lt;/h2&gt;

&lt;p&gt;In general, the combination of manual import and the &lt;code&gt;env&lt;/code&gt; preset is meant for applications and the way with &lt;code&gt;transform-runtime&lt;/code&gt; is meant for libraries. One reason for this is that the first way of using &lt;code&gt;core-js&lt;/code&gt; imports polyfills that "pollute" the global namespace. And if your library defines a global &lt;code&gt;Promise&lt;/code&gt;, it could interfere with other helper libraries used by your library's users. The imports that are injected by &lt;code&gt;transform-runtime&lt;/code&gt; are contained. They import from &lt;code&gt;core-js-pure&lt;/code&gt; which does not set globals.&lt;/p&gt;

&lt;p&gt;On the other hand, using the transform plugin does not account for the environment you are targeting. Probably in the future it could also use the same heuristics as &lt;code&gt;preset-env&lt;/code&gt; but at the moment it just adds every polyfill that is theoretically needed by your code. Even if the target browsers would not need them or not all of them. For the development in that direction see the &lt;a href="https://github.com/zloirock/core-js/blob/master/docs/2019-03-19-core-js-3-babel-and-a-look-into-the-future.md#babelruntime-for-target-environment"&gt;comment from the corejs maintainer&lt;/a&gt; and this &lt;a href="https://github.com/babel/babel/issues/10008"&gt;RFC issue at Babel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So it looks like you have to choose between a package that adds as few code as possible and one that plays nicely with unknown applications around it. I have played around with the different options a bit and bundled the resulting files with webpack and this is my result:&lt;/p&gt;

&lt;p&gt;You get the smallest bundle with the &lt;code&gt;core-js&lt;/code&gt; globals from &lt;code&gt;preset-env&lt;/code&gt;. But it's too dangerous for a library to mess with the global namespace of its users. Besides that, in the (hopefully very near) future the transform-runtime plugin will also use the browserslist target environments. So the size issue is going to go away. &lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;env&lt;/code&gt; key
&lt;/h2&gt;

&lt;p&gt;With &lt;code&gt;env&lt;/code&gt; you can add configuration options for specific build environments. When Babel executes it will look for &lt;code&gt;process.env.BABEL_ENV&lt;/code&gt;. If that's not set, it will look up &lt;code&gt;process.env.NODE_ENV&lt;/code&gt; and if that's not found, it will fallback to the string &lt;code&gt;'development'&lt;/code&gt;. After doing this lookup it will check if the config has an &lt;code&gt;env&lt;/code&gt; object and if there is a key in that object that matches the previously found env string. If there is such a match, Babel applies the configuration under that env name.&lt;/p&gt;

&lt;p&gt;We use it for example for our test runner &lt;a href="https://jestjs.io/"&gt;Jest&lt;/a&gt;. Because Jest can not use ESModules we need a Babel config that transpiles our modules to CommonJS modules. So we just add an alternative configuration for &lt;code&gt;preset-env&lt;/code&gt; under the env name &lt;code&gt;'test'&lt;/code&gt;. When Jest runs (We will use &lt;code&gt;babel-jest&lt;/code&gt; for this. See in a later part of this series.) it sets &lt;code&gt;process.env.NODE_ENV&lt;/code&gt; to &lt;code&gt;'test'&lt;/code&gt;. And so everything will work.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Conclusion and final notes for Babel setup
&lt;/h2&gt;

&lt;p&gt;Install all needed packages:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i -D @babel/core @babel/cli @babel/preset-env @babel/plugin-transform-runtime&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Add a peerDependency to your &lt;code&gt;package.json&lt;/code&gt; that your users should install themselves:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
  "peerDependencies": {
      "@babel/runtime-corejs3": "^7.4.5", // at least version 7.4; your users have to provide it
  }
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a &lt;code&gt;babel.config.js&lt;/code&gt; that contains at least this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// babel.config.js&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;presets&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/env&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// transpile for targets&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;modules&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="c1"&gt;// don't transpile module syntax&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;plugins&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/plugin-transform-runtime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// replace helper code with runtime imports (deduplication)&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;corejs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// import corejs polyfills exactly where they are needed&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// extra configuration for process.env.NODE_ENV === 'test'&lt;/span&gt;
      &lt;span class="na"&gt;presets&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="s1"&gt;@babel/env&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// overwrite env-config from above with transpiled module syntax&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;If you write TypeScript, run &lt;code&gt;npm i -D @babel/preset-typescript&lt;/code&gt; and add &lt;code&gt;'@babel/preset-typescript'&lt;/code&gt; to the &lt;code&gt;presets&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you write React code, (JSX) run &lt;code&gt;npm i -D @babel/preset-react&lt;/code&gt; and add &lt;code&gt;'@babel/preset-react'&lt;/code&gt; to the &lt;code&gt;presets&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Add a &lt;code&gt;browserslist&lt;/code&gt; section in your package.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"browserslist"&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="s2"&gt;"last 2 Chrome versions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"last 2 Firefox versions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"last 2 Edge versions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"last 2 Opera versions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"last 2 FirefoxAndroid versions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"last 2 iOS version"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"last 2 safari version"&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="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In case of using another browserslist query that includes targets that do not have support for generator functions and/or async/await, there is something you have to tell your users:&lt;/p&gt;

&lt;p&gt;Babel's transform-runtime plugin will import &lt;code&gt;regenerator-runtime&lt;/code&gt;. This library depends on a globally available Promise constructor. &lt;strong&gt;But&lt;/strong&gt; Babel will not include a promise polyfill for regenerator-runtime. Probably because it adds polyfills only for things genuinely belonging to &lt;em&gt;your&lt;/em&gt; code, not external library code. That means, if your usecase meets these conditions, you should mention it in your README or installation instructions that the users of your lib have to make sure there is a Promise available in their application.&lt;/p&gt;

&lt;p&gt;And that is it for the Babel setup.&lt;/p&gt;

&lt;p&gt;Next up: Compiling with the TypeScript compiler&lt;/p&gt;




&lt;p&gt;Many thanks to my friend &lt;a href="https://twitter.com/Tim_Kraut"&gt;Tim Kraut&lt;/a&gt; for proof-reading this article!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>library</category>
      <category>babel</category>
    </item>
    <item>
      <title>Publish a modern JavaScript (or TypeScript) library</title>
      <dc:creator>Tobias Barth</dc:creator>
      <pubDate>Sun, 07 Jul 2019 11:47:10 +0000</pubDate>
      <link>https://forem.com/4nduril/publish-a-modern-javascript-or-typescript-library-3hc3</link>
      <guid>https://forem.com/4nduril/publish-a-modern-javascript-or-typescript-library-3hc3</guid>
      <description>&lt;p&gt;Did you ever write some library code together and then wanted to publish it as an NPM package but realized you have no idea what is the technique du jour to do so?&lt;/p&gt;

&lt;p&gt;Did you ever wonder "Should I use Webpack or Rollup?", "What about ES modules?", "What about any other package format, actually?", "How to publish Types along with the compiled code?" and so on?&lt;/p&gt;

&lt;p&gt;Perfect! You have found the right place. In this series of articles I will try to answer every one of these questions. With example configurations for most of the possible combinations of these tools and wishes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Technology base
&lt;/h3&gt;

&lt;p&gt;This is the set of tools and their respective version range for which this tutorial is tested:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ES2018 &lt;/li&gt;
&lt;li&gt;Webpack &amp;gt;= 4&lt;/li&gt;
&lt;li&gt;Babel &amp;gt;= 7.4&lt;/li&gt;
&lt;li&gt;TypeScript &amp;gt;= 3&lt;/li&gt;
&lt;li&gt;Rollup &amp;gt;= 1&lt;/li&gt;
&lt;li&gt;React &amp;gt;= 16.8
( code aimed at other libraries like Vue or Angular should work the same )&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some or even most of that what follows could be applied to older versions of these tools, too. But I will not guarantee or test it. &lt;/p&gt;

&lt;h3&gt;
  
  
  Creation
&lt;/h3&gt;

&lt;p&gt;The first thing to do before publishing a library is obviously to write one. Let's say we have already done that. In fact, it's &lt;a href="https://github.com/4nduril/library-starter/tree/init"&gt;this one&lt;/a&gt;. It consists of several source files and therefore, modules. We have provided our desired functionality, used our favorite, modern JavaScript (or TypeScript) features and crafted it with our beloved editor settings.&lt;/p&gt;

&lt;p&gt;What now? What do we want to achieve in this tutorial?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Transpile modern language features so that every browser in one of the last 2 versions can understand our code.&lt;/li&gt;
&lt;li&gt;Avoid duplicating compile-stage helpers to keep the library as small as possible.&lt;/li&gt;
&lt;li&gt;Ensure code quality with linting and tests.&lt;/li&gt;
&lt;li&gt;Bundle our modules into one consumable, installable file.&lt;/li&gt;
&lt;li&gt;Provide ES modules to make the library tree-shakable.&lt;/li&gt;
&lt;li&gt;Provide typings if we wrote our library in TypeScript.&lt;/li&gt;
&lt;li&gt;Improve collaborating with other developers (from our team or, if it is an open source library, from the public).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Wow. That's a whole lot of things. Let's see if we can make it.&lt;/p&gt;

&lt;p&gt;Note that some of these steps can be done with different tools or maybe differ depending on the code being written in TypeScript or JavaScript. We'll cover all of that. Well, probably not all of that, but I will try to cover the most common combinations.&lt;/p&gt;

&lt;p&gt;The chapters of this series will not only show configurations I think you should use, but also will I explain the reasoning behind it and how it works. If you aren't interested in these backgrounds, there will be a link right at the top of each post down to the configurations and steps to execute without much around.&lt;/p&gt;

&lt;h3&gt;
  
  
  Go!
&lt;/h3&gt;

&lt;p&gt;We will start with the first points on our list above. As new articles arrive, I will add them here as links and I will also try to keep the finished articles updated when the tools they use get new features or change APIs. If you find something that's not true anymore, please give me a hint.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://dev.to/4nduril/transpile-modern-language-features-with-babel-4fcp"&gt;Transpile modern language features – With Babel&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/4nduril/compiling-modern-language-features-with-the-typescript-compiler-36m3"&gt;Compiling modern language features with the TypeScript compiler&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/4nduril/building-your-library-part-1-5cii"&gt;Building your library: Part 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/4nduril/check-types-and-emit-type-declarations-1i29"&gt;Check types and emit type declarations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/4nduril/how-to-bundle-your-library-and-why-1gao"&gt;How to bundle your library and why&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/4nduril/bundling-your-library-with-webpack-12ig"&gt;Bundling your library with Webpack&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Oh and one last thing™: I'll be using &lt;code&gt;npm&lt;/code&gt; throughout the series because I like it. If you like &lt;code&gt;yarn&lt;/code&gt; better, just exchange the commands.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>library</category>
      <category>howto</category>
    </item>
    <item>
      <title>Resize LVM on LUKS partition without messing everything up</title>
      <dc:creator>Tobias Barth</dc:creator>
      <pubDate>Mon, 10 Jun 2019 12:00:16 +0000</pubDate>
      <link>https://forem.com/4nduril/resize-lvm-on-luks-partition-without-messing-everything-up-14dk</link>
      <guid>https://forem.com/4nduril/resize-lvm-on-luks-partition-without-messing-everything-up-14dk</guid>
      <description>&lt;p&gt;Since forever I run my work computer operating systems on a full-disk-encrypted partition. Currently this is Manjaro Linux. When I set up my current machine I made the following partition scheme:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sda                  238,5G  disk
├─sda1                 260M  part  /boot/efi
├─sda2                 128M  part  /boot
└─sda3                 237G  part
  └─tank               237G  crypt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Somewhere, I can't even remember when, I read that 128M for &lt;code&gt;/boot&lt;/code&gt; would be sufficient. And it was for a few years. But kernel images and/or initram disks grew bigger and bigger until I could not upgrade to a newer kernel anymore. The last kernel I ran was Linux 4.16 and the files in &lt;code&gt;/boot&lt;/code&gt; took around 75M space and so &lt;code&gt;mhwd-kernel -i linux417&lt;/code&gt; had too little space on the device left.&lt;/p&gt;

&lt;p&gt;What I needed to do was to shrink &lt;code&gt;/dev/sda3&lt;/code&gt;, move it to the end of the SSD and grow &lt;code&gt;/dev/sda2&lt;/code&gt; as necessary.&lt;/p&gt;

&lt;p&gt;But I did not know if this was even possible with my setup. Inside the encrypted partition there is an LVM container with 5 logical volumes including &lt;code&gt;/&lt;/code&gt;. I pushed it into the future again and again because most of the time I am working in running projects and can not afford to have a non-functioning machine for &amp;lt;absurd amount of time that you never expect before a hardware near change&amp;gt;.&lt;/p&gt;

&lt;p&gt;But in the end it was relatively easy. I had feared that in the worst case I would have to re-setup my whole machine and restore backups for the data and system partitions. Which then maybe would need endless tweaking until it runs again (No, I never had a hard disk failure or similar, so I never had to actually do anything like that).&lt;/p&gt;

&lt;p&gt;So, here are the things I needed to do:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Backup
&lt;/h2&gt;

&lt;p&gt;List all logcal volumes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# lvs
LV     VG   Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
docker tank -wi-ao----   5,00g                                        
home   tank -wi-ao---- 100,00g                                        
mongo  tank -wi-ao----   1,00g                                        
root   tank -wi-ao----  25,00g                                        
swap   tank -wc-ao----  32,00g
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For each lv do the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# lvcreate -s -n &amp;lt;name&amp;gt;snap /dev/tank/&amp;lt;name&amp;gt;
# dd if=/dev/tank/&amp;lt;name&amp;gt;snap of=/path/to/external/storage/&amp;lt;name&amp;gt;.img
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where &lt;code&gt;&amp;lt;name&amp;gt;&lt;/code&gt; must be replaced by the actual names of the lvs. Then I backed up both the &lt;code&gt;/boot&lt;/code&gt; and the &lt;code&gt;/boot/efi&lt;/code&gt; partitions, also with &lt;code&gt;dd&lt;/code&gt;.&lt;br&gt;
Finally I made a backup of the LUKS header for the crypto-partition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# cryptsetup luksHeaderBackup /dev/sda3 --header-backup-file /path/to/external/storage/luks-header.bkp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Boot in a live system from an USB stick and decrypt the device
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# cryptsetup open /dev/sda3 tank --type luks 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Resize the physical volume
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I have free space inside my LVM container. As you can see from the output of &lt;code&gt;lvs&lt;/code&gt; above I currently use only 143GB out of roughly 238GB. That means I do not have to resize logical volumes &lt;em&gt;before&lt;/em&gt; I resize the containing physical volume. If you use all of the available space for logical volumes, look into &lt;a href="https://jlk.fjfi.cvut.cz/arch/manpages/man/lvresize.8"&gt;&lt;code&gt;lvresize(8)&lt;/code&gt;&lt;/a&gt; first: For example in the  &lt;a href="https://wiki.archlinux.org/index.php/LVM#Resizing_volumes"&gt;Arch Wiki&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I generously shrank the volume from 238,07G to 236G with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# pvresize --setphysicalvolumesize 236G /dev/mapper/tank
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Resize the crypto-device
&lt;/h2&gt;

&lt;p&gt;Find out how many sectors is the current size (note that my crypto-device has the same name like my volume group: &lt;code&gt;tank&lt;/code&gt;. That could be different in your setup):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# cryptsetup status tank
...
sector size:  512
size:  499122176
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the end I want to add about 1G to the &lt;code&gt;/boot&lt;/code&gt; partition. That is &lt;code&gt;1024 * 1024 * 1024 / 512 = 2097152&lt;/code&gt; sectors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# cryptsetup -b 497025024 resize tank
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Resize the GUID partition
&lt;/h2&gt;

&lt;p&gt;You see we go from innermost to outermost: LVM -&amp;gt; crypto -&amp;gt; GUID. I use &lt;code&gt;parted&lt;/code&gt; to resize the partition &lt;code&gt;/dev/sda3&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;# parted
(parted) unit s
(parted) print
...
Number  Begin     End         Size                     Name  Flags
...
3      3100672s  500115455s  497014784s               TANK  lvm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These numbers were actually different as I write this blog post in hindsight. The point is that partition number 3 went all the way to the last sector of the disk and I now must calculate where it should end in the future. Because &lt;code&gt;resizepart&lt;/code&gt; takes not the future size but the future end sector of the partition as argument. So I subtract the same sector count as calculated above for cryptsetup (&lt;code&gt;2097152&lt;/code&gt;) from the &lt;em&gt;end sector&lt;/em&gt; of partition 3 (&lt;code&gt;500115455&lt;/code&gt;) which gives &lt;code&gt;498018303&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;
(parted) resizepart 3 498018303s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have free space on the SSD &lt;em&gt;after&lt;/em&gt; the main partition. But I want to grow partition 2.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Reorder partitions and resize partition 2
&lt;/h2&gt;

&lt;p&gt;I did that with GParted instead of a command line tool. Probably there is a way to do it with &lt;code&gt;gdisk&lt;/code&gt; but &lt;code&gt;parted&lt;/code&gt; has removed its command to &lt;code&gt;move&lt;/code&gt; partitions. And because I was in a graphical live system anyway and also read that you could do it with GParted I just went for it.&lt;br&gt;
First I closed the crypto device because GParted would not let me move the partition otherwise:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# vgchange -an tank
# cryptsetup close tank
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I opened GParted and right-clicked on the crypto partition. I chose "Change size|Move" and moved the free space after the partition before it. Then I opend the same dialog for the &lt;code&gt;/boot&lt;/code&gt; partition and extended it to cover all of the free space. Finally I committed the changes.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>lvm</category>
      <category>encryption</category>
    </item>
    <item>
      <title>Fix speed issue when writing to NAS system</title>
      <dc:creator>Tobias Barth</dc:creator>
      <pubDate>Fri, 03 May 2019 09:52:53 +0000</pubDate>
      <link>https://forem.com/4nduril/fix-speed-issue-when-writing-to-nas-system-3oca</link>
      <guid>https://forem.com/4nduril/fix-speed-issue-when-writing-to-nas-system-3oca</guid>
      <description>&lt;p&gt;I just fixed an issue with my FreeBSD home server. It is set up as a file server for Mac (AFP) and Linux Clients (NFS). My local network is Gigabit-based sothe limitating factor on read/write speeds should be the hard disk drives in the server.&lt;/p&gt;

&lt;p&gt;The server has a Core i3-6100T CPU @ 3.20GHz, 8GB RAM, a ZFS setup with two mirror vdevs each consisting of two disks connected to the board via SATA3. And of course the onboard Gbit NIC (Realtek).&lt;/p&gt;

&lt;p&gt;I know very well that write speed was at around 50–60MB/sec, which I would expect. But lately, it dropped amazingly to ~1MB/sec. And I just couldn't think of, why. I suspected the cable, the AFP, the RAM anything.&lt;/p&gt;

&lt;p&gt;What I didn't suspect — until today, that is — was the network interface. But I had time today for some googling and even if I didn't found the solution directly, I stumbled across something related to the output of &lt;code&gt;ifconfig&lt;/code&gt;. So I hacked that into the console and stared at it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;re0: flags=8843&amp;lt;UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST&amp;gt; metric 0 mtu 1500
        options=8209b&amp;lt;RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,WOL_MAGIC,LINKSTATE&amp;gt;
        ether 4c:cc:6a:b3:3c:f5
        hwaddr 4c:cc:6a:b3:3c:f5
        inet6 fd23:16:7:7::1 prefixlen 64
        inet6 fe80::4ecc:6aff:feb3:3cf5%re0 prefixlen 64 scopeid 0x1
        inet 192.168.10.118 netmask 0xffffff00 broadcast 192.168.10.255
        nd6 options=21&amp;lt;PERFORMNUD,AUTO_LINKLOCAL&amp;gt;
        media: Ethernet autoselect (10baseT/UTP &amp;lt;full-duplex&amp;gt;)
        status: active
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do you spot it?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        media: Ethernet autoselect (10baseT/UTP &amp;lt;full-duplex&amp;gt;)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well, that is … unfortunate. The output of &lt;code&gt;ifconfig -m re0&lt;/code&gt; gave me:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    supported media:
            media autoselect mediaopt flowcontrol
            media autoselect
            media 1000baseT mediaopt full-duplex,flowcontrol,master
            media 1000baseT mediaopt full-duplex,flowcontrol
            media 1000baseT mediaopt full-duplex,master
            media 1000baseT mediaopt full-duplex
            media 100baseTX mediaopt full-duplex,flowcontrol
            media 100baseTX mediaopt full-duplex
            media 100baseTX
            media 10baseT/UTP mediaopt full-duplex,flowcontrol
            media 10baseT/UTP mediaopt full-duplex
            media 10baseT/UTP
            media none
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So I ran &lt;code&gt;sudo ifconfig re0 media 1000baseTX mediaopt full-duplex&lt;/code&gt; and it worked. After that I also ran &lt;code&gt;sudo ifconfig re0 media autoselect&lt;/code&gt; which also set the media type to 1000baseT full-duplex. I have no idea why the system did that wrong (or when) but I will monitor what happens after the next reboot. Maybe I have to do some configuration but maybe it was just an hickup.&lt;/p&gt;

&lt;p&gt;Speeds are up to 60MB/sec again.&lt;/p&gt;

</description>
      <category>freebsd</category>
      <category>nas</category>
      <category>network</category>
    </item>
    <item>
      <title>Execute Promise-based code in order over an array</title>
      <dc:creator>Tobias Barth</dc:creator>
      <pubDate>Thu, 18 Apr 2019 13:09:48 +0000</pubDate>
      <link>https://forem.com/4nduril/execute-promise-based-code-in-order-over-an-array-1kg7</link>
      <guid>https://forem.com/4nduril/execute-promise-based-code-in-order-over-an-array-1kg7</guid>
      <description>&lt;h3&gt;
  
  
  The problem
&lt;/h3&gt;

&lt;p&gt;I recently faced a problem: I had a list (an array) of input data and wanted to execute a function for every item in that list. &lt;/p&gt;

&lt;p&gt;No problem, you say, take &lt;code&gt;Array.prototype.map&lt;/code&gt;, that's what it's for. &lt;strong&gt;BUT&lt;/strong&gt; the function in question returns a Promise and I want to be able to only continue in the program flow when all of these Promises are resolved.&lt;/p&gt;

&lt;p&gt;No problem, you say, wrap it in &lt;code&gt;Promise.all&lt;/code&gt;, that's what it's for. &lt;strong&gt;BUT&lt;/strong&gt; the function in question is very expensive. So expensive that it spawns a child process (the whole code runs in NodeJS on my computer) and that child process is using so much CPU power that my computer comes to grinding halt when my input list is longer than a few elements.&lt;/p&gt;

&lt;p&gt;And that's because effectively, all the heavy child processes get started in near parallel. Actually they get started in order but the next will not wait for the previous to finish.&lt;/p&gt;

&lt;h3&gt;
  
  
  The first solution
&lt;/h3&gt;

&lt;p&gt;So what I need is a way to traverse the array, execute the function for the current element, &lt;em&gt;wait&lt;/em&gt; until the Promise resolves and &lt;em&gt;only then&lt;/em&gt; go to the next element and call the function with it. That means &lt;code&gt;map&lt;/code&gt; will not work because I have no control over the execution flow. So I will have to build my own &lt;code&gt;map&lt;/code&gt;. And while I am on it, I will implement it a bit nicer as stand-alone function that takes the mapper function first and then the data array:&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;sequentialMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;innerSequentialMap&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;tail&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;headResult&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;innerSequentialMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tailResult&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;headResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;tailResult&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, what does this? It takes the function &lt;code&gt;fn&lt;/code&gt; that should be applied to all values in the array and returns a new function. This new function expects an array as input. You see that the function is curried in that it takes only ever one argument and the real execution starts when all arguments are provided. That allows us for example to "preload" &lt;code&gt;sequentialMap&lt;/code&gt; with a mapper function and reuse it on different input data:&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;// preloading&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mapWithHeavyComputations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sequentialMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;heavyAsyncComputation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// execution&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mapWithHeavyComputations&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But in this case the currying enables (or simplifies) another technique: recursion.&lt;/p&gt;

&lt;p&gt;We say a function is recursive when it calls itself repeatedly. Recursion is the functional equivalent to looping in imperative programming. You can refactor one into the other as long as the programming language allows both ways. Or so I thought.&lt;/p&gt;

&lt;p&gt;I used a recursive function here because I could not think of a way to wait for a Promise resolving in a loop. How would I use &lt;code&gt;.then()&lt;/code&gt; and jump to the next iteration step &lt;em&gt;within&lt;/em&gt; that &lt;code&gt;then&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Anyway, let's go further through the code. In the body of the internal or second function firstly I define a condition to terminate the recursion: I check if the first element is falsy and if it is falsy I just return a Promise that resolves to an empty array. That is because the main path of the function returns its data as an array wrapped in a Promise. So if we return the same type of data when we terminate all will fit nicely together.&lt;/p&gt;

&lt;p&gt;Next, if we don't terminate (which means the first element of the given list is truthy) we apply the mapper function to it. That will return a Promise and we wait for its resolving with &lt;code&gt;.then&lt;/code&gt;. Once it resolves the whole thing gets a bit magical, but not too much.&lt;/p&gt;

&lt;p&gt;What we do then is to build a nested Promise. Normally, when you work with Promises and want to apply several functions to the inner values you would build a "Promise chain":&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;firstPromise&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doSomethingWithIt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doSomthingElseAfterThat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="err"&gt;…&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem we have here is that to build the final result (the mapped array), we need the result from the first resolved Promise and then also the result values from all the other Promises which are not computed &lt;em&gt;upon&lt;/em&gt; each other but &lt;em&gt;independent&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So we use two features to solve that: nested scope and Promise-flattening (did someone say Monad?).&lt;/p&gt;

&lt;p&gt;For the nested scope first: When we define a function within a function then the inner function can access variables that are defined not within itself but in the outer function (the outer or surrounding scope):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;outer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg1&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;outerValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arg1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;inner&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;outerValue&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;outer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;666&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// logs 731&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And Promise-flattening means essentially that if you have a Promise of a Promise of a value that is the same as if you just had a Promise of the value.&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;p2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Promise&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="nb"&gt;Promise&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="mi"&gt;1&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;p1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Promise&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// logs 1&lt;/span&gt;
&lt;span class="nx"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// logs 1&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;To recall, here is what the code we are talking about looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;headResult&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;sequentialMapInternal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tailResult&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;headResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;tailResult&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;We keep the &lt;code&gt;headResult&lt;/code&gt; in scope and then we generate the next Promise by calling the inner function recursively again but with a shorter list without the first element. We wait again with &lt;code&gt;.then&lt;/code&gt; for the final result and only then we build our result array.&lt;/p&gt;

&lt;p&gt;This is done by spreading the &lt;code&gt;tailResult&lt;/code&gt; after the &lt;code&gt;headResult&lt;/code&gt;: We know we get one value from calling &lt;code&gt;fn(head)&lt;/code&gt; but we get a list of values from calling &lt;code&gt;sequentialMapInternal(tail)&lt;/code&gt;. So with the spread operator we get a nice flat array of result values.&lt;/p&gt;

&lt;p&gt;Note that the function inside the first &lt;code&gt;then&lt;/code&gt;, that gets &lt;code&gt;headResult&lt;/code&gt; as parameter immediately returns the next Promise(-chain). And that is essentially where we use Promise-flattening. &lt;code&gt;.then&lt;/code&gt; returns a Promise in itself and now we are returning a Promise inside of that. But the result will look like an ordinary Promise – no nesting visible.&lt;/p&gt;

&lt;h3&gt;
  
  
  The better way
&lt;/h3&gt;

&lt;p&gt;While that works perfectly and my computer remains usable also when I call my script now, all these nested &lt;code&gt;then&lt;/code&gt;s do not look so nice. We can fix that when we have async functions at our disposal:&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;sequentialMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;innerSequentialMap&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;tail&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;headResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;head&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;tailResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;innerSequentialMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tail&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;headResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;tailResult&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;Yes, that is much better. Now the exection is paused until &lt;code&gt;headResult&lt;/code&gt; is there and then paused again until &lt;code&gt;tailResult&lt;/code&gt; is there and only then we build our result array and are finished.&lt;/p&gt;

&lt;h3&gt;
  
  
  The shortest way
&lt;/h3&gt;

&lt;p&gt;Wait. Did I just say I can pause execution with &lt;code&gt;await&lt;/code&gt;? Wouldn't this work also within a loop?&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;loopVersion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;elem&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;elem&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;result&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See, this is what happens to people like me that are too deep into functional programming paradigms. Yes, you should generally avoid loops because they are not declarative and you end up telling the machine (and your coworker) not &lt;em&gt;what&lt;/em&gt; you want to happen but &lt;em&gt;how&lt;/em&gt; you want it to happen. That is, again, generally, no good practice. But in this case that is exactly what we wanted: To give a step-by-step schema on how to execute our code. To optimize for resource usage.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>recursion</category>
      <category>promises</category>
      <category>asyncawait</category>
    </item>
  </channel>
</rss>
