<?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: genuineswe</title>
    <description>The latest articles on Forem by genuineswe (@genuineswe).</description>
    <link>https://forem.com/genuineswe</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%2F201967%2Fc327c548-0540-4f1d-987e-0b12c6978c99.jpeg</url>
      <title>Forem: genuineswe</title>
      <link>https://forem.com/genuineswe</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/genuineswe"/>
    <language>en</language>
    <item>
      <title>My New Developer Spent 2 Hours on Our README. Docker Fixed It in 5 Minutes.</title>
      <dc:creator>genuineswe</dc:creator>
      <pubDate>Thu, 16 Apr 2026 07:00:36 +0000</pubDate>
      <link>https://forem.com/genuineswe/my-new-developer-spent-2-hours-on-our-readme-docker-fixed-it-in-5-minutes-17in</link>
      <guid>https://forem.com/genuineswe/my-new-developer-spent-2-hours-on-our-readme-docker-fixed-it-in-5-minutes-17in</guid>
      <description>&lt;p&gt;Last month, a new developer joined our team.&lt;br&gt;
I pointed them to the project README.&lt;br&gt;
It had 15 steps to set up the environment.&lt;br&gt;
By lunch, they were still stuck on step 4.&lt;/p&gt;

&lt;p&gt;Their Node version was 20.&lt;br&gt;
The project needed Node 16.&lt;br&gt;
They had a Windows machine.&lt;br&gt;
I was on a Mac.&lt;br&gt;
The "Standard Setup" was a myth.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Wrong Approach
&lt;/h2&gt;

&lt;p&gt;For months, I tried to solve this with documentation.&lt;br&gt;
I added more "Note:" sections to the README.&lt;br&gt;
I shared my &lt;code&gt;.nvmrc&lt;/code&gt; file.&lt;br&gt;
I even wrote a setup script in Bash.&lt;/p&gt;

&lt;p&gt;But documentation is what &lt;em&gt;The Pragmatic Programmer&lt;/em&gt; calls &lt;strong&gt;Knowledge that Rots&lt;/strong&gt;.&lt;br&gt;
Every time we updated a package, the README broke.&lt;br&gt;
The principle of "Don't Repeat Yourself" applies to setups too.&lt;br&gt;
I was repeating the same manual fixes for every new hire.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Effort&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Writing long READMEs&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Quickly outdated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom Bash scripts&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;OS-dependent issues&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Screen-sharing walkthroughs&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Total time sink&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h2&gt;
  
  
  The Realization
&lt;/h2&gt;

&lt;p&gt;I realized that a README is just a wish list.&lt;br&gt;
It &lt;em&gt;hopes&lt;/em&gt; the developer has the right tools.&lt;br&gt;
I needed to provide the &lt;em&gt;actual&lt;/em&gt; environment.&lt;/p&gt;

&lt;p&gt;In &lt;em&gt;The Pragmatic Programmer&lt;/em&gt;, Hunt and Thomas call this &lt;strong&gt;Orthogonality&lt;/strong&gt; — reducing hidden dependencies between components.&lt;br&gt;
My application code was tied too closely to my global OS.&lt;br&gt;
If I updated my system, I broke my app.&lt;br&gt;
I needed a boundary.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Correct Approach
&lt;/h2&gt;

&lt;p&gt;I replaced the 15-step README with one &lt;code&gt;Dockerfile&lt;/code&gt;.&lt;br&gt;
This file defines the operating system, Node version, and dependencies.&lt;br&gt;
It is the single source of truth for the environment.&lt;/p&gt;

