<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Javascript | AkitaOnRails.com</title><link>https://akitaonrails.github.io/en/tags/javascript/</link><description>Fabio Akita's blog — tech, career, and assorted geek topics. English edition.</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Mon, 19 Oct 2026 23:20:51 +0000</lastBuildDate><atom:link href="https://akitaonrails.github.io/en/tags/javascript/index.xml" rel="self" type="application/rss+xml"/><item><title>[Beginner] Trying out Rails 5.1.x</title><link>https://akitaonrails.github.io/en/2017/10/24/beginner-trying-out-rails-5-1-x/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2017/10/24/beginner-trying-out-rails-5-1-x/</guid><pubDate>Tue, 24 Oct 2017 16:29:00 -0200</pubDate><description>&lt;p&gt;One thing that is not so great about having to deal with client projects is that most of them take their time before doing a full framework upgrade. And you can&amp;rsquo;t blame them, as many of the dependencies in the ecosystem take their sweet, sweet time to upgrade as well.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://weblog.rubyonrails.org/2017/9/29/this-week-in-rails-getting-closer-to-rails-5-2-beta/"target="_blank" rel="noopener"&gt;Rails 5.2 Beta&lt;/a&gt; is almost upon us, and I would bet that most of the Rails projects out there are in the 4.2 version, still thinking about doing the jump to 5.0 (which is not so bad an upgrade).&lt;/p&gt;</description><content:encoded><![CDATA[<p>One thing that is not so great about having to deal with client projects is that most of them take their time before doing a full framework upgrade. And you can&rsquo;t blame them, as many of the dependencies in the ecosystem take their sweet, sweet time to upgrade as well.</p>
<p><a href="http://weblog.rubyonrails.org/2017/9/29/this-week-in-rails-getting-closer-to-rails-5-2-beta/"target="_blank" rel="noopener">Rails 5.2 Beta</a> is almost upon us, and I would bet that most of the Rails projects out there are in the 4.2 version, still thinking about doing the jump to 5.0 (which is not so bad an upgrade).</p>
<p>By the way, in case you didn&rsquo;t know, the official Rails Guides website has a section dedicated to upgrades. It&rsquo;s called <a href="http://guides.rubyonrails.org/upgrading_ruby_on_rails.html"target="_blank" rel="noopener">A Guide for Upgrading Ruby on Rails</a>. The process of upgrading is not actually so difficult <strong>if, and only if</strong>:</p>
<ul>
<li>
<p>You have a fairly good test coverage. You should have, at the very least, feature specs for the most important parts of your system.</p>
</li>
<li>
<p>You should upgrade to just one subsequent version at a time, never going straight to the most recent one. For example, If you&rsquo;re in Rails 4.1, you must first upgrade to 4.2, make sure everything works. Then go to 5.0. And only then go to 5.1. Each version has <strong>many</strong> deprecations, changes in behavior, changes in default boilerplate configuration, added new features. You must attend to each very carefully.</p>
</li>
</ul>
<p>So, what are you missing if you&rsquo;re still in Rails 4.2?</p>
<p>Again, in case you didn&rsquo;t know, the official Rails Guides website also compiles detailed and easy to read Release Notes for each new version. The most recent are the <a href="http://guides.rubyonrails.org/5_1_release_notes.html"target="_blank" rel="noopener">Ruby on Rails 5.1 Release Notes</a>.</p>
<h2>Starting a new project<span class="hx:absolute hx:-mt-20" id="starting-a-new-project"></span>
    <a href="#starting-a-new-project" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The <code>rails new</code> command has a lot of new flags. And I think these are the ones most people will use:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>rails new --skip-action-mailer --skip-coffee --webpack=react my_fancy_new_project</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>You can disable features you don&rsquo;t need such as ActionMailer or ActionCable. You can disable CoffeeScript. It was cool for a while but now that ES6 exists we should just use it.</p>
