<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Wouter</title>
    <description>The latest articles on DEV Community by Wouter (@woubuc).</description>
    <link>https://dev.to/woubuc</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%2F3501%2F1015540.png</url>
      <title>DEV Community: Wouter</title>
      <link>https://dev.to/woubuc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/woubuc"/>
    <language>en</language>
    <item>
      <title>How to use API keys in client-side Javascript</title>
      <dc:creator>Wouter</dc:creator>
      <pubDate>Thu, 17 Sep 2020 14:47:51 +0000</pubDate>
      <link>https://dev.to/woubuc/how-to-use-api-keys-in-client-side-javascript-kdg</link>
      <guid>https://dev.to/woubuc/how-to-use-api-keys-in-client-side-javascript-kdg</guid>
      <description>&lt;p&gt;Managing API keys in front-end codebases can be a little tricky, especially for people who aren't very experienced with it. Here's an introduction to API keys and an overview of what to do and what not to do when it comes to key management in client-side Javascript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types of API keys
&lt;/h2&gt;

&lt;p&gt;Generally speaking, there are two types of API keys: &lt;strong&gt;secret&lt;/strong&gt; keys and &lt;strong&gt;read-only&lt;/strong&gt; keys. Sometimes these are called private or public API keys, but it's best to use different terms to avoid confusion with SSH keys.&lt;/p&gt;

&lt;h3&gt;
  
  
  Secret keys
&lt;/h3&gt;

&lt;p&gt;These are your traditional API keys that have write access to the API resources. They can modify data, delete records, or even disable your entire account. If someone got a hold of these API keys, they could do a lot of damage. Depending on what functions the API allows, malicious use of your secret API key could cost you a lot of time and money.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Never ever use secret keys in client-side code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;No, I don't want to hear about your clever obfuscation that prevents people from lifting your key from your source code. Or any one of a dozen other ways you might have "hidden" your API key. If your client-side code makes an HTTP request with that key, it will show up in the network panel of the browser's developer tools for anyone to see.&lt;/p&gt;

&lt;p&gt;Just don't put them in your code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WrpuiwV3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.woubuc.be/content/images/2020/09/image-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WrpuiwV3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.woubuc.be/content/images/2020/09/image-1.png" alt="How to use API keys in client-side Javascript" width="780" height="228"&gt;&lt;/a&gt;The docs for the &lt;a href="https://ghost.org/docs/api/v3/admin/#authentication"&gt;Ghost Admin API&lt;/a&gt; explain that the API key is only suitable for server-side environments&lt;/p&gt;

&lt;h3&gt;
  
  
  Read-only keys
&lt;/h3&gt;

&lt;p&gt;These API keys are specifically designed to be used in client-side code. They can only read data from the API, not write to it or change anything. So even if someone got a hold of a read-only API key, they couldn't do any damage to your data.&lt;/p&gt;

&lt;p&gt;Whether an API can be used in client-side code is often noted explicitly in the documentation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lYztS3At--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.woubuc.be/content/images/2020/09/image.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lYztS3At--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.woubuc.be/content/images/2020/09/image.png" alt="How to use API keys in client-side Javascript" width="880" height="232"&gt;&lt;/a&gt;The docs for the &lt;a href="https://updown.io/api"&gt;updown.io API&lt;/a&gt; explain the read-only API key&lt;/p&gt;

&lt;h2&gt;
  
  
  How to add API keys to your bundle
&lt;/h2&gt;

&lt;p&gt;If you're using a bundler, adding API keys or other configuration is usually fairly easy. The standard way in Node.js is to use &lt;code&gt;dotenv&lt;/code&gt; to load a &lt;code&gt;.env&lt;/code&gt; file and access the environment variables through &lt;code&gt;process.env.*&lt;/code&gt;. Most Javascript bundlers support this as well, either built-in or through plugins.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Webpack: &lt;code&gt;dotenv-webpack&lt;/code&gt;, or simply the built-in &lt;a href="https://webpack.js.org/plugins/define-plugin/"&gt;DefinePlugin&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Rollup: &lt;code&gt;@rollup/plugin-replace&lt;/code&gt; along with dotenv&lt;/li&gt;
&lt;li&gt;Parcel: &lt;a href="https://parceljs.org/env.html"&gt;built-in&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What about unbundled javascript files?
&lt;/h3&gt;

&lt;p&gt;If you're not using a bundler, embedding configuration values an be a little trickier. My preferred solution is to create a &lt;code&gt;config.json&lt;/code&gt; file and &lt;code&gt;fetch()&lt;/code&gt; the config data in my Javascript file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "apiKey": "My read-only API key"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
config.json







