<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Matt Biilmann</title>
    <description>The latest articles on Forem by Matt Biilmann (@biilmann).</description>
    <link>https://forem.com/biilmann</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%2F55464%2F9f0b61d8-3d4e-490b-8e22-5afa91f474be.jpeg</url>
      <title>Forem: Matt Biilmann</title>
      <link>https://forem.com/biilmann</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/biilmann"/>
    <language>en</language>
    <item>
      <title>Distributed Persistent Rendering: A new Jamstack approach for faster builds</title>
      <dc:creator>Matt Biilmann</dc:creator>
      <pubDate>Fri, 14 May 2021 04:14:05 +0000</pubDate>
      <link>https://forem.com/biilmann/distributed-persistent-rendering-a-new-jamstack-approach-for-faster-builds-1d5f</link>
      <guid>https://forem.com/biilmann/distributed-persistent-rendering-a-new-jamstack-approach-for-faster-builds-1d5f</guid>
      <description>&lt;p&gt;I’d like to share a new concept we’ve been exploring for the &lt;a href="https://jamstack.org" rel="noopener noreferrer"&gt;Jamstack&lt;/a&gt; at Netlify, born out of our work with large enterprise dev teams deploying hundreds of thousands of pages at a time.&lt;/p&gt;

&lt;p&gt;We wanted a way to make those deployments faster—without introducing unwanted complexity for Jamstack developers. Some solutions have come up before now, but they tend to lock you into a specific framework or break some of the most compelling reasons to use Jamstack in the first place. A Jamstack-focused approach was needed that would work across the ecosystem. After discussion both within Netlify and some members of the Jamstack community, we feel we’ve landed the right concept—something we’ve dubbed “Distributed Persistent Rendering” or “DPR” for short.&lt;/p&gt;

&lt;p&gt;This post is designed as an early introduction to the approach we’re proposing as well as an invitation for the entire community to offer feedback and collaboration. Our hope is to create a new standard that maintains the core principles and benefits of Jamstack and works across a wide variety of site generators and frameworks, bringing an even wider range of websites and use cases to the Jamstack.&lt;/p&gt;

&lt;h2&gt;
  
  
  The power of atomic deploys
&lt;/h2&gt;

&lt;p&gt;We think the very best tools are built around a simple mental model that helps you easily reason about the state of your application as you build it. Modern frontend libraries (like React and Vue) make a simple, powerful contract with the developer: UI becomes a function of state. Change the state, and the UI will rerender in response.&lt;/p&gt;

&lt;p&gt;The Jamstack has thrived because it too centers around an intuitive mental model: every git push runs a build process to create its own atomic deployment. This approach keeps it incredibly easy to reason about the current state of your site or application, even as many changes are committed daily from around your team. It makes both new deploys and rollbacks painless. It keeps you always confident in what any visitor will see at any given URL. And, most importantly, it avoids all the deep layers of caching, complexity, and infrastructure that came out of scaling the legacy web.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fight against complexity
&lt;/h2&gt;

&lt;p&gt;For any technology, the hardest part is not establishing simplicity, but protecting it over time.&lt;/p&gt;

&lt;p&gt;As the Jamstack evolves, new features like dynamic server side rendering, rehydration, tiered CDN caching, and stale while revalidate seem to be creeping us back towards all the complexity we fought to escape. Can you still be confident in a rollback? Do you really know how your site will behave if you push deploy preview #110?&lt;/p&gt;

&lt;p&gt;Of course the momentum to add features to a platform is the desire to solve real challenges. And one of the challenges of the atomic deployment model is the time it takes to rebuild an entire site each for each deploy. Larger teams and projects are feeling this impact, especially now that Jamstack sites are scaling to 100,000 pages and beyond.&lt;/p&gt;

&lt;h2&gt;
  
  
  Speeding up deployments... without weighing down the Jamstack
&lt;/h2&gt;

&lt;p&gt;Netlify would like to work with the entire Jamstack community to help bring a solution for faster large site deployments—but importantly an approach that stays true to the atomic deployment model of the Jamstack. We’re calling our proposal Distributed Persistent Rendering, and today we’ve posted details about the approach in a &lt;a href="https://www.netlify.com/dpr-rfc" rel="noopener noreferrer"&gt;Request For Comments (RFC)&lt;/a&gt;. Our hope is that community members and site generator authors will weigh in and help us build something that is easily adoptable by multiple frameworks. Already, we’ve seen early engagement from Nuxt and 11ty and we hope many more will join the collaboration.&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%2Fwww.netlify.com%2Fimg%2Fblog%2Fdpr-blog-post-image.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%2Fwww.netlify.com%2Fimg%2Fblog%2Fdpr-blog-post-image.png" title="Distributed Persistent Rendering" alt="Distributed Persistent Rendering"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Distributed Persistent Rendering (or DPR) allows developers to defer rendering any given URL or asset until it’s first requested. With DPR, you can (and should) still prerender critical pages at build time—perhaps your homepage or recent blog posts. But that huge archive containing years of older posts? Using DPR, those pages can be rendered only when and if they are requested. And once rendered, they remain as a persistent asset until the next deploy—just as if they had been part of the initial build. It brings the benefit of faster builds without introducing the complexity of scaling and caching server-side rendering. And unlike a caching-based strategy, there’s no risk of confusion from stale assets or fallback pages.&lt;/p&gt;