<p>Rails 5.1 comes with the support for webpack. But until Rails 5.2 comes up, we need to use the <code>webpack-dev-server</code> manually in development mode so we can hot reload assets. For that end, I recommend installing good old <a href="https://github.com/ddollar/foreman"target="_blank" rel="noopener">Foreman</a>. Install it like this:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>gem install foreman</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>And add a <code>Procfile.dev</code> file to your project with the following content:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>web: ./bin/rails s -b 0.0.0.0 -p 3000
webpack: ./bin/webpack-dev-server</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>And now you can start up your development server like this:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>foreman start -f Procfile.dev</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>In production, you don&rsquo;t need the <code>webpack-dev-server</code> as the <code>bin/rails assets:precompile</code> task should be able to compile all the assets you need as static, timestamped files in <code>public/assets</code>.</p>
<h2>Front-end Specific Changes<span class="hx:absolute hx:-mt-20" id="front-end-specific-changes"></span>
    <a href="#front-end-specific-changes" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Now, you can rejoice with Yarn, Webpack, and no more jQuery pre-installed. Samuel Muller has a <a href="http://samuelmullen.com/articles/embracing-change-rails51-adopts-yarn-webpack-and-the-js-ecosystem/"target="_blank" rel="noopener">nice article</a> that summarizes most of these changes in more detail.</p>
<p>Now Ruby on Rails officially supports every bell and whistle from the Javascript ecosystem. There is nothing left behind that you might miss.</p>
<p>No more manually vendoring JS assets in <code>vendor/assets/javascripts</code> directory. No more need to use <a href="https://rails-assets.org/"target="_blank" rel="noopener">Rails Assets</a>, which was a secondary RubyGems source specific to package JS libraries into RubyGems.</p>
<p>Let&rsquo;s say that, for some reason, you want jQuery back. You can now just do:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>yarn add jquery</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>And, as usual, you can simply add it to your <code>app/assets/javascripts/application.js</code> manifest file:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>// app/assets/javascripts/application.js
...
//= require jquery
...
//= require_tree .</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>The so-called <a href="https://github.com/rails/rails/pull/26836"target="_blank" rel="noopener">&ldquo;support for Yarn in Rails 5.1&rdquo;</a> boils down to a few wrappers and boilerplate. So you can run <code>rails yarn:install</code> and have the dependencies installed, but you can just as easily type <code>yarn</code> and it will install everything you need that is declared in the <code>package.json</code> file, as with any other Javascript-only project.</p>
<p>Now, the whole magic of the integration comes from the inclusion of the <a href="https://github.com/rails/webpacker"target="_blank" rel="noopener">Webpacker</a> gem. It adds a bunch of boilerplate configuration for webpack. And, <strong>bonus fact</strong> you can include it today in your current Rails 4.2+ projects as well. Just start by adding the webpacker gem to your <code>Gemfile</code>:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code># Gemfile
gem &#39;webpacker&#39;, &#39;~&gt; 3.0&#39;</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Then <code>bundle install</code> as usual and run:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>bundle exec rake webpacker:install</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>If you didn&rsquo;t use the <code>--webpack=react</code> flag to the <code>rails new</code> command, you can add it later. Or you can add Angular as well:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>bundle exec rake webpacker:install:angular
bundle exec rake webpacker:install:react </code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>You should replace <code>bundle exec rake</code> for <code>bin/rails</code> if you&rsquo;re in Rails 5.1.</p>
<p>Adding proper React components is a bit more than the command above though. And the details are more than I want to cover in this post.</p>
<p>Andy Barnov has a <a href="https://x-team.com/blog/get-in-full-stack-shape-with-rails-5-1-webpacker-and-reactjs/"target="_blank" rel="noopener">good post</a> on how to follow the Rails 5.1 packs convention to add your React components in the pipeline. As he recommends, don&rsquo;t fight the conventions and you should be golden.</p>
<p>Oddly enough, even though I used the <code>--webpack-react</code> flag to the <code>rails new</code> I still had to run the following command to bootstrap the webpack and react supports:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>./bin/rails webpacker:install:react</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>But once you do, you will get a new place to add React components, and that&rsquo;s in a proper <code>app/javascripts/packs</code>. And in the views, instead of the usual <code>javascript_include_tag</code> you will use the brand new <code>javascript_pack_tag</code>. I believe you can figure out the rest from the example component <code>hello_react.jsx</code> that it generates for you.</p>
<h2>Final Thoughts<span class="hx:absolute hx:-mt-20" id="final-thoughts"></span>
    <a href="#final-thoughts" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>You now have a whole lot more options for Javascript, as Rails 5.1 fully embraces the current standards.</p>