&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fetch('/config.json').then(function (config) {
    console.log('API key:', config.apiKey);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
script.js





&lt;p&gt;Simply add the &lt;code&gt;config.json&lt;/code&gt; to your &lt;code&gt;.gitignore&lt;/code&gt; and treat it the same as you would a &lt;code&gt;.env&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Of course, the downside of this method is that you have to make an additional network request. You can mitigate the delay by adding a &lt;code&gt;&amp;lt;link rel="preload"&amp;gt;&lt;/code&gt; tag to your page, but it will still have some effect on how fast your Javascript will be ready to run.&lt;/p&gt;

&lt;p&gt;Keeping that in mind, I highly recommend using a tool like &lt;a href="https://parceljs.org/"&gt;Parcel&lt;/a&gt; to bundle your Javascript code. It will improve the load times of your web app and it will make your life easier.&lt;/p&gt;

&lt;p&gt;However, if you're not working on a large online platform, if you're just writing some Javascript for your personal blog or website, then you have to ask yourself...&lt;/p&gt;

&lt;h2&gt;
  
  
  Do I need to hide my API keys?
&lt;/h2&gt;

&lt;p&gt;The popular &lt;a href="https://12factor.net/"&gt;Twelve-Factor App&lt;/a&gt; principles state that configuration, such as credentials to external services (i.e. API keys), &lt;a href="https://12factor.net/config"&gt;should be stored in the environment&lt;/a&gt;. This means using something like &lt;code&gt;dotenv&lt;/code&gt; to load and manage your config, rather than including it directly in your code and pushing it to your repository. And I completely agree with that.&lt;/p&gt;

&lt;p&gt;Complex front-end applications need bundlers, API key management, minification and other optimisations, and many more things that make the website better and faster.&lt;/p&gt;

&lt;p&gt;However, most of the sites on the internet are not large platforms. They're personal websites, blogs, online playgrounds for people just discovering the joys of web development. If you're working on a site like that, chances are most of the aspects of the Twelve-Factor App don't even apply to you. So why should the rule about configuration?&lt;/p&gt;

&lt;p&gt;As long as you're using read-only API keys, there is no risk in simply pasting your API key into your Javascript code where you need it. It will be published on your website anyways, so people who really want your API key will find it even if you manage not to put it in your Github repository. So if they can't do anything wrong with the key itself, there's nothing to worry about.&lt;/p&gt;

&lt;p&gt;So go ahead and build that awesome site using a simple .html file and some .js files in a folder. Just remember to use the correct, read-only API keys.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>frontend</category>
      <category>configuration</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Publishing a Rust binary on npm</title>
      <dc:creator>Wouter</dc:creator>
      <pubDate>Mon, 16 Dec 2019 18:25:00 +0000</pubDate>
      <link>https://dev.to/woubuc/publishing-a-rust-binary-on-npm-1lgf</link>
      <guid>https://dev.to/woubuc/publishing-a-rust-binary-on-npm-1lgf</guid>
      <description>&lt;p&gt;Instead of asking your users to install the entire Rust toolchain just to compile your program with cargo, it may be easier to let them install it through npm. Here's how to set it up.&lt;/p&gt;

&lt;p&gt;I recently wrote a CLI tool in Rust, called &lt;a href="https://github.com/woubuc/project-cleanup"&gt;Project Cleanup&lt;/a&gt;. I published it on crates.io, the Rust package manager, so people can install it with &lt;code&gt;cargo install project-cleanup&lt;/code&gt;. Great! It's published! But this is a program that everyone could use, not just Rust developers, so I wanted to provide a way for non-Rust developers to install it.&lt;/p&gt;

&lt;p&gt;These days I mostly write Javascript code so I use npm daily. Npm makes it very easy to install and update global packages, and publishing my Rust program worked surprisingly well. So here's a little guide on how to set it all up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 0: Research
&lt;/h2&gt;

&lt;p&gt;There are several good solutions to publish binaries to npm, but the most common is using &lt;strong&gt;pre-compiled binaries&lt;/strong&gt; that are downloaded as-needed. The npm package will just be a tiny wrapper that downloads the appropriate binary when it's installed. A lot of native packages on npm use a this approach because it's easy to set up and maintain.&lt;/p&gt;

&lt;p&gt;We'll be using a package called &lt;a href="https://github.com/EverlastingBugstopper/binary-install"&gt;binary-install&lt;/a&gt;. It's built by a Rust developer and used for the npm package of &lt;a href="https://github.com/rustwasm/wasm-pack"&gt;wasm-pack&lt;/a&gt;, a popular tool to compile Rust programs to WebAssemly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Building the binaries
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;I implemented cross-compilation for Windows, Linux and Mac OS through Github Actions for Project Cleanup. You can check out the &lt;a href="https://github.com/woubuc/project-cleanup/blob/master/.github/workflows/build.yml"&gt;build workflow&lt;/a&gt; but for this post I'm going to focus mainly on the npm part.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  File structure
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;binary-install&lt;/code&gt; package requires your files to be in a specific structure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your release should be a &lt;code&gt;.tar.gz&lt;/code&gt; archive&lt;/li&gt;
&lt;li&gt;Inside that archive should be a directory, containing the binary&lt;/li&gt;
&lt;li&gt;The archive filename and the directory name should be the same&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So you should end up with something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-program-win64.tar.gz/my-program-win64/my-program.exe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is somewhat of a convention to use when releasing binaries, especially on linux platforms. But it's good to note that &lt;code&gt;binary-install&lt;/code&gt; expects exactly this structure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating the files
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;The following is a simplified version of the build script I use. Adjust paths, filenames and targets where necessary to fit your program.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Compile the binary
&lt;/h4&gt;

&lt;p&gt;First of all, we need to build our Rust program.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo build &lt;span class="nt"&gt;--release&lt;/span&gt; &lt;span class="nt"&gt;--target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;x86_64-pc-windows-gnu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Create the directory structore
&lt;/h4&gt;

&lt;p&gt;Next, create a new directory and copy the compiled binary into that directory. This is the directory that we'll put in our release archive.&lt;/p&gt;

&lt;p&gt;It's best to use a separate directory outside of the &lt;code&gt;target&lt;/code&gt; directory, because there are a lot of other files in there that don't need to end up in our release.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; builds/my-program-win64

&lt;span class="c"&gt;# If you haven't set a target, the path will just be 'target/release/...'&lt;/span&gt;
&lt;span class="nb"&gt;cp &lt;/span&gt;target/x86_64-pc-windows-gnu/release/my-program.exe builds/my-program-win64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. Pack the archive
&lt;/h4&gt;

&lt;p&gt;Now all we need to do is pack it all into a nice &lt;code&gt;.tar.gz&lt;/code&gt; archive.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; builds &lt;span class="nt"&gt;-czvf&lt;/span&gt; my-program-win64.tar.gz my-program-win64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should have a file called &lt;code&gt;my-program-win64.tar.gz&lt;/code&gt; now. Repeat as needed for every target you want to support.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Creating a release
&lt;/h2&gt;

&lt;p&gt;Once you have all your release archives, create a new release on Github. You can do this by creating a tag locally and pushing it to Github, or by creating a release via the web interface. Check out the &lt;a href="https://help.github.com/en/github/administering-a-repository/managing-releases-in-a-repository"&gt;Github documentation&lt;/a&gt; for more help.&lt;/p&gt;

&lt;p&gt;Attach the &lt;code&gt;.tar.gz&lt;/code&gt; files that you created to the release, write some release notes if you want, then click "Publish release" when you're ready.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kVJ4mbwz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/2m8k8c4gwh1w70p6klfz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kVJ4mbwz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/2m8k8c4gwh1w70p6klfz.png" alt="Screenshot of attached binaries in the Github release editor" width="820" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your binaries are ready! Now let's make an npm package that can install them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Making the npm package
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;I like to keep the npm package and the Rust project together in the same repository, but you can also create a separate project for the npm package if you prefer.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Create a new node project and add the &lt;code&gt;binary-install&lt;/code&gt; dependency.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn init &lt;span class="nt"&gt;-y&lt;/span&gt;
yarn add binary-install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://github.com/EverlastingBugstopper/binary-install/tree/master/example"&gt;example project&lt;/a&gt; in the &lt;code&gt;binary-install&lt;/code&gt; repository is very clear and shows us what we need to do — although we're going to make a few tweaks.&lt;/p&gt;

&lt;p&gt;Let's also create a new directory called &lt;code&gt;npm&lt;/code&gt; to put our scripts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;npm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Binary class
&lt;/h3&gt;

&lt;p&gt;If we want to do anything, we first need to create an instance of the &lt;code&gt;Binary&lt;/code&gt; class, provided by the &lt;code&gt;binary-install&lt;/code&gt; package.&lt;/p&gt;

&lt;h4&gt;
  
  
  Get binary
&lt;/h4&gt;

&lt;p&gt;Let's create a function that returns the proper &lt;code&gt;Binary&lt;/code&gt; instance.&lt;/p&gt;

&lt;h6&gt;
  
  
  npm/getBinary.js
&lt;/h6&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Binary&lt;/span&gt; &lt;span class="p"&gt;}&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;binary-install&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getBinary&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;version&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;../package.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;version&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;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://github.com/username/my-program/releases/download/v&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt; &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/my-program-win64.tar.gz`&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;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-program&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="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="nx"&gt;getBinary&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We get the current version from the &lt;code&gt;package.json&lt;/code&gt; file, so users can install a specific version of our program. This means that we have to keep our npm package's version synchronised with our release versions.&lt;/p&gt;

&lt;p&gt;Don't forget to change the values in &lt;code&gt;url&lt;/code&gt; and &lt;code&gt;name&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Multiple platforms
&lt;/h4&gt;

&lt;p&gt;Now you've probably spotted that this will always download the Windows binaries, even on non-Windows platforms. So let's do something about that. We can use the built-in Node.js module &lt;code&gt;os&lt;/code&gt; to get information about the current platform.&lt;/p&gt;

&lt;h6&gt;
  
  
  npm/getBinary.js
&lt;/h6&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Binary&lt;/span&gt; &lt;span class="p"&gt;}&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;binary-install&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;os&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;os&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getPlatform&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;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&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;arch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Windows_NT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;arch&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;win64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Windows_NT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;win32&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Linux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;arch&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;linux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Darwin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;arch&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;macos&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Unsupported platform: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;arch&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getBinary&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;platform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getPlatform&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;version&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;../package.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;version&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;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://github.com/username/my-program/releases/download/v&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt; &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/my-program-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt; &lt;span class="nx"&gt;platform&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.tar.gz`&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;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-program&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="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="nx"&gt;getBinary&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That should do the trick. This function will return the proper &lt;code&gt;Binary&lt;/code&gt; instance for each supported platform. If you have different platform support, or different filenames, you can adjust the values and checks in the &lt;code&gt;getPlatform()&lt;/code&gt; function.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scripts
&lt;/h3&gt;

