<?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: Mike Eason</title>
    <description>The latest articles on DEV Community by Mike Eason (@mikeeason).</description>
    <link>https://dev.to/mikeeason</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%2F259153%2F53328c12-17ba-4058-9dee-fe943f022b0d.png</url>
      <title>DEV Community: Mike Eason</title>
      <link>https://dev.to/mikeeason</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mikeeason"/>
    <language>en</language>
    <item>
      <title>Supercharge your API with Compression</title>
      <dc:creator>Mike Eason</dc:creator>
      <pubDate>Wed, 14 Apr 2021 10:12:09 +0000</pubDate>
      <link>https://dev.to/mikeeason/supercharge-your-api-with-compression-4ikp</link>
      <guid>https://dev.to/mikeeason/supercharge-your-api-with-compression-4ikp</guid>
      <description>&lt;p&gt;Performance is critical to any API, taking the time to reduce API response times to be as low as possible is absolutely worth the effort.&lt;/p&gt;

&lt;p&gt;Take a look at this example API request in &lt;a href="https://solaris.games" rel="noopener noreferrer"&gt;Solaris&lt;/a&gt;:&lt;/p&gt;

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

&lt;p&gt;The API response is &lt;code&gt;44.6kB&lt;/code&gt; with a time of &lt;code&gt;584ms&lt;/code&gt;. This isn't &lt;em&gt;terrible&lt;/em&gt; but could be &lt;strong&gt;smaller and faster&lt;/strong&gt; with compression.&lt;/p&gt;

&lt;h3&gt;
  
  
  Express Compression
&lt;/h3&gt;

&lt;p&gt;If you're familiar with &lt;strong&gt;Node.js&lt;/strong&gt; you have probably used &lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;Express.js&lt;/a&gt; at some time or another.&lt;/p&gt;

&lt;p&gt;Express is extensible and has a large number of &lt;strong&gt;middleware&lt;/strong&gt; libraries that can be bolted on. One such library is &lt;a href="https://github.com/expressjs/compression" rel="noopener noreferrer"&gt;compression&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To install &lt;code&gt;compression&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;npm install compression
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then its a case of simply calling the Express &lt;code&gt;use&lt;/code&gt; function to register the middleware 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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&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;express&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;compression&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&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;compression&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

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

&lt;span class="c1"&gt;// Compress all responses&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;compression&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="c1"&gt;// Byte threshold (0 means compress everything)&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;Easy, right? Now calling the same API endpoint we get this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fktfqig27f6zk2pq9jror.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fktfqig27f6zk2pq9jror.PNG" alt="The same API response, but smaller and faster"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The response is now &lt;code&gt;8.1kB&lt;/code&gt; and a time of &lt;code&gt;101ms&lt;/code&gt;, that's over &lt;strong&gt;5x faster&lt;/strong&gt; than before!&lt;/p&gt;

&lt;h4&gt;
  
  
  Compressing Specific Responses
&lt;/h4&gt;

&lt;p&gt;With the above code, we'll be compressing &lt;strong&gt;all&lt;/strong&gt; responses, if for some reason you'd like to &lt;strong&gt;not&lt;/strong&gt; compress a response from the API then we can override the &lt;code&gt;filter&lt;/code&gt; function 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="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;compression&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-no-compression&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;// don't compress responses if this request header is present&lt;/span&gt;
            &lt;span class="k"&gt;return&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="c1"&gt;// fallback to standard compression&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;compression&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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;Any API request with the &lt;code&gt;x-no-compression&lt;/code&gt; header will be ignored.&lt;/p&gt;

&lt;p&gt;And that's it, your API will now serve compressed responses and should now be performing even better than before!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;In my spare time I develop an open source strategy game called **Solaris&lt;/em&gt;&lt;em&gt;, &lt;a href="https://solaris.games" rel="noopener noreferrer"&gt;check it out&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>performance</category>
      <category>compression</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How I migrated my development environment to a Raspberry Pi</title>
      <dc:creator>Mike Eason</dc:creator>
      <pubDate>Mon, 12 Apr 2021 14:39:19 +0000</pubDate>
      <link>https://dev.to/mikeeason/how-i-migrated-my-development-environment-to-a-raspberry-pi-1olg</link>
      <guid>https://dev.to/mikeeason/how-i-migrated-my-development-environment-to-a-raspberry-pi-1olg</guid>
      <description>&lt;p&gt;In my spare time I develop an open source strategy game called &lt;strong&gt;Solaris&lt;/strong&gt;, &lt;a href="https://solaris.games" rel="noopener noreferrer"&gt;check it out&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One of the problems with software development is that you need to set up a development environment on every device that you code on, also there can be differences between dev and production which often lead to unforeseen issues.&lt;/p&gt;

&lt;p&gt;An ideal solution would be to be able to develop on &lt;em&gt;any&lt;/em&gt; device without having to go through a long setup process other than installing VS Code (even this is optional as you will see later) on my development machine and have all of the code and apps hosted on a &lt;strong&gt;remote server&lt;/strong&gt;. In this case, a Raspberry Pi.&lt;/p&gt;

&lt;h4&gt;
  
  
  Introducing the Raspberry Pi
&lt;/h4&gt;

&lt;p&gt;The &lt;a href="https://www.raspberrypi.org/" rel="noopener noreferrer"&gt;Raspberry Pi&lt;/a&gt; is an awesome little device capable of a lot of different tasks, like most tinkerers I have a few lying around doing nothing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://solaris.games" rel="noopener noreferrer"&gt;Solaris&lt;/a&gt; runs on Ubuntu Server, the Pi is the perfect candidate to mimic production as it can run the same software in an almost identical environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Plan
&lt;/h3&gt;