&lt;p&gt;First, a &lt;code&gt;.dockerignore&lt;/code&gt; file to keep the image clean:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# .dockerignore
node_modules
dist
.git
.env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;This works like &lt;code&gt;.gitignore&lt;/code&gt; — it prevents Docker from copying unnecessary files into your image. Without it, your 50MB project becomes a 500MB image.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Then the &lt;code&gt;Dockerfile&lt;/code&gt; itself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:18-alpine&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package.json package-lock.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 5173&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["npm", "run", "dev", "--", "--host"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;The &lt;code&gt;--host&lt;/code&gt; flag is critical. Vite's dev server binds to &lt;code&gt;localhost&lt;/code&gt; by default, which is unreachable from outside the container. Adding &lt;code&gt;--host&lt;/code&gt; binds it to &lt;code&gt;0.0.0.0&lt;/code&gt;, making it accessible on your machine at &lt;code&gt;localhost:5173&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For full-stack features, I used &lt;strong&gt;Docker Compose&lt;/strong&gt;.&lt;br&gt;
Instead of telling devs to "install Redis locally," I just added it to the config.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5173:5173"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.:/app&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/app/node_modules&lt;/span&gt;
  &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis:alpine&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;The &lt;code&gt;volumes&lt;/code&gt; section syncs your local code to the container in real time. Edit a file in VS Code and Vite hot-reloads instantly — no rebuild needed. The second volume (&lt;code&gt;/app/node_modules&lt;/code&gt;) prevents your local &lt;code&gt;node_modules&lt;/code&gt; from overwriting the container's.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Results
&lt;/h2&gt;

&lt;p&gt;I asked that same new developer to try the Docker setup instead.&lt;br&gt;
They ran &lt;code&gt;docker compose up&lt;/code&gt;.&lt;br&gt;
The environment was ready in minutes.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before Docker&lt;/th&gt;
&lt;th&gt;After Docker&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;First install&lt;/td&gt;
&lt;td&gt;2 hours&lt;/td&gt;
&lt;td&gt;5 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local OS pollution&lt;/td&gt;
&lt;td&gt;High (Global DBs)&lt;/td&gt;
&lt;td&gt;Zero&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Environment drift&lt;/td&gt;
&lt;td&gt;Constant&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Reflection
&lt;/h2&gt;

&lt;p&gt;Consistency is a feature.&lt;br&gt;
We spend too much time on "Incidental Complexity" — problems we accidentally create for ourselves.&lt;br&gt;
Setting up a dev environment shouldn't be a test of patience.&lt;br&gt;
Docker is just a better way to communicate requirements.&lt;/p&gt;

&lt;p&gt;John Ousterhout writes in &lt;em&gt;A Philosophy of Software Design&lt;/em&gt; that the best way to deal with complexity is to &lt;strong&gt;eliminate it, not manage it&lt;/strong&gt;.&lt;br&gt;
A 15-step README &lt;em&gt;manages&lt;/em&gt; the complexity. A Dockerfile &lt;em&gt;eliminates&lt;/em&gt; it.&lt;/p&gt;

&lt;p&gt;It isn't about being a DevOps expert.&lt;br&gt;
It is about being a professional who values their time.&lt;br&gt;
Keep your laptop clean.&lt;br&gt;
Containers are the modern README.&lt;/p&gt;




&lt;h2&gt;
  
  
  Your Next Step
&lt;/h2&gt;

&lt;p&gt;Check your project's README today.&lt;br&gt;
Count how many steps are just environment setup.&lt;br&gt;
Try to move the first three steps into a &lt;code&gt;Dockerfile&lt;/code&gt;.&lt;br&gt;
Run it locally and see if you can delete those lines from your documentation.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Have you replaced documentation with Docker in your workflow? I'd love to hear what worked (or didn't) in the comments below.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How I Took My PageSpeed Score from 35 to 92...</title>
      <dc:creator>genuineswe</dc:creator>
      <pubDate>Wed, 25 Mar 2026 07:17:07 +0000</pubDate>
      <link>https://forem.com/genuineswe/pagespeed-35-to-90-what-i-got-wrong-then-right-1o2m</link>
      <guid>https://forem.com/genuineswe/pagespeed-35-to-90-what-i-got-wrong-then-right-1o2m</guid>
      <description>&lt;p&gt;Have you ever shipped a feature you were really proud of, only to watch your PageSpeed score sit at a painful &lt;strong&gt;35&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;That was me. My app worked fine locally. But once deployed, Lighthouse painted the screen red. Users noticed too: "Why is this so slow?"&lt;/p&gt;