&lt;p&gt;With our &lt;code&gt;Binary&lt;/code&gt; instance, we can do 3 things: &lt;code&gt;install&lt;/code&gt;, &lt;code&gt;uninstall&lt;/code&gt; and &lt;code&gt;run&lt;/code&gt;. So let's create a script for each of those.&lt;/p&gt;

&lt;h6&gt;
  
  
  npm/run.js
&lt;/h6&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;getBinary&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;./getBinary&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;getBinary&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  npm/install.js
&lt;/h6&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;getBinary&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;./getBinary&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;getBinary&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  npm/uninstall.js
&lt;/h6&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;getBinary&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;./getBinary&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;getBinary&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;uninstall&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It may seem a little excessive to create a separate file for each function, but it's the easiest way to call them from a script in &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Update package.json
&lt;/h4&gt;

&lt;p&gt;Now that we have the js files for these commands, we'll need to call them from our &lt;code&gt;package.json&lt;/code&gt;. We'll install the binary with the &lt;code&gt;postinstall&lt;/code&gt; hook.&lt;/p&gt;

&lt;h6&gt;
  
  
  package.json
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"postinstall"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node npm/install.js"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;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;Next, if our program is already installed and the user installs a new version, we should uninstall the old version first. Let's use the &lt;code&gt;preinstall&lt;/code&gt; hook for that.&lt;/p&gt;

&lt;h6&gt;
  
  
  package.json
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"postinstall"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node npm/install.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;"preinstall"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node npm/uninstall.js"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;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;Once installed, we want the user to be able to run &lt;code&gt;my-program&lt;/code&gt; from anywhere. Luckily, &lt;a href="https://docs.npmjs.com/files/package.json#bin"&gt;npm supports a &lt;code&gt;bin&lt;/code&gt; field&lt;/a&gt; in &lt;code&gt;package.json&lt;/code&gt;. We just need to point it to a script.&lt;/p&gt;

&lt;h6&gt;
  
  
  package.json
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"bin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"my-program"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./npm/run.js"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"postinstall"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node ./npm/install.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;"preinstall"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node ./npm/uninstall.js"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;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;We also need to let the system know that this is an executable script, and to run it with &lt;code&gt;node&lt;/code&gt;. We do this by adding a &lt;a href="https://en.wikipedia.org/wiki/Shebang_(Unix)"&gt;shebang&lt;/a&gt; to the top of the file.&lt;/p&gt;

&lt;h6&gt;
  
  
  npm/run.js
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cp"&gt;#!/usr/bin/env node
&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getBinary&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;./getBinary&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;getBinary&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Shebangs are a Unix concept, but npm will take care of the Windows side for us.&lt;/p&gt;

&lt;h3&gt;
  
  
  First install problem
&lt;/h3&gt;

&lt;p&gt;We're almost done, but there's one more thing. I only learned this after releasing the my npm package, because it's not exactly obvious if you've followed these steps in order.&lt;/p&gt;

&lt;p&gt;When installing locally, the &lt;code&gt;preinstall&lt;/code&gt; script is executed &lt;strong&gt;before&lt;/strong&gt; any dependencies are installed. But our script &lt;code&gt;require()&lt;/code&gt;s a dependency. You can probably see where this is going — another developer who clones the repository and runs &lt;code&gt;yarn install&lt;/code&gt; will get an error that dependencies are missing, and they'll be unable to install those dependencies.&lt;/p&gt;

