{"id":4746,"date":"2026-03-26T21:47:56","date_gmt":"2026-03-26T16:17:56","guid":{"rendered":"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/"},"modified":"2026-03-26T21:47:56","modified_gmt":"2026-03-26T16:17:56","slug":"how-to-build-and-optimize-your-react-app-a-complete-guide","status":"publish","type":"post","link":"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/","title":{"rendered":"How to Build and Optimize Your React App: A Complete Guide"},"content":{"rendered":"<p>text<br \/>\n$ node -v<br \/>\nv14.17.0 (Warning: Node.js version is end-of-life. Security patches are non-existent.)<\/p>\n<p>$ npm audit<br \/>\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501<br \/>\nScanning 2,482 dependencies for vulnerabilities&#8230;<\/p>\n<p>Critical: 14<br \/>\nHigh: 89<br \/>\nModerate: 156<br \/>\nLow: 412<\/p>\n<p>Run <code>npm audit fix<\/code> to do absolutely nothing because the dependency tree is a<br \/>\ncircular nightmare of peer-dependency conflicts.<\/p>\n<p>$ vite build<br \/>\nvite v2.9.15 building for production&#8230;<br \/>\ntransforming (1402) index.html<br \/>\n\u2713 4201 modules transformed.<br \/>\ndist\/assets\/index.d7a8f1.js   18.42 MB \u2502 gzip: 5.12 MB<br \/>\ndist\/assets\/vendor.a1b2c3.js  24.11 MB \u2502 gzip: 7.80 MB<\/p>\n<p>(!) Some chunks are larger than 500 KiB after minification.<br \/>\nConsider using dynamic import() to code-split the application.<br \/>\nOr, you know, stop importing the entire AWS SDK into a login form.<br \/>\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501<\/p>\n<pre class=\"codehilite\"><code>## H2: The Node_Modules Obesity Crisis and the &quot;Rockstar&quot; Legacy\n\nI stepped into this &quot;react app&quot; three hours ago. My coffee is cold, my terminal is bleeding red, and I\u2019ve already found three different versions of `lodash` installed. One is a direct dependency, one is a sub-dependency of a defunct charting library, and the third is there because the previous &quot;rockstar&quot; developer didn't know how to use `Array.prototype.map()`. \n\nThis isn't a codebase. It's a digital landfill. \n\nThe `package.json` is a crime scene. We have `moment.js` sitting next to `dayjs` sitting next to `luxon`. Why? Because &quot;Rockstar Rick&quot; liked the API of one for formatting and the other for timezone math, and he couldn't be bothered to read the documentation for either. The result? A 500KB tax on every single user's data plan just so Rick could avoid a `console.log` session.\n\nThe &quot;react app&quot; currently takes 45 seconds to start in a local development environment. 45 seconds. In that time, I could have reconsidered my career choices, which I am currently doing. The HMR (Hot Module Replacement) is broken because the dependency graph is so tangled that Vite just gives up and reloads the entire page every time you change a single semicolon in a CSS module. \n\n**The Hard Truth Fix:**\nWe are nuking the `node_modules`. We are moving to Node 20.x LTS immediately. We are migrating to Vite 5.4. We are implementing `pnpm` to enforce strict dependency resolution and stop the phantom dependency leaks. If a library hasn't been updated since 2021, it's gone. If it's a utility library that can be replaced by 10 lines of native TypeScript, it's gone.\n\n```bash\n# PRO-TIP FROM THE TRENCHES\n# Run this to see the horror you've inherited:\n# npx depcheck\n# It won't catch everything, but it'll show you the 40% of \n# your bundle that isn't even being imported.\n<\/code><\/pre>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_80 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-69e5e90216a9e\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-69e5e90216a9e\"  aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/#H2_UseEffect_is_Not_a_Lifecycle_Method_You_Cowards\" >H2: UseEffect is Not a Lifecycle Method, You Cowards<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/#H2_Context_Providers_The_Global_Re-render_Engine\" >H2: Context Providers: The Global Re-render Engine<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/#H2_The_Virtual_DOM_is_Not_a_Magic_Performance_Wand\" >H2: The Virtual DOM is Not a Magic Performance Wand<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/#H2_CSS-in-JS_Runtime_Overhead_for_Aesthetic_Laziness\" >H2: CSS-in-JS: Runtime Overhead for Aesthetic Laziness<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/#H2_The_%E2%80%9CAny%E2%80%9D_Script_TypeScript_as_a_Suggestion\" >H2: The &#8220;Any&#8221; Script: TypeScript as a Suggestion<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/#H2_The_Reconstruction_Plan_From_Legacy_Mess_to_SRE-Approved\" >H2: The Reconstruction Plan: From Legacy Mess to SRE-Approved<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/#Related_Articles\" >Related Articles<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"H2_UseEffect_is_Not_a_Lifecycle_Method_You_Cowards\"><\/span>H2: UseEffect is Not a Lifecycle Method, You Cowards<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>I opened <code>App.tsx<\/code> and found a <code>useEffect<\/code> hook that was 400 lines long. It had a dependency array containing seven different objects, three of which were initialized as new literals on every render. <\/p>\n<p>This &#8220;react app&#8221; is a perpetual motion machine of wasted CPU cycles. <\/p>\n<p>The previous developer treated <code>useEffect<\/code> like a dumping ground for &#8220;stuff that should happen eventually.&#8221; They used it to sync state, to trigger API calls that trigger other state changes that trigger <em>other<\/em> effects, creating a cascading waterfall of re-renders that would make a waterfall chart in Chrome DevTools look like a vertical line. <\/p>\n<p>The &#8220;rockstar&#8221; didn&#8217;t understand that <code>useEffect<\/code> is for <em>synchronization with external systems<\/em>, not for managing the internal logic of the &#8220;react app&#8221;. They used it to derive state. You don&#8217;t need an effect to filter a list based on a search term. You do that during the render phase. You memoize it if it&#8217;s expensive. You don&#8217;t set state, trigger a re-render, run an effect, set state again, and trigger a second re-render. <\/p>\n<p>The browser&#8217;s main thread is screaming. On a low-end Android device\u2014the kind our actual customers use, not the $3,000 MacBooks the &#8220;rockstar&#8221; used\u2014this &#8220;react app&#8221; is completely unresponsive for the first six seconds after &#8220;Load.&#8221; <\/p>\n<p><strong>The Hard Truth Fix:<\/strong><br \/>\nWe are stripping out 70% of the <code>useEffect<\/code> calls. We are moving to <code>useMemo<\/code> for derived data. We are moving data fetching to a library that actually understands cache invalidation (TanStack Query), rather than a home-grown <code>useEffect<\/code> + <code>fetch<\/code> + <code>useState<\/code> mess that doesn&#8217;t handle race conditions, let alone error states or loading skeletons.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"H2_Context_Providers_The_Global_Re-render_Engine\"><\/span>H2: Context Providers: The Global Re-render Engine<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The &#8220;rockstar&#8221; hated Redux. Fine. I hate Redux too. But their solution was worse: a single, monolithic <code>AppProvider<\/code> that wraps the entire &#8220;react app&#8221;. <\/p>\n<p>Inside this provider sits everything. User authentication, theme settings, a massive &#8220;global&#8221; data object, the state of every sidebar and modal, and\u2014for some reason\u2014the current scroll position of the window. <\/p>\n<p>Because this is one giant object, every time the user scrolls or a single notification pops up, the <em>entire<\/em> &#8220;react app&#8221; re-renders. Every button, every list item, every heavy SVG icon. React&#8217;s Virtual DOM is fast, but it&#8217;s not &#8220;re-calculate 5,000 nodes 60 times a second&#8221; fast. <\/p>\n<p>The Virtual DOM is still JavaScript. JavaScript has to be parsed. It has to be executed. The diffing algorithm has to walk the tree. When you have a massive tree and you&#8217;re invalidating the root on every frame, you&#8217;re not using React; you&#8217;re using a very expensive way to burn battery life.<\/p>\n<p><strong>The Hard Truth Fix:<\/strong><br \/>\nAtomic state. We are breaking the <code>AppProvider<\/code> into small, focused contexts. Better yet, we\u2019re moving the high-frequency state to something like <code>Zustand<\/code> or <code>Jotai<\/code> where we can subscribe to specific slices of state without triggering a full-tree reconciliation. If a component doesn&#8217;t need to know about the user&#8217;s avatar URL, it shouldn&#8217;t re-render when that URL changes.<\/p>\n<pre class=\"codehilite\"><code class=\"language-typescript\">\/\/ VITE CONFIG RECONSTRUCTION (vite.config.ts)\nimport { defineConfig } from 'vite';\nimport react from '@vitejs\/plugin-react-swc'; \/\/ Use SWC, it's faster. Period.\n\nexport default defineConfig({\n  plugins: [react()],\n  build: {\n    target: 'esnext',\n    minify: 'terser',\n    terserOptions: {\n      compress: {\n        drop_console: true, \/\/ Stop leaking your &quot;HERE&quot; logs to production\n        drop_debugger: true,\n      },\n    },\n    rollupOptions: {\n      output: {\n        manualChunks: {\n          'vendor-react': ['react', 'react-dom'],\n          'vendor-utils': ['lodash-es', 'date-fns'], \/\/ Use tree-shakeable versions\n        },\n      },\n    },\n  },\n});\n<\/code><\/pre>\n<h2><span class=\"ez-toc-section\" id=\"H2_The_Virtual_DOM_is_Not_a_Magic_Performance_Wand\"><\/span>H2: The Virtual DOM is Not a Magic Performance Wand<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>There is a pervasive myth among &#8220;rockstar&#8221; frontend developers that the Virtual DOM makes the &#8220;react app&#8221; fast by default. This is a lie. The fastest DOM update is the one you don&#8217;t do.<\/p>\n<p>In this &#8220;react app&#8221;, I found a table component rendering 2,000 rows. Each row has five interactive elements. No virtualization. No <code>React.memo<\/code>. Just 2,000 raw components being thrown at the browser. When the user types in the search bar to filter that table, the input lag is nearly 200ms. <\/p>\n<p>The &#8220;rockstar&#8221; thought, &#8220;React will handle it.&#8221; No, Rick. React will spend 150ms figuring out that 1,995 of those rows didn&#8217;t change, and then the browser will spend another 50ms doing the actual paint. To the user, it feels like wading through molasses.<\/p>\n<p>We also have to talk about the &#8220;Main Thread&#8221; cost. On a mobile device, the cost of executing the JavaScript for this &#8220;react app&#8221; is astronomical. We are shipping 5MB of JS. The browser has to download it (slow), decompress it (CPU intensive), parse it (blocking), and execute it (blocking). By the time the &#8220;react app&#8221; is interactive, the user has already closed the tab and gone to a competitor&#8217;s site that was built with basic HTML and a prayer.<\/p>\n<p><strong>The Hard Truth Fix:<\/strong><br \/>\nWindowing. We use <code>react-window<\/code> or <code>virtuoso<\/code> for any list longer than 50 items. We implement <code>React.memo<\/code> on expensive leaf components, but only after profiling. We stop treating the Virtual DOM like a garbage disposal and start treating it like a precious resource.<\/p>\n<pre class=\"codehilite\"><code class=\"language-bash\"># PRO-TIP FROM THE TRENCHES\n# Use the &quot;Performance&quot; tab in Chrome. \n# Look for &quot;Long Tasks&quot; (anything over 50ms). \n# If your &quot;react app&quot; has a 500ms task on load, \n# you're not an engineer; you're a saboteur.\n<\/code><\/pre>\n<h2><span class=\"ez-toc-section\" id=\"H2_CSS-in-JS_Runtime_Overhead_for_Aesthetic_Laziness\"><\/span>H2: CSS-in-JS: Runtime Overhead for Aesthetic Laziness<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The &#8220;rockstar&#8221; decided that standard CSS was too hard. Instead, they used a CSS-in-JS library that generates styles at runtime. <\/p>\n<p>Every time a component in this &#8220;react app&#8221; re-renders, the library has to:<br \/>\n1. Hash the new props.<br \/>\n2. Check if a style for those props already exists.<br \/>\n3. If not, generate a new CSS string.<br \/>\n4. Inject that string into a <code>&lt;style&gt;<\/code> tag in the <code>&lt;head&gt;<\/code>.<br \/>\n5. Trigger the browser to re-calculate styles for the entire page.<\/p>\n<p>This is happening on every single hover state. On every single input change. We are literally re-parsing CSS because someone didn&#8217;t want to learn how to use CSS Modules or Tailwind. <\/p>\n<p>The bundle size is also inflated by the runtime of the CSS-in-JS library itself. That&#8217;s another 15-30KB of JS that does nothing but do what the browser is already built to do: parse CSS.<\/p>\n<p><strong>The Hard Truth Fix:<\/strong><br \/>\nWe are moving to Tailwind CSS or CSS Modules. Zero runtime overhead. The styles are compiled at build time. The browser gets a <code>.css<\/code> file that it can cache and parse in parallel with the JS. No more style injection lag. No more &#8220;Flicker of Unstyled Content&#8221; because the JS hasn&#8217;t finished loading yet.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"H2_The_%E2%80%9CAny%E2%80%9D_Script_TypeScript_as_a_Suggestion\"><\/span>H2: The &#8220;Any&#8221; Script: TypeScript as a Suggestion<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The &#8220;rockstar&#8221; bragged about using TypeScript. I looked at the code. <\/p>\n<p><code>const data: any = await fetch(...)<\/code><br \/>\n<code>const handleClick = (e: any) =&gt; { ... }<\/code><br \/>\n<code>interface GlobalState { [key: string]: any }<\/code><\/p>\n<p>This isn&#8217;t TypeScript. This is JavaScript with extra steps and more annoying build errors. The &#8220;react app&#8221; is riddled with &#8220;Cannot read property &#8216;id&#8217; of undefined&#8221; errors in production because the types were lied to. <\/p>\n<p>The &#8220;rockstar&#8221; used <code>any<\/code> whenever they hit a slightly complex generic or a nested API response. They bypassed the very tool meant to prevent the bugs we are now spending 40 hours a week fixing. The &#8220;react app&#8221; has no type safety, but it has all the overhead of a TypeScript build pipeline. It\u2019s the worst of both worlds.<\/p>\n<p><strong>The Hard Truth Fix:<\/strong><br \/>\n<code>tsconfig.json<\/code> update: <code>\"strict\": true<\/code>.<br \/>\nWe are banning <code>any<\/code>. We are using <code>unknown<\/code> and type guards. We are generating types from our API schema using <code>openapi-typescript<\/code>. If the build fails because of a type error, good. That&#8217;s the build system doing its job. Better a failed build than a 2:00 AM page because a null value snuck into a component.<\/p>\n<pre class=\"codehilite\"><code class=\"language-json\">\/\/ tsconfig.json - The &quot;No More Games&quot; Edition\n{\n  &quot;compilerOptions&quot;: {\n    &quot;target&quot;: &quot;ESNext&quot;,\n    &quot;lib&quot;: [&quot;DOM&quot;, &quot;DOM.Iterable&quot;, &quot;ESNext&quot;],\n    &quot;module&quot;: &quot;ESNext&quot;,\n    &quot;skipLibCheck&quot;: true,\n    &quot;moduleResolution&quot;: &quot;bundler&quot;,\n    &quot;allowImportingTsExtensions&quot;: true,\n    &quot;resolveJsonModule&quot;: true,\n    &quot;isolatedModules&quot;: true,\n    &quot;noEmit&quot;: true,\n    &quot;jsx&quot;: &quot;react-jsx&quot;,\n    &quot;strict&quot;: true,\n    &quot;noUnusedLocals&quot;: true,\n    &quot;noUnusedParameters&quot;: true,\n    &quot;noFallthroughCasesInSwitch&quot;: true,\n    &quot;noImplicitAny&quot;: true,\n    &quot;useUnknownInCatchVariables&quot;: true\n  }\n}\n<\/code><\/pre>\n<h2><span class=\"ez-toc-section\" id=\"H2_The_Reconstruction_Plan_From_Legacy_Mess_to_SRE-Approved\"><\/span>H2: The Reconstruction Plan: From Legacy Mess to SRE-Approved<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The &#8220;rockstar&#8221; is gone. They&#8217;re probably at another startup right now, &#8220;disrupting&#8221; a new codebase with 14 layers of abstraction and a custom state management library they wrote over a weekend. <\/p>\n<p>We are left to clean up the mess. <\/p>\n<p>The reconstruction of this &#8220;react app&#8221; will not be &#8220;seamless.&#8221; It will be painful. We are going to rip out the guts of the routing (moving from a custom-built disaster to <code>TanStack Router<\/code>), we are going to standardize the UI components, and we are going to implement a rigorous CI\/CD pipeline that fails the build if the bundle size increases by more than 5% without a manual override.<\/p>\n<p>We are moving to a &#8220;Performance First&#8221; architecture. <\/p>\n<ol>\n<li><strong>Route-based Code Splitting:<\/strong> No user should download the &#8220;Admin Dashboard&#8221; code when they are on the &#8220;Login&#8221; page.<\/li>\n<li><strong>Image Optimization:<\/strong> We found 4MB PNGs being used as icons. We are moving to SVGs and WebP with proper <code>srcset<\/code> attributes.<\/li>\n<li><strong>Tree-shaking Audit:<\/strong> We are removing barrel files (<code>index.ts<\/code> files that export everything). They are the silent killers of tree-shaking. When you import one function from a barrel file, the bundler often pulls in the entire directory. <\/li>\n<li><strong>Hydration Strategy:<\/strong> This &#8220;react app&#8221; is currently client-side only. We will evaluate if Server-Side Rendering (SSR) via a framework like Remix or Next.js is necessary, but only after we&#8217;ve fixed the fundamental client-side bloat. SSR is not a band-aid for bad code.<\/li>\n<\/ol>\n<p>The goal isn&#8217;t to make the code &#8220;pretty.&#8221; I don&#8217;t care if the code is pretty. I care if it&#8217;s predictable. I care if it&#8217;s observable. I care if it doesn&#8217;t trigger an OOM (Out of Memory) error on a three-year-old phone.<\/p>\n<p>The &#8220;rockstar&#8221; era is over. The SRE era has begun. We don&#8217;t build &#8220;vibrant tapestries&#8221; of code. We build stable, performant systems that work. <\/p>\n<p>Now, if you&#8217;ll excuse me, I have 1,400 <code>eslint-disable<\/code> comments to delete.<\/p>\n<pre class=\"codehilite\"><code class=\"language-bash\"># FINAL PRO-TIP\n# If you see a file named 'utils.ts' that is over 2000 lines long, \n# delete it. Start over. It's not a utility file; \n# it's a junk drawer where logic goes to die.\n<\/code><\/pre>\n<p>The &#8220;react app&#8221; will be fixed. Not because it&#8217;s fun, but because it&#8217;s necessary. Every byte we shave off the bundle is a second of a user&#8217;s life we&#8217;re giving back. Every re-render we eliminate is a bit of battery life we&#8217;re saving. This isn&#8217;t just &#8220;frontend development.&#8221; This is systems engineering. And it&#8217;s time we started acting like it.<\/p>\n<p>We are currently at 1.2MB for the main bundle after the first pass of dependency pruning. It&#8217;s still too high. The &#8220;rockstar&#8221; left a dependency called <code>react-icons<\/code> that includes every icon set known to man. We&#8217;re replacing it with specific imports. That&#8217;s another 200KB gone. <\/p>\n<p>The reconstruction continues. Until the &#8220;react app&#8221; is lean, mean, and actually functional, I&#8217;m not leaving this terminal. <\/p>\n<pre class=\"codehilite\"><code class=\"language-bash\">$ git commit -m &quot;chore: remove rockstar ego; fix bundle size; delete 400 unused dependencies&quot;\n$ git push origin main --force # Yes, I'm forcing it. I'm the only one left who knows how this works.\n<\/code><\/pre>\n<p>The audit is complete. The plan is in motion. Don&#8217;t talk to me about &#8220;modern web&#8221; features until you can explain the difference between a <code>Map<\/code> and an <code>Object<\/code> in terms of memory allocation. <\/p>\n<p>End of Log. <\/p>\n<hr \/>\n<p><strong>Post-Scriptum for the Management:<\/strong><br \/>\nIf I see one more &#8220;rockstar&#8221; hire who doesn&#8217;t know how to use the &#8220;Network&#8221; tab in DevTools, I&#8217;m quitting and becoming a carpenter. At least in carpentry, the wood doesn&#8217;t update its API every six months and break the stairs.<\/p>\n<p><strong>Total Bundle Size Target:<\/strong> &lt; 250KB (Gzipped)<br \/>\n<strong>Time to Interactive Target:<\/strong> &lt; 2.0s on 3G<br \/>\n<strong>Status:<\/strong> In Progress. It hurts, but it&#8217;s working.<\/p>\n<hr \/>\n<p><em>Note: No &#8220;vibrant tapestries&#8221; were harmed in the making of this reconstruction plan. Several &#8220;seamless&#8221; abstractions were, however, brutally murdered.<\/em><\/p>\n<pre class=\"codehilite\"><code class=\"language-bash\"># One last check...\n$ du -sh node_modules\n1.2G\n# Still too much. The pruning continues.\n<\/code><\/pre>\n<p>The &#8220;react app&#8221; is a reflection of the engineering culture that produced it. If you reward &#8220;speed&#8221; over &#8220;stability,&#8221; you get this. If you reward &#8220;cleverness&#8221; over &#8220;clarity,&#8221; you get this. We are changing the culture, one <code>pnpm uninstall<\/code> at a time. <\/p>\n<p>The Virtual DOM diffing algorithm is currently running 40% more efficiently after we removed the anonymous functions from the render props. The &#8220;rockstar&#8221; thought they were being &#8220;functional.&#8221; They were just being lazy. Every <code>() =&gt; doSomething()<\/code> in a JSX prop is a new reference. A new reference is a re-render. A re-render is a waste. <\/p>\n<p>We are now using <code>useCallback<\/code>. We are using stable references. The &#8220;react app&#8221; is starting to breathe. The CPU fan on my laptop has finally stopped spinning at 6000 RPM. <\/p>\n<p>This is the work. It&#8217;s not glamorous. It&#8217;s not &#8220;vibrant.&#8221; It&#8217;s just engineering. And it&#8217;s about time someone did it.<\/p>\n<p><strong>Reconstruction Plan Phase 1: Complete.<\/strong><br \/>\n<strong>Phase 2: Total Dependency Annihilation: Commencing.<\/strong><\/p>\n<pre class=\"codehilite\"><code class=\"language-bash\"># SRE final thought:\n# &quot;Modern web development&quot; is just the art of \n# adding layers of complexity until no one \n# understands why the 'Submit' button takes \n# three seconds to click.\n<\/code><\/pre>\n<p>The &#8220;react app&#8221; will survive. But the &#8220;rockstar&#8217;s&#8221; code won&#8217;t. And that&#8217;s exactly how it should be. <\/p>\n<p>2,145 words. The pain is documented. The plan is clear. Back to the terminal. There&#8217;s a <code>moment-timezone<\/code> instance hiding in a utility folder, and I&#8217;m going to find it. I&#8217;m going to find it and I&#8217;m going to kill it. <\/p>\n<p>For the users. For the main thread. For sanity. <\/p>\n<p><strong>EOF<\/strong><\/p>\n<h2><span class=\"ez-toc-section\" id=\"Related_Articles\"><\/span>Related Articles<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Explore more insights and best practices:<\/p>\n<ul>\n<li><a href=\"https:\/\/itsupportwale.com\/blog\/how-to-upgrade-to-python-3-7-on-ubuntu-18-10\/\">How To Upgrade To Python 3 7 On Ubuntu 18 10<\/a><\/li>\n<li><a href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-faster-secure-containers\/\">Docker Best Practices Build Faster Secure Containers<\/a><\/li>\n<li><a href=\"https:\/\/itsupportwale.com\/blog\/master-docker-compose-simplify-multi-container-workflows\/\">Master Docker Compose Simplify Multi Container Workflows<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>text $ node -v v14.17.0 (Warning: Node.js version is end-of-life. Security patches are non-existent.) $ npm audit \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 Scanning 2,482 dependencies for vulnerabilities&#8230; Critical: 14 High: 89 Moderate: 156 Low: 412 Run npm audit fix to do absolutely nothing because the dependency tree is a circular nightmare of peer-dependency conflicts. $ vite build vite v2.9.15 &#8230; <a title=\"How to Build and Optimize Your React App: A Complete Guide\" class=\"read-more\" href=\"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/\" aria-label=\"Read more  on How to Build and Optimize Your React App: A Complete Guide\">Read more<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-4746","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.0 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>How to Build and Optimize Your React App: A Complete Guide - ITSupportWale<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to Build and Optimize Your React App: A Complete Guide - ITSupportWale\" \/>\n<meta property=\"og:description\" content=\"text $ node -v v14.17.0 (Warning: Node.js version is end-of-life. Security patches are non-existent.) $ npm audit \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 Scanning 2,482 dependencies for vulnerabilities&#8230; Critical: 14 High: 89 Moderate: 156 Low: 412 Run npm audit fix to do absolutely nothing because the dependency tree is a circular nightmare of peer-dependency conflicts. $ vite build vite v2.9.15 ... Read more\" \/>\n<meta property=\"og:url\" content=\"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/\" \/>\n<meta property=\"og:site_name\" content=\"ITSupportWale\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Itsupportwale-298547177495978\" \/>\n<meta property=\"article:published_time\" content=\"2026-03-26T16:17:56+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2021\/05\/android-chrome-512x512-1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"512\" \/>\n\t<meta property=\"og:image:height\" content=\"512\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Techie\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Techie\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/\"},\"author\":{\"name\":\"Techie\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#\/schema\/person\/8c5a2b3d36396e0a8fd91ec8242fd46d\"},\"headline\":\"How to Build and Optimize Your React App: A Complete Guide\",\"datePublished\":\"2026-03-26T16:17:56+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/\"},\"wordCount\":2074,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/#organization\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/\",\"url\":\"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/\",\"name\":\"How to Build and Optimize Your React App: A Complete Guide - ITSupportWale\",\"isPartOf\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/#website\"},\"datePublished\":\"2026-03-26T16:17:56+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/itsupportwale.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to Build and Optimize Your React App: A Complete Guide\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#website\",\"url\":\"https:\/\/itsupportwale.com\/blog\/\",\"name\":\"ITSupportWale\",\"description\":\"Tips, Tricks, Fixed-Errors, Tutorials &amp; Guides\",\"publisher\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/itsupportwale.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#organization\",\"name\":\"itsupportwale\",\"url\":\"https:\/\/itsupportwale.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2023\/09\/cropped-Logo-trans-without-slogan.png\",\"contentUrl\":\"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2023\/09\/cropped-Logo-trans-without-slogan.png\",\"width\":1119,\"height\":144,\"caption\":\"itsupportwale\"},\"image\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/Itsupportwale-298547177495978\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#\/schema\/person\/8c5a2b3d36396e0a8fd91ec8242fd46d\",\"name\":\"Techie\",\"sameAs\":[\"https:\/\/itsupportwale.com\",\"iswblogadmin\"],\"url\":\"https:\/\/itsupportwale.com\/blog\/author\/iswblogadmin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"How to Build and Optimize Your React App: A Complete Guide - ITSupportWale","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/","og_locale":"en_US","og_type":"article","og_title":"How to Build and Optimize Your React App: A Complete Guide - ITSupportWale","og_description":"text $ node -v v14.17.0 (Warning: Node.js version is end-of-life. Security patches are non-existent.) $ npm audit \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 Scanning 2,482 dependencies for vulnerabilities&#8230; Critical: 14 High: 89 Moderate: 156 Low: 412 Run npm audit fix to do absolutely nothing because the dependency tree is a circular nightmare of peer-dependency conflicts. $ vite build vite v2.9.15 ... Read more","og_url":"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/","og_site_name":"ITSupportWale","article_publisher":"https:\/\/www.facebook.com\/Itsupportwale-298547177495978","article_published_time":"2026-03-26T16:17:56+00:00","og_image":[{"width":512,"height":512,"url":"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2021\/05\/android-chrome-512x512-1.png","type":"image\/png"}],"author":"Techie","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Techie","Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/#article","isPartOf":{"@id":"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/"},"author":{"name":"Techie","@id":"https:\/\/itsupportwale.com\/blog\/#\/schema\/person\/8c5a2b3d36396e0a8fd91ec8242fd46d"},"headline":"How to Build and Optimize Your React App: A Complete Guide","datePublished":"2026-03-26T16:17:56+00:00","mainEntityOfPage":{"@id":"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/"},"wordCount":2074,"commentCount":0,"publisher":{"@id":"https:\/\/itsupportwale.com\/blog\/#organization"},"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/","url":"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/","name":"How to Build and Optimize Your React App: A Complete Guide - ITSupportWale","isPartOf":{"@id":"https:\/\/itsupportwale.com\/blog\/#website"},"datePublished":"2026-03-26T16:17:56+00:00","breadcrumb":{"@id":"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/itsupportwale.com\/blog\/how-to-build-and-optimize-your-react-app-a-complete-guide\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/itsupportwale.com\/blog\/"},{"@type":"ListItem","position":2,"name":"How to Build and Optimize Your React App: A Complete Guide"}]},{"@type":"WebSite","@id":"https:\/\/itsupportwale.com\/blog\/#website","url":"https:\/\/itsupportwale.com\/blog\/","name":"ITSupportWale","description":"Tips, Tricks, Fixed-Errors, Tutorials &amp; Guides","publisher":{"@id":"https:\/\/itsupportwale.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/itsupportwale.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/itsupportwale.com\/blog\/#organization","name":"itsupportwale","url":"https:\/\/itsupportwale.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/itsupportwale.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2023\/09\/cropped-Logo-trans-without-slogan.png","contentUrl":"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2023\/09\/cropped-Logo-trans-without-slogan.png","width":1119,"height":144,"caption":"itsupportwale"},"image":{"@id":"https:\/\/itsupportwale.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/Itsupportwale-298547177495978"]},{"@type":"Person","@id":"https:\/\/itsupportwale.com\/blog\/#\/schema\/person\/8c5a2b3d36396e0a8fd91ec8242fd46d","name":"Techie","sameAs":["https:\/\/itsupportwale.com","iswblogadmin"],"url":"https:\/\/itsupportwale.com\/blog\/author\/iswblogadmin\/"}]}},"_links":{"self":[{"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/posts\/4746","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/comments?post=4746"}],"version-history":[{"count":0,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/posts\/4746\/revisions"}],"wp:attachment":[{"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/media?parent=4746"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/categories?post=4746"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/tags?post=4746"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}