&lt;p&gt;This is the story of how I diagnosed the problem, wasted time on the wrong fix, and eventually pushed the score past &lt;strong&gt;90&lt;/strong&gt;. If you've ever stared at a bad Lighthouse report and didn't know where to start, this one's for you.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Was Actually Wrong
&lt;/h2&gt;

&lt;p&gt;Before jumping into fixes, I needed to understand what was happening. I opened Chrome DevTools, ran Lighthouse, and found three clear issues:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Issue&lt;/th&gt;
&lt;th&gt;What I Found&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Huge JS bundle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;main.js&lt;/code&gt; was over 2MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Render-blocking resources&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Components loaded upfront even when users didn't need them yet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Unoptimized images&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;PNG/JPEG files, some over 1MB each&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip for fellow devs:&lt;/strong&gt; Before optimizing anything, always run Lighthouse first. It tells you exactly where the bottleneck is. Don't guess.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This step alone saved me hours. In &lt;em&gt;The Pragmatic Programmer&lt;/em&gt;, Hunt and Thomas call this &lt;strong&gt;"Don't Assume It — Prove It."&lt;/strong&gt; It's tempting to jump straight into fixing things based on gut feeling, but the data almost always tells a different story than you expect.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Tried First (And Why It Failed)
&lt;/h2&gt;

&lt;p&gt;My instinct was to compress everything. I spent hours tweaking &lt;code&gt;Terser&lt;/code&gt; settings and adding image compression plugins to my build pipeline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; Score went from 35 to... 42. That's it.&lt;/p&gt;

&lt;p&gt;Here's what I got wrong: compressing a 2MB bundle down to 1.8MB still means the browser has to &lt;strong&gt;parse and execute 1.8MB of JavaScript&lt;/strong&gt; before the page becomes interactive. I was treating the symptom, not the cause.&lt;/p&gt;

&lt;p&gt;In hindsight, I was doing what &lt;em&gt;The Pragmatic Programmer&lt;/em&gt; warns against: &lt;strong&gt;"Programming by Coincidence"&lt;/strong&gt; — making changes and hoping something improves without truly understanding the underlying problem. The config tweaks felt productive, but I had no clear mental model of &lt;em&gt;why&lt;/em&gt; the page was slow.&lt;/p&gt;

&lt;p&gt;The real question wasn't &lt;em&gt;"How do I make this smaller?"&lt;/em&gt; It was &lt;em&gt;"Does the user actually need all of this right now?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That reframe is what John Ousterhout describes in &lt;em&gt;A Philosophy of Software Design&lt;/em&gt; as tackling &lt;strong&gt;complexity at its source&lt;/strong&gt; rather than patching around it. The bundle wasn't too big because it lacked compression. It was too big because it was loading things nobody asked for.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Actually Worked
&lt;/h2&gt;

&lt;p&gt;Once I reframed the problem, three changes made the biggest difference:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Code Splitting by Route
&lt;/h3&gt;

&lt;p&gt;Instead of shipping the entire app in one bundle, I split it so each page only loads what it needs.&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="c1"&gt;// Before: everything loads at once&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Dashboard&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pages/Dashboard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Settings&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pages/Settings&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// After: each page loads on demand&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Suspense&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lazy&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&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;Dashboard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pages/Dashboard&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;Settings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pages/Settings&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Suspense&lt;/span&gt; &lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Loading&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;}&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Routes&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/dashboard&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Dashboard&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/settings&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Settings&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Routes&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Suspense&lt;/span&gt;&lt;span class="err"&gt;&amp;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;&lt;strong&gt;Why this works:&lt;/strong&gt; The user visiting &lt;code&gt;/dashboard&lt;/code&gt; doesn't download the code for &lt;code&gt;/settings&lt;/code&gt;. Simple, but the impact is massive.&lt;/p&gt;