&lt;p&gt;We think DPR strikes the right balance—new capabilities without new complexities. We’re so excited we’ve even built a new service offering to help accelerate us towards DPR and &lt;a href="https://www.netlify.com/blog/2021/04/14/faster-builds-for-large-sites-on-netlify-with-on-demand-builders-now-in-early-access/" rel="noopener noreferrer"&gt;we’re announcing today&lt;/a&gt; that any Netlify customer can gain early access to explore the approach and the simple API behind it.&lt;/p&gt;

&lt;p&gt;Please let us know what you think in the &lt;a href="https://www.netlify.com/dpr-rfc" rel="noopener noreferrer"&gt;RFC&lt;/a&gt; and show us what you build!&lt;/p&gt;

</description>
      <category>jamstack</category>
      <category>dpr</category>
      <category>netlify</category>
    </item>
    <item>
      <title>Open source parallel processing for Gatsby</title>
      <dc:creator>Matt Biilmann</dc:creator>
      <pubDate>Tue, 25 Feb 2020 15:12:37 +0000</pubDate>
      <link>https://forem.com/biilmann/open-source-parallel-processing-for-gatsby-270d</link>
      <guid>https://forem.com/biilmann/open-source-parallel-processing-for-gatsby-270d</guid>
      <description>&lt;p&gt;To help the greater Gatsby ecosystem shorten the time it takes from commit to deploy, today I've just submitted a freshly baked &lt;a href="https://github.com/gatsbyjs/gatsby/pull/21733"&gt;Pull Request&lt;/a&gt; as my first larger contribution to the Gatsby open source project.&lt;/p&gt;

&lt;p&gt;The new &lt;a href="https://www.npmjs.com/package/gatsby-parallel-runner"&gt;gatsby-parallel-runner&lt;/a&gt; plugin builds on some of the existing work in the Gatsby project to allow both plugins and core parts of Gatsby to parallelize certain tasks by delegating the work to a large pool of serverless functions.&lt;/p&gt;

&lt;p&gt;Gatsby Cloud pioneered this approach, and with this plugin I hope that we can open an even more generalized approach to parallelization. While it's in early development, my goal is that this can one day be made available on any CI/CD environment, and empower individual plugin developers in the ecosystem to build in support for parallelization when a task is well suited for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gatsby and "External Jobs"
&lt;/h2&gt;

&lt;p&gt;A bit under a month ago Ward Peeters from Gatsby's team landed a &lt;a href="https://github.com/gatsbyjs/gatsby/pull/20835"&gt;Pull Request&lt;/a&gt; to "enable external jobs with ipc". The idea behind the pull request is that instead of running &lt;code&gt;gatsby build&lt;/code&gt; directly, an orchestrating parent process can fork &lt;code&gt;gatsby build&lt;/code&gt; and make sure an environment variable called &lt;code&gt;ENABLE_GATSBY_EXTERNAL_JOBS&lt;/code&gt; is set. When that is done certain jobs will be sent via node's IPC protocol to the parent process as "external jobs" in order to allow the parent orchestrater to efficiently parallelize the execution of them.&lt;/p&gt;

&lt;p&gt;In itself nodejs is single threaded, so out of the box any CPU intensive jobs in Gatsby will only ever take advantage of one CPU core, but this ipc based delegation opens up the possibility of taking advantage of external worker processes for parallelization.&lt;/p&gt;

&lt;p&gt;The only plugin that currently hooks into this is &lt;code&gt;gatsby-plugin-sharp&lt;/code&gt; which is used for image transformation. At Netlify we've often seen image transformations be a huge source of build slowdowns for Gatsby sites, since doing lots of image processing within a single threaded build is really inefficient.&lt;/p&gt;

&lt;p&gt;The open source Gatsby process has until now not offered any implementation of an orchestrator for Gatsby that can help you take advantage of external jobs, and that's where our new &lt;code&gt;gatsby-parallel-runner&lt;/code&gt; helps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gatsby Parallel Runner
&lt;/h2&gt;

&lt;p&gt;I've been having fun building out this new Gatsby plugin that acts as an alternative build command. Once installed in a project, you'll run &lt;code&gt;gatsby-parallel-runner&lt;/code&gt; instead of &lt;code&gt;gatsby build&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Out of the box it comes with a parallelized implementation of the Sharp image plugin based on Google Cloud Functions. It includes an easy script to get your own functions and queues setup in a Google Cloud project with just one command. It's built to be extensible so the community can easily add alternative implementations of the actual execution layer. Obvious candidates would be AWS Lambda functions or a nodejs cluster implementation. It should also be easy to use with new plugins that want to add external jobs outside of just image processing.&lt;/p&gt;