&lt;p&gt;We'll solve this with a simple &lt;code&gt;try/catch&lt;/code&gt; and swallow the error. After all, if the dependencies are not found it means the package wasn't installed yet, and that means there's no binary to uninstall in the first place.&lt;/p&gt;

&lt;h6&gt;
  
  
  npm/uninstall.js
&lt;/h6&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;getBinary&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&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;getBinary&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;./getBinary&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;getBinary&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;binary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getBinary&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;binary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;binary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uninstall&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;
  
  
  Step 4: Publishing
&lt;/h2&gt;

&lt;p&gt;Now our package is ready to publish. But let's make sure we only publish what's necessary for the npm package to work. We can use the &lt;code&gt;files&lt;/code&gt; property in &lt;code&gt;package.json&lt;/code&gt; to define which files get uploaded to npm. The package.json itself is always included, so we just need to add our scripts in the &lt;code&gt;npm&lt;/code&gt; directory.&lt;/p&gt;

&lt;h6&gt;
  
  
  package.json
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"files"&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;"npm/**/*"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it. Let's publish!&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



</description>
      <category>rust</category>
      <category>npm</category>
      <category>publishing</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Self-documenting is a myth, and how to make your code self-documenting</title>
      <dc:creator>Wouter</dc:creator>
      <pubDate>Sat, 03 Aug 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/woubuc/self-documenting-is-a-myth-and-how-to-make-your-code-self-documenting-3h2n</link>
      <guid>https://dev.to/woubuc/self-documenting-is-a-myth-and-how-to-make-your-code-self-documenting-3h2n</guid>
      <description>&lt;p&gt;Self-documenting code is often presented as a programmer's utopia, where you don't need to write comments at all! But code can never be entirely self-documenting. Here are some tips on how to clean up your code and write fewer comments without losing sight of the big picture.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is self-documenting code
&lt;/h2&gt;

&lt;p&gt;In order to write code, you have to understand the surrounding code. And in order to understand it, you need to read it. Often repeatedly and frequently. So it's in everyone's best interest that this code is clear, concise and properly documented.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Self-documenting code&lt;/strong&gt; is a goal that a lot of developers (including myself) set for themselves at least once. For most people it means you should write clean, well-structured code that makes it immediately obvious what's going on, so you don't need to write comments explaining it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Well actually...
&lt;/h3&gt;

&lt;p&gt;You can write the best, cleanest, most well-structured code anyone has ever seen, but here's the truth: &lt;strong&gt;You'll still need to write comments and document your code&lt;/strong&gt;. You won't have to write &lt;em&gt;as many&lt;/em&gt; comments, but you can't stop writing comments altogether.&lt;/p&gt;

&lt;h3&gt;
  
  
  Three questions
&lt;/h3&gt;

&lt;p&gt;When someone reads what you wrote, for them to build the mental modal they need to understand it, your code needs to answer three questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What&lt;/strong&gt; is the goal of this code?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How&lt;/strong&gt; is it achieving that goal?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why&lt;/strong&gt; does it achieve that goal in this way?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's take a little piece of &lt;em&gt;less-than-ideal&lt;/em&gt; code, examine why it's written like that, and try to improve it so it answers all three questions.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: The code samples are written in Javascript/Typescript, but the theory should be applicable for any language&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;While experimenting with a new feature, you're just trying to get something working. So it can be tempting to think "I'll clean this up later" and write something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="kd"&gt;get&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;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAll&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;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Only you don't clean it up because deadlines are looming and you have ten more things to finish before tomorrow's standup. And so that piece of code sits in your codebase for seven months, until another developer — let's call him Steve — needs to update something in that file.&lt;/p&gt;

&lt;p&gt;After reading the function for the first time, Steve will probably have several questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What&lt;/strong&gt; is this function getting?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What&lt;/strong&gt; is in &lt;code&gt;arr&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why&lt;/strong&gt; does it map to &lt;code&gt;name&lt;/code&gt;?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By parsing what's happening, Steve can deduce a partial answer to these questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The variable &lt;code&gt;arr&lt;/code&gt; must be an array, given its name and the fact that &lt;code&gt;arr.map()&lt;/code&gt; is used.&lt;/li&gt;
&lt;li&gt;The values in &lt;code&gt;arr&lt;/code&gt; must have a property called &lt;code&gt;name&lt;/code&gt; since it is mapped.&lt;/li&gt;
&lt;li&gt;The function returns an array.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, Steve is trying to deduce the &lt;strong&gt;what&lt;/strong&gt; and the &lt;strong&gt;why&lt;/strong&gt; based on the only thing he has: the &lt;strong&gt;how&lt;/strong&gt;. This happens a lot, in all types of codebases, and most developers don't even think twice about it. But in the end, the time and energy you spent parsing this kind of code adds up and takes away from your time working on the code.&lt;/p&gt;

&lt;p&gt;So how can we make it easier on Steve, so he can understand what's going on at a single glance?&lt;/p&gt;

&lt;h3&gt;
  
  
  Add comments
&lt;/h3&gt;

&lt;p&gt;One solution would be to add some comments to explain what's going on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
* Gets the names of all participants from the database
*/&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Load the participants from the database&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAll&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Map to get just the participant's names&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It has gotten a little clearer already, but adding comments is exactly what we wanted to avoid with our self-documenting code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Name those variables
&lt;/h3&gt;

&lt;p&gt;Instead of adding comments, how about we change the names of the variables to reflect what they mean?&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;getParticipantNames&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;participants&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAllParticipants&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;participants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now we have communicated essentially the same thing as before, but we didn't need all those comments. &lt;strong&gt;Properly naming your variables&lt;/strong&gt; is one of the cornerstones of self-documenting code, because they communicate exactly &lt;strong&gt;what&lt;/strong&gt; they represent.&lt;/p&gt;

&lt;p&gt;Note how I still used a short variable &lt;code&gt;p&lt;/code&gt; in the &lt;code&gt;participants.map()&lt;/code&gt; function, since it's abundantly clear from the context that it will contain the participant.&lt;/p&gt;

&lt;p&gt;So with these changes to the variable names, we've answered our original questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;&lt;strong&gt;What&lt;/strong&gt; is this function getting?&lt;/em&gt; It gets the names of the participants.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;&lt;strong&gt;What&lt;/strong&gt; is in &lt;code&gt;arr&lt;/code&gt;?&lt;/em&gt; The participant entities.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;&lt;strong&gt;Why&lt;/strong&gt; does it map to &lt;code&gt;name&lt;/code&gt;?&lt;/em&gt; Because we only need the name&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Steve will find it much easier next time he has to read our code!&lt;/p&gt;