<p>Once upon a time, no one properly knew how to streamline an <a href="http://guides.rubyonrails.org/asset_pipeline.html"target="_blank" rel="noopener">Asset Pipeline</a>. It was very messy to compile all your assets in a single file with proper cache busting timestamps, but the <strong>Sprockets</strong> gem did it.</p>
<p>Once upon a time, Javascript 5 was a damn mess. Libraries such as jQuery actually &ldquo;fixed&rdquo; most of the browser DOM situation, and CoffeeScript normalized the language in a way that made it enjoyable. ES6 came to take over the reins but it&rsquo;s very unfair to criticize jQuery and Coffee as neither ES6 nor HTML5 were there to solve the situation almost 10 years ago. jQuery and Coffee were there, and they solved it.</p>
<p>When Angular, Ember, and React were starting, we already had a good enough solution for javascript-heavy websites with <a href="https://github.com/turbolinks/turbolinks"target="_blank" rel="noopener">Turbolinks</a>. This is still a very good solution that you should consider using instead of adding a full-blown (and sometimes unnecessary) React/Redux solution at once.</p>
<p>CSS is another matter entirely. The Rails community also created Sass (which then Twitter envied and copied to Less for the Bootstrap framework).</p>
<p>It&rsquo;s easy to see the current landscape and just repeat that Coffee is bad or Sprockets is bad. But for the past 10 years, those tools were the best of breed in a time where people didn&rsquo;t have Yarn, Webpack, React and all the tools that popped up in the past 3 years or so.</p>
<p>Rails 5.1 is a very good release to marry the best of Rails with the best that kinda stabilized today in the Javascript mad arena. And I highly recommend that any new, greenfield project, start with Rails 5.1 in mind.</p>
<p>One thing that led me to write this post is to highlight that many people ask questions that are mostly answered in the official <a href="http://guides.rubyonrails.org/"target="_blank" rel="noopener">Rails Guides</a>. Not only on how to install and use the many components of the framework but also how to upgrade and what the new features of each release are. So you should definitely take a better look there.</p>
]]></content:encoded><category>rails</category><category>javascript</category><category>frontend</category></item><item><title>The Obligatory "Flame War" Phoenix vs Node.js</title><link>https://akitaonrails.github.io/en/2015/12/03/the-obligatory-flame-war-phoenix-vs-node-js/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2015/12/03/the-obligatory-flame-war-phoenix-vs-node-js/</guid><pubDate>Thu, 03 Dec 2015 12:01:00 -0200</pubDate><description>&lt;p&gt;I&amp;rsquo;ll warn you upfront: this will be a very unfair post. Not only am I biased for disliking Javascript and Node.js, but at this moment, I am very excited and fascinated by Elixir and Erlang.&lt;/p&gt;
&lt;p&gt;Comparisons are always unfair. There is no such thing as a &amp;ldquo;fair&amp;rdquo; synthetic benchmark comparison, the author is &lt;strong&gt;always&lt;/strong&gt; biased towards some targeted result. It&amp;rsquo;s the old pseudo-science case of having a conclusion and picking and choosing data that backs those conclusions. There are just too many different variables. People think it&amp;rsquo;s fair when you run it in the same machine against 2 &amp;ldquo;similar&amp;rdquo; kinds of applications, but it is not. Please don&amp;rsquo;t trust me on this as well, do your own tests.&lt;/p&gt;</description><content:encoded><![CDATA[<p>I&rsquo;ll warn you upfront: this will be a very unfair post. Not only am I biased for disliking Javascript and Node.js, but at this moment, I am very excited and fascinated by Elixir and Erlang.</p>
<p>Comparisons are always unfair. There is no such thing as a &ldquo;fair&rdquo; synthetic benchmark comparison, the author is <strong>always</strong> biased towards some targeted result. It&rsquo;s the old pseudo-science case of having a conclusion and picking and choosing data that backs those conclusions. There are just too many different variables. People think it&rsquo;s fair when you run it in the same machine against 2 &ldquo;similar&rdquo; kinds of applications, but it is not. Please don&rsquo;t trust me on this as well, do your own tests.</p>
<p>All that being said, let&rsquo;s have some fun, shall we?</p>
<h3>The Obligatory &ldquo;Hello World&rdquo; warm-up<span class="hx:absolute hx:-mt-20" id="the-obligatory-hello-world-warm-up"></span>
    <a href="#the-obligatory-hello-world-warm-up" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>For this very short post, I just created a Node.js + Express &ldquo;hello world,&rdquo; I will point to its root endpoint, Express, rendering a super simple HTML template with one title and one paragraph.</p>
<p>For Elixir, I just bootstrapped a bare-bone Phoenix project and added one extra endpoint called &ldquo;/teste&rdquo; in the Router. This endpoint will call the PageController, then the &ldquo;teste&rdquo; function, and render an EEX template with the same title and paragraph as in the Express example.</p>
<p>Simple enough. Phoenix does more than Express, but this is not supposed to be a fair trial anyway. I chose <a href="https://www.joedog.org/siege-home/"target="_blank" rel="noopener">Siege</a> as the testing tool for no particular reason. You can pick the testing tool you like the most. I am running this over my 2013 Macbook Pro with 8 cores and 16GB of RAM, so this benchmark will never max out my machine.</p>
<p>The first test is a simple run of 200 concurrent connections (the number of CPUs I have) firing just 8 requests each for 1,600. First, the Node.js + Express results:</p>
<video controls>
<source src="https://s3.us-east-2.amazonaws.com/blip.tv/Elixir/Node+8+x+200.mp4">
Your browser does not support the video tag. [Direct Link](https://s3.us-east-2.amazonaws.com/blip.tv/Elixir/Node+8+x+200.mp4)
</source></video>
<p>The first run already broke a few connections, but the 2nd run picked up and finished all 1,600 requests. And this is the Phoenix results:</p>
<video controls>
<source src="https://s3.us-east-2.amazonaws.com/blip.tv/Elixir/Phoenix+8+x+200.mp4">
Your browser does not support the video tag. [Direct Link](https://s3.us-east-2.amazonaws.com/blip.tv/Elixir/Phoenix+8+x+200.mp4)
</source></video>
<p>As you can see, Node.js has the upper hand in terms of the total time spent. One single Node.js process can only run one single real OS thread. Therefore it had to use just a single CPU core (although I had 7 other cores to spare). On the other hand, Elixir can reach all 8 cores of my machine, each running a Scheduler in a single real OS thread. So, if this test was CPU bound, it should have run 8 times faster than the Node.js version. As the test is largely a case of I/O bound operations, the clever async construction of Node.js does the job just fine.</p>
<p>This is not an impressive test by any stretch of the imagination. But we&rsquo;re just warming up.</p>
<p>Oh, and by the way, notice how Phoenix logs show the request processing times in MICROseconds instead of milliseconds!</p>
<h3>The Real Fun<span class="hx:absolute hx:-mt-20" id="the-real-fun"></span>
    <a href="#the-real-fun" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Now comes the real fun. In this second run, I added a blocking &ldquo;sleep&rdquo; call to both projects, so each request will sleep for one full second, and this is not absurd. Many programmers will use poor code that blocks for that time, process too much data from the database, render templates that are too complex, and so on. Never trust a programmer to follow best practices all the time.</p>
<p>Then, I fire up Siege with ten concurrent connections and just one request each, for starters.</p>
<video controls>
<source src="https://s3.us-east-2.amazonaws.com/blip.tv/Elixir/Node+1+x+10+Sleep.mp4">
Your browser does not support the video tag. [Direct Link](https://s3.us-east-2.amazonaws.com/blip.tv/Elixir/Node+1+x+10+Sleep.mp4)
</source></video>
<p>This is why in my previous article &ldquo;Why Elixir?&rdquo; (<a href="http://www.akitaonrails.com/en/2015/12/01/o-obrigatorio-por-que-elixir-visao-pessoal%29"target="_blank" rel="noopener">http://www.akitaonrails.com/en/2015/12/01/o-obrigatorio-por-que-elixir-visao-pessoal)</a>, I repeated many times how <strong>&ldquo;rudimentary&rdquo;</strong> a Reactor pattern-based solution is. It is super easy to block a single-threaded event loop.</p>
<p>If you didn&rsquo;t know that already, how does Node.js work? In summary, it is a simple infinite loop. When a Javascript function runs, it blocks that event loop. The function has to explicitly yield control back to the loop for another function to have a chance to run. I/O calls take time and just sit back idly waiting for a response, so it can yield control back and wait for a callback to continue running, which is why you end up with the dreaded <em>&ldquo;callback pyramid hell&rdquo;</em>.</p>
<p>Now, with what I explained in all my previous articles, you may already know how Elixir + Phoenix will perform:</p>
<video controls>
<source src="https://s3.us-east-2.amazonaws.com/blip.tv/Elixir/Phoenix+2+x+400+-+Sleep.mp4">
Your browser does not support the video tag. [Direct Link](https://s3.us-east-2.amazonaws.com/blip.tv/Elixir/Phoenix+2+x+400+-+Sleep.mp4)
</source></video>
<p>As expected, this is a walk in the park for Phoenix. It doesn&rsquo;t have a rudimentary single-thread loop waiting for the running functions to yield control back willingly. The Schedulers can forcefully suspend running coroutines/processes if they think they are taking too much time (the 2,000 reductions count and priority configurations), so every running process has a fair share of resources to run.</p>
<p>Because of that, I can keep increasing the number of requests and concurrent connections, and it&rsquo;s still <strong>fast</strong>.</p>
<p>In Node.js, if a function takes 1 second to run, it blocks the loop. When it finally returns, the next 1-second function can run. That&rsquo;s why if I have ten requests taking 1 second each to run, the entire process will linearly take 10 seconds!</p>
<p>Which obviously does not scale! If you &ldquo;do it right,&rdquo; you can scale. But why bother?</p>
<h3>&ldquo;Node&rdquo; done right<span class="hx:absolute hx:-mt-20" id="node-done-right"></span>
    <a href="#node-done-right" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>As a side note, I find it ironic that &ldquo;Node&rdquo; is called &ldquo;Node.&rdquo; I would assume that connecting multiple Nodes that communicate with each other should be easy. And as a matter of fact, <a href="http://www.sitepoint.com/how-to-create-a-node-js-cluster-for-speeding-up-your-apps/"target="_blank" rel="noopener">it is not</a>.</p>
<p>If I had spun up 5 Node processes, instead of 10 seconds, everything would take 2 seconds as five requests would block the 5 Node processes for 1 second, and when returned, the next five requests would block again. This is similar to what we need to do with Ruby or Python, which have the dreaded big Global Interpreter Locks (GIL) that, in reality, can only run one blocking computation at a time. (Ruby with Eventmachine and Python with Tornado or Twisted are similar to Node.js implementation of a reactor event loop).</p>
<p>Elixir can do much better in terms of actually coordinating different nodes, and it is the Erlang underpinnings that allow highly distributed systems such as <a href="https://www.ejabberd.im/"target="_blank" rel="noopener">ejabberd</a> or <a href="https://www.rabbitmq.com/"target="_blank" rel="noopener">RabbitMQ</a> to do their thing as efficiently as they can.</p>
<p>Check out how simple it is for one Elixir Node to notice the presence of other Elixir nodes and make them send and receive messages between each other:</p>
<video controls>
<source src="https://s3.us-east-2.amazonaws.com/blip.tv/Elixir/7+-+Nodes.mp4">
Your browser does not support the video tag. [Direct Link](https://s3.us-east-2.amazonaws.com/blip.tv/Elixir/7+-+Nodes.mp4)
</source></video>
<p>Yep, it is this simple. We have been using Remote Procedure Calls (RPC) for decades; this is not new. Erlang has implemented this for years, and it is built-in and available for easy usage out-of-the-box.</p>
<p>On their websites, ejabberd calls itself a &ldquo;Robust, Scalable, and Extensible XMPP Server,&rdquo; and RabbitMQ calls itself &ldquo;Robust messaging for applications.&rdquo; Now we know they deserve the labels &ldquo;Robust&rdquo; and &ldquo;Scalable.&rdquo;</p>
<p>So, we are struggling to do things that have been polished and ready for years. Elixir is the key to unlocking all this Erlang goodness right now. Let&rsquo;s just use it and stop shrugging.</p>
]]></content:encoded><category>performance</category><category>elixir-and-erlang</category><category>javascript</category></item></channel></rss>