&lt;p&gt;My hope is that this can help pave the way for more innovations in the ecosystem around build parallelization – and of course we're seeing a lot of opportunity in adding a more generalized form of this to Netlify's own build layer.&lt;/p&gt;

&lt;p&gt;Our philosophy has always been to keep the build layer fundamentally open - our &lt;a href="https://github.com/netlify/build-image"&gt;core build image&lt;/a&gt; has always been Open Source as is our new &lt;a href="https://github.com/netlify/build"&gt;Build Plugin&lt;/a&gt; layer, and we've always believed that a healthy Open Source ecosystem in the build tool space is vital to the growth of the whole JAMstack category. So we're happy to contribute this project back to the Open Source community.&lt;/p&gt;

&lt;p&gt;I ran a few benchmarks with the &lt;a href="https://github.com/gatsbyjs/gatsby/tree/master/benchmarks/image-processing"&gt;official Gatsby image benchmark repository&lt;/a&gt; on Netlify's build environment both with and without the &lt;code&gt;gatsby-parallel-runner&lt;/code&gt; and was thrilled to see the &lt;code&gt;gatsby-parallel-runnner&lt;/code&gt; consistently outperform the normal &lt;code&gt;gatsby build&lt;/code&gt; command:&lt;/p&gt;

&lt;p&gt;Running 3 times from a clear cache with &lt;code&gt;gatsby build&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Run 1:
11:10:27 PM: success Generating image thumbnails - 351.218s - 3234/3234 9.21/s

Run 2:
1:45:43 PM: success Generating image thumbnails - 384.171s - 3234/3234 8.42/s

Run 3:
11:18:22 PM: success Generating image thumbnails - 322.853s - 3234/3234 10.02/s

Avg time for image generation: 352.747s
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Running 6 times from a clear cache with &lt;code&gt;gatsby-parallel-runner&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Run 1:
10:51:31 PM: success Generating image thumbnails - 158.438s - 3234/3234 20.41/s

Run 2:
5:33:33 PM: success Generating image thumbnails - 68.016s - 3234/3234 47.55/s

Run 3:
3:03:48 AM: success Generating image thumbnails - 75.731s - 3234/3234 42.70/s

Run 4:
10:54:47 PM: success Generating image thumbnails - 64.478s - 3234/3234 50.16/s

Run 5:
10:58:31 PM: success Generating image thumbnails - 66.021s - 3234/3234 48.98/s

Run 6:
11:01:58 PM: success Generating image thumbnails - 71.416s - 3234/3234 45.28/s


Avg time for image generation: 84.017s
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The first run after deploying the functions was a bit slower than the subsequent runs, as Google worked on scaling up the number of concurrent function executions, but even then it was still more than twice as fast in the worst case as the standard Gatsby build command. &lt;/p&gt;

&lt;p&gt;And on average - even with the initial outlier included - the parallel runner gave more than a 4.2x speedup over the single threaded runtime.&lt;/p&gt;

&lt;p&gt;For curiosity I repeated the same benchmark on Gatsby Cloud:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Run 1:
03:02:38 AM: success Generating image thumbnails - 98.472s - 3234/3234 32.84/s

Run 2:
07:34:53 AM: success Generating image thumbnails - 328.141s - 3234/3234 9.86/s

Run 3:
22:19:50 PM: success Generating image thumbnails - 85.101s - 3234/3234 38.00/s

Run 4:
22:34:22 PM: success Generating image thumbnails - 134.721s - 3234/3234 24.01/s

Run 5:
23:02:37 PM: success Generating image thumbnails - 82.822s - 3234/3234 39.05/s

Run 6:
23:07:31 PM: success Generating image thumbnails - 60.532s - 3234/3234 53.43/s


Avg time for image generation: 131.631s
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;These tests had a lot more variability in build times than my Netlify based tests, and while the average was more than twice as fast as the single threaded build performance, the open source parallel runner performed significantly better in the tests I ran. So hopefully the Gatsby Cloud team can also benefit from looking into the source code behind this implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up
&lt;/h2&gt;

&lt;p&gt;Install in your gatsby project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i gatsby-parallel-runner
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To use with Google Cloud, set relevant env variables in your shell:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export GOOGLE_APPLICATION_CREDENTIALS=~/path/to/your/google-credentials.json

export TOPIC=parallel-runner-topic
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Deploy the cloud function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx gatsby-parallel-runner deploy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then run your Gatsby build with the parallel runner instead of the default &lt;code&gt;gatsby build&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx gatsby-parallel-runner
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>gatsby</category>
      <category>jamstack</category>
      <category>netlify</category>
      <category>performance</category>
    </item>
  </channel>
</rss>