&lt;p&gt;This is the &lt;strong&gt;YAGNI principle&lt;/strong&gt; &lt;em&gt;(You Aren't Gonna Need It)&lt;/em&gt; applied to delivery: don't send the browser code it doesn't need yet. Martin Fowler and Kent Beck popularized YAGNI for writing code, but it applies just as well to &lt;em&gt;shipping&lt;/em&gt; code.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Lazy Loading Images
&lt;/h3&gt;

&lt;p&gt;Images below the fold don't need to load immediately. HTML5 makes this a one-liner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Above the fold: load immediately --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"hero.webp"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Hero banner"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Below the fold: load when user scrolls --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"footer-graphic.webp"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Footer"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No library needed. Just one attribute.&lt;/p&gt;

&lt;p&gt;Robert C. Martin writes in &lt;em&gt;Clean Code&lt;/em&gt; that &lt;strong&gt;"the best code is no code at all."&lt;/strong&gt; The same idea applies here: the best optimization is often the simplest one. A single HTML attribute replaced what used to require a JavaScript library with scroll listeners.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Switching to WebP
&lt;/h3&gt;

&lt;p&gt;I converted all images from PNG/JPEG to WebP, with a fallback for older browsers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"photo.webp"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/webp"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"photo.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Example"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;WebP files are typically 25-35% smaller&lt;/strong&gt; than JPEG at the same quality. Multiply that across every image on your site and the savings add up fast.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Results
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Initial Bundle Size&lt;/td&gt;
&lt;td&gt;2.2 MB&lt;/td&gt;
&lt;td&gt;340 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;First Contentful Paint&lt;/td&gt;
&lt;td&gt;4.2s&lt;/td&gt;
&lt;td&gt;0.8s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PageSpeed Score&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;35&lt;/strong&gt; 🔴&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;92&lt;/strong&gt; 🟢&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;The biggest takeaway wasn't about any specific tool or technique. It was a mindset shift:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance optimization isn't about making things smaller. It's about loading the right things at the right time.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The Pragmatic Programmer&lt;/em&gt; has a concept called &lt;strong&gt;"Tracer Bullets"&lt;/strong&gt; — find the path that lights up the whole system, then iterate. Applied to performance work, this means: identify the critical rendering path first. Everything that isn't on that path can wait.&lt;/p&gt;

&lt;p&gt;Before applying any optimization, ask yourself: &lt;em&gt;"Does the user need this resource right now?"&lt;/em&gt; If the answer is no, defer it.&lt;/p&gt;

&lt;p&gt;Three things that made the real difference:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Code Splitting&lt;/strong&gt; — only ship the JS the user actually needs &lt;em&gt;(YAGNI)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lazy Loading&lt;/strong&gt; — defer images and components below the fold &lt;em&gt;(simplicity over cleverness)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modern Formats&lt;/strong&gt; — use WebP instead of legacy image formats&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you're facing a similar problem, start with a Lighthouse audit. Look at what's blocking your initial load. Chances are, the fix isn't compression — it's prioritization.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Kaizen"&lt;/em&gt; — the Japanese philosophy of continuous, small improvements — is how I think about performance now. You don't need a massive rewrite. A few targeted changes, guided by data, can transform your app.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;strong&gt;Your action step:&lt;/strong&gt; Open your app right now. Run Lighthouse. Check what your biggest bundle is. If it's over 500KB, try code splitting that one route first. Come back and tell me what happened in the comments.&lt;/p&gt;

</description>
      <category>webperf</category>
      <category>react</category>
      <category>javascript</category>
      <category>engineering</category>
    </item>
  </channel>
</rss>
