<?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: Dan L</title>
    <description>The latest articles on DEV Community by Dan L (@s1owjke).</description>
    <link>https://dev.to/s1owjke</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%2F1045926%2F1fc27e96-faa2-4e7f-a16e-1ee40df84720.jpeg</url>
      <title>DEV Community: Dan L</title>
      <link>https://dev.to/s1owjke</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/s1owjke"/>
    <language>en</language>
    <item>
      <title>How to destroy an infra deployed with Terraform by .tfstate</title>
      <dc:creator>Dan L</dc:creator>
      <pubDate>Mon, 26 Feb 2024 18:30:11 +0000</pubDate>
      <link>https://dev.to/s1owjke/how-to-destroy-an-infra-deployed-with-terraform-by-tfstate-44k4</link>
      <guid>https://dev.to/s1owjke/how-to-destroy-an-infra-deployed-with-terraform-by-tfstate-44k4</guid>
      <description>&lt;p&gt;Sometimes it's necessary to remove previously deployed infrastructure using Terraform, but in some cases it can be challenging to do so.&lt;/p&gt;

&lt;p&gt;This could be due to old pipelines where destroying cannot be started due to breaking changes in configuration (e.g. environment variables no longer exists) or manually created infrastructure during development.&lt;/p&gt;

&lt;p&gt;Today I want to show you a quick and easy way using only the .tfstate files where Terrafrom stores the &lt;a href="https://developer.hashicorp.com/terraform/language/state" rel="noopener noreferrer"&gt;current state&lt;/a&gt; (assuming you follow best practices and store them in one place like an S3 bucket).&lt;/p&gt;

&lt;h2&gt;
  
  
  Initial configuration
&lt;/h2&gt;

&lt;p&gt;In my examples, I'll use AWS, but you can easily adapt this to any other &lt;a href="https://registry.terraform.io/browse/providers" rel="noopener noreferrer"&gt;supported&lt;/a&gt; provider.&lt;/p&gt;

&lt;p&gt;You'll need the correct version of Terraform (the version of Terraform used for apply can be found in &lt;code&gt;terraform_version&lt;/code&gt; at the beginning of the .tfstate file), to switch between versions I recommend &lt;a href="https://github.com/tfutils/tfenv" rel="noopener noreferrer"&gt;tfenv&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First, create an &lt;code&gt;.env&lt;/code&gt; where we'll specify all the variables. For backend configuration we'll pass it as command-line arguments because Terraform still doesn't support variables in the backend section.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TF_VAR_account_id=000000000000
TF_VAR_region=us-east-1
TF_VAR_access_key=XXXXXXXXXXXXXXXXXXXX
TF_VAR_secret_key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
TF_BACKEND_BUCKET=your-bucket-name
TF_BACKEND_KEY=path/to/terraform.tfstate
TF_BACKEND_ENCRYPT=true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create &lt;code&gt;main.tf&lt;/code&gt; specifying the provider, its version, and the used backend. Use the optional &lt;code&gt;allowed_account_ids&lt;/code&gt; parameter to ensure it runs in the correct AWS account.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;aws&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hashicorp/aws"&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;"~&amp;gt; 5.9"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="s2"&gt;"s3"&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;allowed_account_ids&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;region&lt;/span&gt;
  &lt;span class="nx"&gt;access_key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;access_key&lt;/span&gt;
  &lt;span class="nx"&gt;secret_key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secret_key&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's run &lt;code&gt;terraform init&lt;/code&gt;, (Note: we use the &lt;code&gt;env $(cat .env | xargs)&lt;/code&gt; to read variables from the .env file).&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;env&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; .env | xargs&lt;span class="si"&gt;)&lt;/span&gt; terraform init &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-backend-config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"region=&lt;/span&gt;&lt;span class="nv"&gt;$TF_VAR_region&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-backend-config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"access_key=&lt;/span&gt;&lt;span class="nv"&gt;$TF_VAR_access_key&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-backend-config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"secret_key=&lt;/span&gt;&lt;span class="nv"&gt;$TF_VAR_secret_key&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-backend-config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"bucket=&lt;/span&gt;&lt;span class="nv"&gt;$TF_BACKEND_BUCKET&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-backend-config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"key=&lt;/span&gt;&lt;span class="nv"&gt;$TF_BACKEND_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-backend-config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"encrypt=&lt;/span&gt;&lt;span class="nv"&gt;$TF_BACKEND_ENCRYPT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now we can destroy all the infra registered in the .tfstate file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating a utility