&lt;p&gt;The end result of this exercise will be set up the development environment to be &lt;strong&gt;as close as possible&lt;/strong&gt; to what runs in production:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install everything required to run Solaris.&lt;/li&gt;
&lt;li&gt;Run the client and server applications in dev mode.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;Visual Studio Code&lt;/strong&gt; with &lt;code&gt;ssh&lt;/code&gt; to edit files and debug the applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Pi Installation and Setup
&lt;/h4&gt;

&lt;p&gt;The setup for Ubuntu running on the Pi is super simple. Using the &lt;a href="https://www.raspberrypi.org/blog/raspberry-pi-imager-imaging-utility/" rel="noopener noreferrer"&gt;Pi imager software&lt;/a&gt;, I just chose &lt;strong&gt;Ubuntu Server&lt;/strong&gt; and using the &lt;a href="https://www.raspberrypi.org/blog/raspberry-pi-imager-update-to-v1-6/" rel="noopener noreferrer"&gt;advanced options&lt;/a&gt;, set up the hostname, WiFi and SSH there and then. There was no need to even plug in a keyboard and monitor once this installation was complete, just insert the SD card, power the Pi and SSH in from another machine for the rest of the setup process.&lt;/p&gt;

&lt;h4&gt;
  
  
  Setting Up Node and MongoDB
&lt;/h4&gt;

&lt;p&gt;Solaris requires &lt;strong&gt;Node.js&lt;/strong&gt; and &lt;strong&gt;MongoDB&lt;/strong&gt; to run, it was straightforward to get these running as they are very well supported and documented.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/" rel="noopener noreferrer"&gt;MongoDB installation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/nodesource/distributions/blob/master/README.md#debinstall" rel="noopener noreferrer"&gt;Node.js installation&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next step was to &lt;code&gt;git clone&lt;/code&gt; the repository down and walk through the steps in the &lt;a href="https://github.com/mike-eason/solaris#readme" rel="noopener noreferrer"&gt;README&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git clone https://github.com/mike-eason/solaris.git&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Setting Up Apps and Services
&lt;/h4&gt;

&lt;p&gt;The Node applications will be managed on the server by &lt;a href="https://pm2.keymetrics.io/" rel="noopener noreferrer"&gt;PM2&lt;/a&gt;. After installing &lt;code&gt;pm2&lt;/code&gt; the setup is easy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API - &lt;code&gt;pm2 start ~/solaris/server/api/index.js --name solaris-api --watch&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Server jobs - &lt;code&gt;pm2 start ~/solaris/server/jobs/index.js --name solaris-jobs --watch&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Vue.js client - &lt;code&gt;pm2 start ~/solaris/client/node_modules/@vue/cli-service/bin/vue-cli-service.js --name solaris-client --node-args="serve"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The above is where the magic happens. &lt;code&gt;pm2&lt;/code&gt; will manage the 3 processes, automatically watch for changes and restart the apps when necessary. The app is now accessible via the local IP address &lt;code&gt;192.168.1.xxx:8080&lt;/code&gt;, amazing!&lt;/p&gt;

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

&lt;h4&gt;
  
  
  Setting Up Visual Studio Code
&lt;/h4&gt;

&lt;p&gt;Now the apps are running and watching for changes, I needed a way to actually edit files. I chose to use VS Code for this as it has an awesome &lt;a href="https://code.visualstudio.com/docs/remote/ssh#:~:text=The%20Visual%20Studio%20Code%20Remote,anywhere%20on%20the%20remote%20filesystem." rel="noopener noreferrer"&gt;extension&lt;/a&gt; for &lt;strong&gt;remote development&lt;/strong&gt; via &lt;code&gt;ssh&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Debugging
&lt;/h4&gt;

&lt;p&gt;The only caveat with debugging is that it is &lt;em&gt;slightly&lt;/em&gt; inconvenient to stop the &lt;code&gt;pm2&lt;/code&gt; process and then launch a VS Code debugging session.&lt;/p&gt;

&lt;p&gt;The best way to get around this is to enable the &lt;code&gt;--inspect&lt;/code&gt; flag when launching the &lt;code&gt;pm2&lt;/code&gt; process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pm2 start solaris-jobs --node-args="--inspect=9230" --watch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then using a VS Code configuration to attach to the process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "type": "node",
    "request": "attach",
    "name": "Attach to Jobs",
    "port": 9230
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more info on the &lt;code&gt;--inspect&lt;/code&gt; flag, see &lt;a href="https://nodejs.org/en/docs/guides/debugging-getting-started/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;With all of that setup I can now simply open VS Code on my development machine and get straight into coding without really having to think about getting set up first. The environment is remote so any changes are &lt;strong&gt;persistent&lt;/strong&gt;, I can code on my desktop and then switch over to my laptop and continue what I was working on.&lt;/p&gt;

&lt;p&gt;I could take this a step further and use something like &lt;a href="https://github.com/cdr/code-server" rel="noopener noreferrer"&gt;code-server&lt;/a&gt; which will actually host VS Code itself on the Pi. Then all I need is a device with a browser and I'm good to go. Finally, I'll be able to code on my Samsung Smart Fridge!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Let me know what you think in the comments or if you have any suggestions. Thanks for reading.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>raspberrypi</category>
      <category>node</category>
      <category>ubuntu</category>
    </item>
  </channel>
</rss>