&lt;h3&gt;
  
  
  Why?
&lt;/h3&gt;

&lt;p&gt;Another question you could ask is a little more far-fetched and doesn't concern this function specifically, but I'll ask it anyway: &lt;strong&gt;Why&lt;/strong&gt; is there no function called &lt;code&gt;database.getAllParticipantNames()&lt;/code&gt;, to query just the names from the database (instead of all this other data we don't need)?&lt;/p&gt;

&lt;p&gt;There could be a million different technical reasons for this, but for this example let's say that the database queries are cached. This means that when the query runs, the received data is stored in memory for a little while so subsequent calls don't need to make another roundtrip to the database. So using the same query here is actually an optimisation, even if we get too much data from the call.&lt;/p&gt;

&lt;p&gt;This optimisation is an example of something you can't possibly communicate using code alone. As it turns out, purely "self-documenting" code is simply insufficient to paint the whole picture. So we will need &lt;em&gt;some&lt;/em&gt; comments after all.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;getParticipantNames&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Because queries are cached, using the `allParticipants` query &lt;/span&gt;
    &lt;span class="c1"&gt;// prevents another roundtrip to the database&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;participants&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAllParticipants&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;participants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With this, we've made the &lt;strong&gt;Why&lt;/strong&gt; even more complete. We needed comments to fully document the code, but this code can still be considered "self-documenting".&lt;/p&gt;

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

&lt;p&gt;There is one last question remaining, one asked not by Steve who has to look at your function, but rather by Tom who has to use it in another part of the codebase: &lt;strong&gt;What&lt;/strong&gt; is the return type of this function?&lt;/p&gt;

&lt;p&gt;The best solution for that is type annotations. Statically typed languages like Java, C# or Rust don't need any additional work since they require explicit type information to work. But dynamically typed languages like Javascript and Python don't have this luxury. Luckily, most of these dynamically typed languages have solutions for (optional) typing. Javascript even has several — I've worked with &lt;a href="https://devhints.io/jsdoc"&gt;JSDoc comments&lt;/a&gt;, &lt;a href="https://flow.org/"&gt;Flow types&lt;/a&gt; and &lt;a href="https://www.typescriptlang.org/"&gt;Typescript&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We've already tried the full JSDoc comment above, but all that's necessary to annotate the return type is an &lt;code&gt;@returns&lt;/code&gt; statement in the comment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
* @returns {string[]}
*/&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getParticipantNames&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Because queries are cached, using the `allParticipants` query &lt;/span&gt;
    &lt;span class="c1"&gt;// prevents another roundtrip to the database&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;participants&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAllParticipants&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;participants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Typescript and Flowtype use syntactic notations rather than comments. Note the &lt;code&gt;: string[]&lt;/code&gt; after the function name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getParticipantNames&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Because queries are cached, using the `allParticipants` query &lt;/span&gt;
    &lt;span class="c1"&gt;// prevents another roundtrip to the database&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;participants&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAllParticipants&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;participants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;My personal favourite is Typescript. It helps you create clean code with strict interfaces and it makes refactoring a whole lot easier when you need to. I use Typescript in nearly all of my projects.&lt;/p&gt;

&lt;p&gt;However, it's important to note that adding Typescript to a project is generally not a decision to take lightly — especially if you have an already developed codebase — so be sure to consider the ramifications before you start. JSDoc is almost always the easiest choice to get started typing your code because it's based on comment blocks, which have no impact on the code itself.&lt;/p&gt;

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

&lt;p&gt;Let's extract the three most important rules from what we've seen in this post, based on the three questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use clear and consistent &lt;strong&gt;naming, types and function signatures&lt;/strong&gt; to communicate &lt;strong&gt;what&lt;/strong&gt; the goal of each piece of code is.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;well-structured code&lt;/strong&gt; to show &lt;strong&gt;how&lt;/strong&gt; you're going about achieving the goal.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;comments&lt;/strong&gt; to explain &lt;strong&gt;why&lt;/strong&gt; you're doing things a certain way, especially if that way may be non-obvious.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last one is the hardest for a lot of developers because the &lt;strong&gt;why&lt;/strong&gt; is usually obvious while you're writing the code. But take a moment to think of the developers who will need to look at your code months or even years after you wrote it. They'll be grateful.&lt;/p&gt;

&lt;p&gt;Make Steve happy. Document your self-documenting code.&lt;/p&gt;

</description>
      <category>bestpractices</category>
      <category>code</category>
      <category>documentation</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Choosing a static site generator</title>
      <dc:creator>Wouter</dc:creator>
      <pubDate>Sun, 28 Jul 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/woubuc/choosing-a-static-site-generator-126k</link>
      <guid>https://dev.to/woubuc/choosing-a-static-site-generator-126k</guid>
      <description>&lt;p&gt;When I started building my blog, I knew from the start that I wanted to use a static site generator with markdown files. But I had no idea which SSG I should use. I've heard about them, and I know they've gained in popularity in the past couple of years, but until now when I made a static site it was just a folder of HTML files. But now I decided to do it &lt;em&gt;properly&lt;/em&gt;, since I was going to build a whole new blog. So I started searching.&lt;/p&gt;

&lt;p&gt;After a few Google searches, I found a website called &lt;a href="https://www.staticgen.com/"&gt;StaticGen.com&lt;/a&gt; which lists a lot of static site generators (I didn't even know there were that many!). The site also provides filters to search for exactly the type of SSG you want. Of course, since I was new at all this, I had no idea what I needed from a static site generator, so I started with the top entries on the list.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I'm going to list good and bad things about each of the tools I tried. These are just my initial experiences based on working with them for a short time. Your mileage may vary.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Jekyll
&lt;/h2&gt;

&lt;p&gt;The 'classic' static site generator, &lt;a href="https://jekyllrb.com/"&gt;Jekyll&lt;/a&gt; has been around for ages, it's stable and boring. A great choice for a writer or someone who just needs their site online. A little less &lt;em&gt;fun&lt;/em&gt; for someone who wants to use their site as a personal playground for experimenting (like me).&lt;/p&gt;

&lt;h4&gt;
  
  
  I liked
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Stable, battle-tested and production-ready&lt;/li&gt;
&lt;li&gt;Can deploy directly to Github pages&lt;/li&gt;
&lt;li&gt;Big community, lots of info to be found and most problems have been solved before&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  I didn't like
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Liquid templates have limited logic (also I'm not a fan of the &lt;code&gt;{% %}&lt;/code&gt; syntax)&lt;/li&gt;
&lt;li&gt;It requires Ruby, GCC and Make, which are a bit of a headache to set up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the end, I didn't go with Jekyll because of its limited support for custom logic or functionality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hugo
&lt;/h2&gt;

&lt;p&gt;Next on the list is &lt;a href="https://gohugo.io/"&gt;Hugo&lt;/a&gt;. This one is built in Go, another language and toolset that I don't use, but is downloadable as a simple binary.&lt;/p&gt;

&lt;h4&gt;
  
  
  I liked
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;It's fast, especially compared to Javascript-based alternatives&lt;/li&gt;
&lt;li&gt;Their system of page resources, while not always properly documented, works very nicely and intuitively&lt;/li&gt;
&lt;li&gt;Resource pipes with transform functions are implemented very nicely&lt;/li&gt;
&lt;li&gt;You can download a binary instead of compiling Hugo from source&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  I didn't like
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;I found the template syntax to be just awful if you want to do anything beyond printing variables and simple if-statements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unfortunately, that one dislike was a dealbreaker for me. If it wasn't for the clumsy and messy templates, I probably would've stuck with Hugo. But the way I had to interpolate variables, the function calls without parentheses, and the fact that the template compiler doesn't support line breaks in code blocks, made for the worst code mess I've ever seen.&lt;/p&gt;

&lt;p&gt;A short example of what this means:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;{{ $css := resources.Get "css/pageStyles/post.scss" | resources.ExecuteAsTemplate (printf "page-%s.scss" .File.UniqueID) .Params.colour | resources.ToCSS (dict "outputStyle" "compressed") }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This line gets an SCSS file, fills the template tags inside it with a variable, and then renders it to CSS. On their own, these functions aren't that bad. But put together in this way the whole thing becomes difficult to visually grok what's going on and impossible to debug or change without a lot of trial-and-error.&lt;/p&gt;

&lt;p&gt;Now I'm sure there must be good reasons why the template syntax is like this, but there were so many little annoyances and inconveniences that I simply gave up after building about two-thirds of the blog in Hugo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gatsby
&lt;/h2&gt;

&lt;p&gt;The next step on my search was &lt;a href="https://www.gatsbyjs.org/"&gt;Gatsby&lt;/a&gt;. As a front-end developer first and foremost, the concept of using &lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt; — a front-end framework — to build a front-end website, sounded logical. Next to the pre-rendered static HTML, Gatsby outputs a React-powered bundle of Javascript to turn the rest of the site into a progressive web app (&lt;strong&gt;PWA&lt;/strong&gt; for short). This makes for a fast initial load time because of the static HTML, and then even faster navigation due to the powers of the PWA.&lt;/p&gt;

&lt;h4&gt;
  
  
  I liked
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Static sites for front-end developers&lt;/li&gt;
&lt;li&gt;Generates static HTML pages for SEO, and then hydrates those pages with the client-side Javascript bundle&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  I didn't like
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;I'm not a big fan of React&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In any case, I like the concept of Gatsby, but I'm more partial to Vue and I have a lot more experience with it, so I decided to look for something similar in Vue-land.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gridsome
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://gridsome.org/"&gt;Gridsome&lt;/a&gt; is essentially the same as Gatsby, but it replaces React with &lt;a href="https://vuejs.org/"&gt;Vue.js&lt;/a&gt;, which is pretty much exactly what I was looking for at this point.&lt;/p&gt;

&lt;p&gt;I checked out some other Vue-based alternatives, specifically &lt;a href="https://nuxtjs.org/"&gt;Nuxt.js&lt;/a&gt; (aimed at server-rendered applications) and &lt;a href="https://vuepress.vuejs.org/"&gt;Vuepress&lt;/a&gt; (for documentation sites), but Gridsome seemed the most geared towards building a static blog.&lt;/p&gt;

&lt;h4&gt;
  
  
  I liked
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Everything good about Gatsby, but with Vue instead of React.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  I didn't like
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;It's relatively new and hasn't got a large community behind it yet, so finding answers to specific questions can be a little difficult.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Gridsome is pretty early in development and is still finding itself, but I found the latest version at this time (v0.6.7) to be sufficiently stable. They've got some serious work to do before it could be considered production-ready — I especially found error-handling to be lacking during my initial tests — but overall it has worked well for me. Gridsome has allowed me to use my Vue experience to build a nice looking blog with relatively little effort.&lt;/p&gt;

&lt;h3&gt;
  
  
  Side note: GraphQL
&lt;/h3&gt;

&lt;p&gt;Like Gatsby, Gridsome uses &lt;a href="https://graphql.org/"&gt;GraphQL&lt;/a&gt; to describe which page data to load. I've seen GraphQL get a lot of praise from developers online, but I hadn't actually worked with it until now. The ideas behind GraphQL sound very good and I could definitely see it work, but my practical experience is that the queries often feel a little &lt;em&gt;bloated&lt;/em&gt; and excessively verbose at times. On my post details page, I just want &lt;strong&gt;all&lt;/strong&gt; the properties from my &lt;code&gt;Post&lt;/code&gt; type, why do I need to write them out manually?&lt;/p&gt;

&lt;p&gt;I also haven't figured out sorting and filtering yet, so I've got some learning to do still. But by looking at the Gridsome starters and examples I've managed to get my blog up and running.&lt;/p&gt;

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

&lt;p&gt;All static site generators have pros and cons, and I can't recommend enough that you just try them all out for a few hours to see how they work. Most of the time you'll figure out very quickly if the tool's workflow matches yours or not, and then you can move on to the next one.&lt;/p&gt;

&lt;p&gt;The best resource I found to search for SSGs is &lt;a href="https://www.staticgen.com/"&gt;StaticGen.com&lt;/a&gt;. If you're trying to find a good static site generator, this is the best place to start your search. Not every tool is for everyone, but there's bound to be one that works &lt;em&gt;just right&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In any case, so far I'm very happy with my choice of Gridsome. I plan to do a write-up later about my experience building a site with it, but I decided to keep this post just about the selection process.&lt;/p&gt;

</description>
      <category>gridsome</category>
      <category>graphql</category>
      <category>frontend</category>
      <category>ssg</category>
    </item>
    <item>
      <title>Making a background music player in Godot</title>
      <dc:creator>Wouter</dc:creator>
      <pubDate>Sat, 27 Apr 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/woubuc/a-background-music-player-in-godot-h6e</link>
      <guid>https://dev.to/woubuc/a-background-music-player-in-godot-h6e</guid>
      <description>&lt;p&gt;&lt;em&gt;This is my first blog post. If you notice anything out of the ordinary (styling, structure, content, anything), let me know so I can fix it and learn for my next posts!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are multiple ways to play and manage music tracks for your game but most are linked to your scene. In this tutorial we'll make an autoload music manager that will allow to you play background music independent from your game scenes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we need
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Godot 3.1
&lt;/h3&gt;

&lt;p&gt;You can use another version of Godot, but this tutorial is written with Godot 3.1.&lt;/p&gt;

&lt;p&gt;Download Godot at &lt;a href="https://godotengine.org" rel="noopener noreferrer"&gt;godotengine.org&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Music
&lt;/h3&gt;

&lt;p&gt;Since we're making a music player, you'll need two music tracks. Godot supports .wav and .ogg formats, but they recommend using &lt;a href="https://docs.godotengine.org/en/3.1/getting_started/workflow/assets/importing_audio_samples.html" rel="noopener noreferrer"&gt;.ogg for background music&lt;/a&gt; because it takes up a lot less disk space than .wav.&lt;/p&gt;

&lt;p&gt;If you don't have music, you can find some nice free tracks at &lt;a href="https://incompetech.com/music/royalty-free/music.html" rel="noopener noreferrer"&gt;incompetech&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Autoload
&lt;/h2&gt;

&lt;p&gt;We're going to use the &lt;strong&gt;autoload&lt;/strong&gt; feature in Godot. This lets us add static nodes to the scene tree that will always exist, independent of our game scenes.&lt;/p&gt;

&lt;p&gt;This is perfect to keep our music playing, even if we change the scene.&lt;/p&gt;

&lt;p&gt;If you want to learn more about autoload you can &lt;a href="https://docs.godotengine.org/en/3.1/getting_started/step_by_step/singletons_autoload.html" rel="noopener noreferrer"&gt;check out the Godot docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Our project will consist of 3 scenes: &lt;strong&gt;Scene1&lt;/strong&gt; and &lt;strong&gt;Scene2&lt;/strong&gt; will be our regular game scenes, and we'll add some buttons to them to manage the music.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MusicController&lt;/strong&gt; will be our special autoload scene. We'll add some custom functions to this scene so that we can easily play our music from anywhere in our game.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scene 1
&lt;/h3&gt;

&lt;p&gt;Create a new scene and call it &lt;code&gt;Scene1&lt;/code&gt;. Then add &lt;strong&gt;1 label and 3 buttons&lt;/strong&gt; as in the screenshot below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsvmh63dl3pmnda6vszkf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsvmh63dl3pmnda6vszkf.png" alt="Screenshot of scene 1, containing a label saying 'This is scene 1', a button labeled 'Go to scene 2', another button labeled 'Play track 1', and a third button labeled 'Stop music'." width="800" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add a script to the root node of the scene, and connect the &lt;code&gt;pressed()&lt;/code&gt; events of the three buttons to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Scene1.gd&lt;/span&gt;

&lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Control&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_GoToScene2Button_pressed&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;get_tree&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;change_scene&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"res://Scene2.tscn"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_PlayTrack1Button_pressed&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt; &lt;span class="c1"&gt;# Replace with function body.&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_StopMusicButton_pressed&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt; &lt;span class="c1"&gt;# Replace with function body.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Scene 2
&lt;/h3&gt;

&lt;p&gt;Now make another scene and call it &lt;code&gt;Scene2&lt;/code&gt;. Add &lt;strong&gt;1 label and 2 buttons&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foqrrwpefxsc0lo094aer.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foqrrwpefxsc0lo094aer.png" alt="Screenshot of scene 2, containing a label saying 'This is scene 2', a button labeled 'Go to scene 1', and a second button labeled 'Play track 2'." width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, add a script to the root node of the scene and connect the &lt;code&gt;pressed()&lt;/code&gt; events of both buttons to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Scene2.gd&lt;/span&gt;

&lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Control&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_GoToScene1Button_pressed&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;get_tree&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;change_scene&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"res://Scene1.tscn"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_PlayTrack2Button_pressed&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt; &lt;span class="c1"&gt;# Replace with function body.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Music Controller
&lt;/h2&gt;

&lt;p&gt;Now it's time to create our music controller scene.&lt;/p&gt;

&lt;p&gt;Create a new scene and call it &lt;code&gt;MusicController&lt;/code&gt;. Add &lt;strong&gt;1 AudioStreamPlayer&lt;/strong&gt; to play our music.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnkoi28jv4bye6lt0tjaj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnkoi28jv4bye6lt0tjaj.png" alt="Screenshot of the music controller scene, containing an AudioStreamPlayer node" width="800" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add a script to the root node of the scene and add the following code to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="c1"&gt;# MusicController.gd&lt;/span&gt;

&lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Control&lt;/span&gt;

&lt;span class="c1"&gt;# Load the music player node&lt;/span&gt;
&lt;span class="k"&gt;onready&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;_player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;AudioStreamPlayer&lt;/span&gt;

&lt;span class="c1"&gt;# Calling this function will load the given track, and play it&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;track_url&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="c1"&gt;# Calling this function will stop the music&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you see, we have defined 2 functions: &lt;code&gt;play()&lt;/code&gt; and &lt;code&gt;stop()&lt;/code&gt;. We'll be using these to play and stop the music as needed from our game scenes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Side note:&lt;/strong&gt; wondering what that &lt;code&gt;track_url : String&lt;/code&gt; syntax is? It's a new feature in Godot 3.1 called &lt;a href="https://godotengine.org/article/optional-typing-gdscript" rel="noopener noreferrer"&gt;optional typing&lt;/a&gt;. It means we expect that function parameter to be a string, and the editor should warn us if we call that function with anything that isn't a string.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stop()
&lt;/h3&gt;

&lt;p&gt;Let's begin with the easiest function to implement. The &lt;code&gt;stop()&lt;/code&gt; function simply needs to stop the music - hence its name.&lt;/p&gt;

&lt;p&gt;Checking the &lt;a href="https://docs.godotengine.org/en/3.1/classes/class_audiostreamplayer.html#class-audiostreamplayer-method-stop" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;, we can see that AudioStreamPlayer has a &lt;code&gt;stop()&lt;/code&gt; method, so all we need to do is call that method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;_player&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Play()
&lt;/h3&gt;

&lt;p&gt;This one is a little more involved. When the &lt;code&gt;play()&lt;/code&gt; function is called, we need to do 3 things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Stop the previous track&lt;/li&gt;
&lt;li&gt;Load the new track from the &lt;code&gt;track_url&lt;/code&gt; function parameter&lt;/li&gt;
&lt;li&gt;Start playing the new track.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Luckily, it's not difficult to do any of these things with GDScript.&lt;/p&gt;

&lt;h4&gt;
  
  
  Stop
&lt;/h4&gt;

&lt;p&gt;To stop, the previous track, we simply call our own &lt;code&gt;stop()&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Load
&lt;/h4&gt;

&lt;p&gt;Next, we need to load the new track. GDScript makes this very easy with the &lt;code&gt;load()&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;new_track&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;track_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Update
&lt;/h4&gt;

&lt;p&gt;Now we have to update the player and tell it to use the track we just loaded.&lt;/p&gt;

&lt;p&gt;Returning to the &lt;a href="https://docs.godotengine.org/en/3.1/classes/class_audiostreamplayer.html#class-audiostreamplayer-property-stream" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;, we can see that AudioStreamPlayer has a property &lt;code&gt;stream&lt;/code&gt; that we can set.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="n"&gt;_player&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_track&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Play
&lt;/h4&gt;

&lt;p&gt;Now all we have to do is start the track.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="n"&gt;_player&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Everything together
&lt;/h4&gt;

&lt;p&gt;Our MusicController script looks like this now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="c1"&gt;# MusicController.gd&lt;/span&gt;

&lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Control&lt;/span&gt;

&lt;span class="c1"&gt;# Load the music player node&lt;/span&gt;
&lt;span class="k"&gt;onready&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;_player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;AudioStreamPlayer&lt;/span&gt;

&lt;span class="c1"&gt;# Calling this function will load the given track, and play it&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;track_url&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;track_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;_player&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;
    &lt;span class="n"&gt;_player&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Calling this function will stop the music&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;_player&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Set Up Autoload
&lt;/h2&gt;

&lt;p&gt;The last thing we need to do is tell Godot to actually load our  autoload scene.&lt;/p&gt;

&lt;p&gt;Go to the &lt;code&gt;Project&lt;/code&gt; menu and open &lt;code&gt;Project Settings&lt;/code&gt;. Then click on the &lt;code&gt;AutoLoad&lt;/code&gt; tab. This is where we can configure our autoload scripts.&lt;/p&gt;

&lt;p&gt;An autoload script always has a &lt;strong&gt;path&lt;/strong&gt; that points to the resource (either a script or a scene) that should be loaded, and a &lt;strong&gt;name&lt;/strong&gt; that you can use to refer to it in your code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Side note:&lt;/strong&gt; You can also access autoload nodes through the scene tree. See the &lt;a href="https://docs.godotengine.org/en/3.1/getting_started/step_by_step/singletons_autoload.html" rel="noopener noreferrer"&gt;autoload documentation&lt;/a&gt; for more information.&lt;/p&gt;

&lt;p&gt;To add our &lt;code&gt;MusicController&lt;/code&gt; scene to the autoload settings, select it in the &lt;strong&gt;Path&lt;/strong&gt; field. You can look for it with a file browser by clicking the little button next to the field.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Node name&lt;/strong&gt; should automatically get filled based on the name of the scene. You can change this if you want, but we'll leave it for now.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhk9cg13h8rhoqm0ysotl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhk9cg13h8rhoqm0ysotl.png" alt="Screenshot of the autoload manager, with the path to the music controller scene selected" width="800" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click the &lt;strong&gt;Add&lt;/strong&gt; button to add the autoload scene to the project. It will appear in the list below.&lt;/p&gt;

&lt;p&gt;Every autoload script has some buttons that allow you to edit or remove the autoload script, and to change the order in which they are loaded. They also have an &lt;strong&gt;enabled&lt;/strong&gt; checkbox so you can temporarily disable an autoload script without having to delete it and re-add it if you want to test something.&lt;/p&gt;

&lt;p&gt;Make sure &lt;strong&gt;enabled&lt;/strong&gt; is checked for our new MusicController autoload script.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqge30hm4800spuzvm6q1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqge30hm4800spuzvm6q1.png" alt="Screenshot of the autoload manager, with the path to the music controller scene added and enabled" width="800" height="139"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that's it! Our autoload scene has been added and is now active in the project! This means we can access the &lt;code&gt;play()&lt;/code&gt; and &lt;code&gt;stop()&lt;/code&gt; functions we made through the global &lt;code&gt;MusicController&lt;/code&gt; variable. So let's try that out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Your Autoload Functions
&lt;/h2&gt;

&lt;p&gt;In the &lt;code&gt;Scene1&lt;/code&gt; and &lt;code&gt;Scene2&lt;/code&gt; scripts, we can now call the functions we need in the pressed events. The scripts will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Scene1.gd&lt;/span&gt;

&lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Control&lt;/span&gt;

&lt;span class="c1"&gt;# Switch to the other scene&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_GoToScene2Button_pressed&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;get_tree&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;change_scene&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"res://Scene2.tscn"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Load and play track 1&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_PlayTrack1Button_pressed&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;MusicController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"res://tracks/track 1.ogg"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Stop the music&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_StopMusicButton_pressed&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;MusicController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Scene2.gd&lt;/span&gt;

&lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Control&lt;/span&gt;

&lt;span class="c1"&gt;# Switch to the other scene&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_GoToScene1Button_pressed&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;get_tree&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;change_scene&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"res://Scene1.tscn"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Load and play track 2&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_PlayTrack2Button_pressed&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;MusicController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"res://tracks/track 2.ogg"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't forget to set the correct paths to your tracks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Done
&lt;/h2&gt;

&lt;p&gt;Now we can run the game and enjoy the music. Notice how it doesn't stop playing, even if you change to the other scene!&lt;/p&gt;

&lt;p&gt;That's what autoload is all about.&lt;/p&gt;

</description>
      <category>godot</category>
      <category>gamedev</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