&lt;/h2&gt;

&lt;p&gt;Usually if you start doing this you'll have to execute multiple times which is not very convenient, let's create a &lt;code&gt;run.sh&lt;/code&gt; entrypoint where we can pass the path to the .tfstate file as argument.&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="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Path to terraform.tfstate is required"&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; .env | xargs&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;TF_BACKEND_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;

terraform init &lt;span class="nt"&gt;-reconfigure&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-backend-config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"region=&lt;/span&gt;&lt;span class="nv"&gt;$TF_VAR_region&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-backend-config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"access_key=&lt;/span&gt;&lt;span class="nv"&gt;$TF_VAR_access_key&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-backend-config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"secret_key=&lt;/span&gt;&lt;span class="nv"&gt;$TF_VAR_secret_key&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-backend-config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"bucket=&lt;/span&gt;&lt;span class="nv"&gt;$TF_BACKEND_BUCKET&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-backend-config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"key=&lt;/span&gt;&lt;span class="nv"&gt;$TF_BACKEND_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-backend-config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"encrypt=&lt;/span&gt;&lt;span class="nv"&gt;$TF_BACKEND_ENCRYPT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

terraform destroy &lt;span class="nt"&gt;-auto-approve&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We added the &lt;code&gt;-reconfigure&lt;/code&gt; to init to reuse cached &lt;a href="https://developer.hashicorp.com/terraform/cli/init#working-directory-contents" rel="noopener noreferrer"&gt;plugins and modules&lt;/a&gt; (don't delete the .terraform folder between calls, it'll significantly speed up the process). To avoid confirming destroy each time, we added the &lt;code&gt;-auto-approve&lt;/code&gt; flag.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use it
&lt;/h2&gt;

&lt;p&gt;Now, you can run it (remember to make it executable with &lt;code&gt;chmod +x&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./run.sh path/to/terraform.tfstate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To batch run, we need to find all matching .tfstate files and call our script for each of them using &lt;code&gt;awk&lt;/code&gt;. Please double check that you have filtered only what you need to destroy before running it.&lt;/p&gt;

&lt;p&gt;For AWS with the S3 backend run this (if you are using another backend, you'll need to adapt this command).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws s3 &lt;span class="nb"&gt;ls &lt;/span&gt;s3://your-bucket-name &lt;span class="nt"&gt;--recursive&lt;/span&gt; |
  &lt;span class="nb"&gt;grep &lt;/span&gt;terraform.tfstate |
  &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{ system("./run.sh " $4) }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it, just run it and wait for Terraform to do the rest.&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>devops</category>
      <category>cicd</category>
      <category>aws</category>
    </item>
    <item>
      <title>🚀 Fastest way to bundle JavaScript in 2023</title>
      <dc:creator>Dan L</dc:creator>
      <pubDate>Fri, 31 Mar 2023 18:20:53 +0000</pubDate>
      <link>https://dev.to/s1owjke/fastest-way-to-bundle-javascript-in-2023-2oml</link>
      <guid>https://dev.to/s1owjke/fastest-way-to-bundle-javascript-in-2023-2oml</guid>
      <description>&lt;p&gt;JavaScript bundlers are essential tools for modern web development. They handle all the routine tasks for building an application, which allows developers to focus on writing code. &lt;/p&gt;

&lt;p&gt;However, as applications grow in size and complexity, bundling performance can become a bottleneck, slowing down the deployment process and negatively impacting the overall developer experience.&lt;/p&gt;

&lt;p&gt;Luckily, we are now entering a new era of build tools written in high-performance languages like &lt;a href="https://go.dev/" rel="noopener noreferrer"&gt;Go&lt;/a&gt; or &lt;a href="https://www.rust-lang.org/" rel="noopener noreferrer"&gt;Rust&lt;/a&gt;. In this article, we will compare the speed and bundle size of the most popular bundlers across various configurations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Available options
&lt;/h2&gt;

&lt;p&gt;Despite the variety of available bundlers, most of them use the same packages for transpilation and minification.&lt;/p&gt;

&lt;p&gt;The first option is &lt;a href="https://babeljs.io" rel="noopener noreferrer"&gt;Babel&lt;/a&gt; and &lt;a href="https://terser.org" rel="noopener noreferrer"&gt;Terser&lt;/a&gt;, two popular JavaScript tools for transpiling and minifying code, respectively. They are often used together, and many popular toolkits such as &lt;a href="https://create-react-app.dev/" rel="noopener noreferrer"&gt;CRA&lt;/a&gt; (Create React App) are based on them. While both tools have large communities and are widely used, which makes it easy to find answers to most questions, their main drawback is their speed.&lt;/p&gt;

&lt;p&gt;The second option is &lt;a href="https://esbuild.github.io" rel="noopener noreferrer"&gt;Esbuild&lt;/a&gt;, a lightweight and extremely fast bundler and minifier developed by Evan Wallace. It also supports bundling of other web assets like CSS and images, and can be extended using a variety of plugins. Esbuild is written in Go, which enables it to be significantly faster than any JavaScript bundlers. It’s easy to configure and supports JSX syntax and TypeScript out of the box.&lt;/p&gt;

&lt;p&gt;And last but not least, &lt;a href="https://swc.rs" rel="noopener noreferrer"&gt;SWC&lt;/a&gt; is a popular compiler designed to be blazingly fast and efficient. It is written in Rust and maintained by the developer community. It can be used to transpile and minimize JavaScript or TypeScript code. Also worth noting is that the &lt;a href="https://swc.rs/docs/usage/bundling" rel="noopener noreferrer"&gt;swcpack&lt;/a&gt; bundler is currently under active development and it has all chances to become an extremely fast alternative to Webpack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benchmark
&lt;/h2&gt;

&lt;p&gt;The story of this performance benchmark began with an attempt to understand why it takes more than half a minute to build a relatively small application with &lt;a href="https://mui.com/" rel="noopener noreferrer"&gt;Material UI&lt;/a&gt; components and how to improve that.&lt;/p&gt;

&lt;p&gt;For tests I created several React projects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Empty as the baseline&lt;/li&gt;
&lt;li&gt;Project containing five different libraries with a large codebase commonly used in web development&lt;/li&gt;
&lt;li&gt;All components from Material UI&lt;/li&gt;
&lt;li&gt;Synthetic test with 5000 small components as a way to measure the overhead of the bundler itself&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Initially, the project with Material UI components also included an icons package, but after the first measurements I found a performance degradation in Rollup, so as not to distort the final results I removed it.&lt;/p&gt;

&lt;p&gt;To keep results accurate there are no other files that can require additional loaders or plugins, as the main goal is to measure time spent on JavaScript bundling not on CSS or other assets.&lt;/p&gt;

&lt;p&gt;The benchmark includes four bundlers in various configurations, all of them are configured as closely as possible (production build, no cache):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Esbuild as bundler without any extra plugins&lt;/li&gt;
&lt;li&gt;Parcel in its default configuration with Babel and Terser&lt;/li&gt;
&lt;li&gt;Rollup and Webpack in three different presets: Babel and Terser, Esbuild and SWC&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the testing environment I used Mac OS &lt;code&gt;11.5.2&lt;/code&gt; and Node &lt;code&gt;16.20.0&lt;/code&gt;, with the latest package versions at the time of writing this article.&lt;/p&gt;

&lt;p&gt;Tests were done on a 6-core 2019 MacBook Pro with 16gb of RAM. To ensure the accuracy of my measurements each test was run three times consecutively, the final results represent the average value. &lt;/p&gt;

&lt;p&gt;In addition, I have measured the size of the resulting bundle and its size after gzip compression with standard settings.&lt;/p&gt;

&lt;p&gt;All code is available in the &lt;a href="https://github.com/s1owjke/js-bundler-benchmark" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&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%2Fjstateha4xgfxxrbzvni.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%2Fjstateha4xgfxxrbzvni.png" alt="Time in sec"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Time in sec (average time for 3 runs)&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Empty&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Libraries&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Mui&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Synthetic&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Esbuild&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.046&lt;/td&gt;
&lt;td&gt;0.142&lt;/td&gt;
&lt;td&gt;0.192&lt;/td&gt;
&lt;td&gt;0.685&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Parcel: babel + terser&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3.737&lt;/td&gt;
&lt;td&gt;11.529&lt;/td&gt;
&lt;td&gt;8.892&lt;/td&gt;
&lt;td&gt;57.232&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rollup: babel + terser&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3.121&lt;/td&gt;
&lt;td&gt;13.056&lt;/td&gt;
&lt;td&gt;9.495&lt;/td&gt;
&lt;td&gt;37.689&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rollup: esbuild&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.874&lt;/td&gt;
&lt;td&gt;5.553&lt;/td&gt;
&lt;td&gt;5.746&lt;/td&gt;
&lt;td&gt;14.612&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rollup: swc&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.788&lt;/td&gt;
&lt;td&gt;5.966&lt;/td&gt;
&lt;td&gt;5.802&lt;/td&gt;
&lt;td&gt;14.644&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Webpack: babel + terser&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2.471&lt;/td&gt;
&lt;td&gt;11.529&lt;/td&gt;
&lt;td&gt;6.406&lt;/td&gt;
&lt;td&gt;23.889&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Webpack: esbuild&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.808&lt;/td&gt;
&lt;td&gt;3.145&lt;/td&gt;
&lt;td&gt;2.665&lt;/td&gt;
&lt;td&gt;8.798&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Webpack: swc&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.849&lt;/td&gt;
&lt;td&gt;4.033&lt;/td&gt;
&lt;td&gt;2.927&lt;/td&gt;
&lt;td&gt;9.134&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Bundle size in KiB&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Empty&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Libraries&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Mui&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Synthetic&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Esbuild&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;164.60&lt;/td&gt;
&lt;td&gt;1239.04&lt;/td&gt;
&lt;td&gt;607.99&lt;/td&gt;
&lt;td&gt;1008.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Parcel: babel + terser&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;348.28&lt;/td&gt;
&lt;td&gt;1546.24&lt;/td&gt;
&lt;td&gt;950.09&lt;/td&gt;
&lt;td&gt;1351.68&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rollup: babel + terser&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;157.85&lt;/td&gt;
&lt;td&gt;1454.08&lt;/td&gt;
&lt;td&gt;592.64&lt;/td&gt;
&lt;td&gt;786.78&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rollup: esbuild&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;163.61&lt;/td&gt;
&lt;td&gt;1239.04&lt;/td&gt;
&lt;td&gt;621.77&lt;/td&gt;
&lt;td&gt;816.58&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rollup: swc&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;166.95&lt;/td&gt;
&lt;td&gt;1351.68&lt;/td&gt;
&lt;td&gt;712.35&lt;/td&gt;
&lt;td&gt;1064.96&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Webpack: babel + terser&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;158.33&lt;/td&gt;
&lt;td&gt;1464.32&lt;/td&gt;
&lt;td&gt;593.95&lt;/td&gt;
&lt;td&gt;868.48&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Webpack: esbuild&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;166.17&lt;/td&gt;
&lt;td&gt;1617.92&lt;/td&gt;
&lt;td&gt;613.37&lt;/td&gt;
&lt;td&gt;891.19&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Webpack: swc&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;163.00&lt;/td&gt;
&lt;td&gt;1454.08&lt;/td&gt;
&lt;td&gt;600.74&lt;/td&gt;
&lt;td&gt;878.15&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Bundle size after gzip in KiB&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Empty&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Libraries&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Mui&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Synthetic&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Esbuild&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;54.75&lt;/td&gt;
&lt;td&gt;367.50&lt;/td&gt;
&lt;td&gt;183.51&lt;/td&gt;
&lt;td&gt;132.16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Parcel: babel + terser&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;106.91&lt;/td&gt;
&lt;td&gt;424.13&lt;/td&gt;
&lt;td&gt;264.39&lt;/td&gt;
&lt;td&gt;139.05&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rollup: babel + terser&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;52.81&lt;/td&gt;
&lt;td&gt;353.12&lt;/td&gt;
&lt;td&gt;173.57&lt;/td&gt;
&lt;td&gt;67.34&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rollup: esbuild&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;54.68&lt;/td&gt;
&lt;td&gt;368.10&lt;/td&gt;
&lt;td&gt;185.70&lt;/td&gt;
&lt;td&gt;84.23&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rollup: swc&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;54.24&lt;/td&gt;
&lt;td&gt;368.08&lt;/td&gt;
&lt;td&gt;190.88&lt;/td&gt;
&lt;td&gt;93.57&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Webpack: babel + terser&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;52.90&lt;/td&gt;
&lt;td&gt;407.58&lt;/td&gt;
&lt;td&gt;175.36&lt;/td&gt;
&lt;td&gt;84.42&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Webpack: esbuild&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;56.04&lt;/td&gt;
&lt;td&gt;445.32&lt;/td&gt;
&lt;td&gt;185.35&lt;/td&gt;
&lt;td&gt;86.71&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Webpack: swc&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;54.49&lt;/td&gt;
&lt;td&gt;409.35&lt;/td&gt;
&lt;td&gt;178.29&lt;/td&gt;
&lt;td&gt;93.34&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;p&gt;Esbuild as a bundler currently is significantly faster than others, it will be fascinating to see how it compares to swcpack in the future, but at the moment it's the ultimate winner.&lt;/p&gt;

&lt;p&gt;When we consider Esbuild and SWC as plugins with other bundlers, there is really not much difference between them, it completely depends on the specific configuration, detailed comparison between them you can &lt;a href="https://swc.rs/docs/benchmarks" rel="noopener noreferrer"&gt;find here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A couple of words about Parcel, when I tried to build 10 copies of &lt;a href="https://threejs.org" rel="noopener noreferrer"&gt;three.js&lt;/a&gt; my results were completely identical to &lt;a href="https://esbuild.github.io/faq/#benchmark-details" rel="noopener noreferrer"&gt;Esbuild benchmark&lt;/a&gt;, it really was the fastest, but for React application the metrics are different.&lt;/p&gt;

&lt;p&gt;The unpleasant discovery for me was the build time of Rollup, on a large number of files/imports it shows worse results even than Webpack.&lt;/p&gt;

&lt;p&gt;So, what to choose for React app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To achieve maximum performance and if you don't care about &lt;a href="https://webpack.js.org/concepts/hot-module-replacement/" rel="noopener noreferrer"&gt;HMR&lt;/a&gt; support consider using Esbuild as bundler&lt;/li&gt;
&lt;li&gt;If you are already using Webpack, you can simply improve the build speed by using Esbuild or SWC as a loader and minimizer, in this case you can keep using CRA configuration&lt;/li&gt;
&lt;li&gt;If you really need HMR you can use combination of the previous options, Esbuild for production, Webpack + Esbuild loader for development (don’t use different tools for dev and production builds, there is a chance that the generated code may be different)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>performance</category>
      <category>tooling</category>
      <category>react</category>
    </item>
  </channel>
</rss>
