<?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: Ahmed Hinedy</title>
    <description>The latest articles on DEV Community by Ahmed Hinedy (@hinedy).</description>
    <link>https://dev.to/hinedy</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%2F947042%2Fad97eeb8-c24d-4ede-9cf4-2dc6cc0edc35.jpg</url>
      <title>DEV Community: Ahmed Hinedy</title>
      <link>https://dev.to/hinedy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hinedy"/>
    <language>en</language>
    <item>
      <title>The Hidden Cost of “Best Practices” in Frontend Systems</title>
      <dc:creator>Ahmed Hinedy</dc:creator>
      <pubDate>Thu, 12 Feb 2026 10:55:10 +0000</pubDate>
      <link>https://dev.to/hinedy/the-hidden-cost-of-best-practices-in-frontend-systems-hgn</link>
      <guid>https://dev.to/hinedy/the-hidden-cost-of-best-practices-in-frontend-systems-hgn</guid>
      <description>&lt;p&gt;&lt;em&gt;A decision framework for adopting, keeping, or retiring frontend practices in systems under change.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Best practices aren’t stupid. but they age
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Why following them is necessary early, and insufficient later&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Best practices are taught for a reason.&lt;/p&gt;

&lt;p&gt;When you’re early in your career. or new to a codebase. they’re often the fastest way to become effective. They compress hard‑won lessons into usable rules. They reduce obvious mistakes. They help you ship something reasonable before you fully understand the system you’re working in.&lt;/p&gt;

&lt;p&gt;Learning and applying best practices is often the shortest path to competence.&lt;/p&gt;

&lt;p&gt;Learning when they no longer fit is what comes later.&lt;/p&gt;

&lt;p&gt;That second skill isn’t rebellion. It’s not contrarianism. It’s what emerges once you’ve seen the same practice succeed, struggle, and eventually get in the way across different systems.&lt;/p&gt;

&lt;p&gt;The problem isn’t that these practices are wrong.&lt;/p&gt;

&lt;p&gt;Frontend best practices rarely fail because they’re incorrect. they fail because the system they were optimized for no longer exists.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The optimization mismatch
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Review-time clarity versus change over time&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This isn’t about taste, preference, or engineers disagreeing about style. It’s about what different systems are optimized for.&lt;/p&gt;

&lt;p&gt;Many frontend best practices are designed to optimize for moments of inspection:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;clarity during code review&lt;/li&gt;
&lt;li&gt;visible consistency across files and teams&lt;/li&gt;
&lt;li&gt;confidence that the current state is "correct"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are real needs. They reduce friction and make systems easier to reason about.&lt;/p&gt;

&lt;p&gt;Frontend products, however, are governed by something else entirely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;long stretches of continuous change&lt;/li&gt;
&lt;li&gt;requirements that evolve faster than documentation&lt;/li&gt;
&lt;li&gt;UX and workflows that are reshaped incrementally&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most frontend best practices are optimized for how code looks at review time.&lt;br&gt;
Frontend products are governed by how code behaves over months of change.&lt;/p&gt;

&lt;p&gt;When those optimization targets diverge, tension is inevitable. Practices rarely fail loudly. they simply stop fitting the system they’re embedded in.&lt;/p&gt;




&lt;p&gt;When practices optimized for inspection meet systems governed by change, the stress shows up first at the edges.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Why frontend absorbs change differently
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Where product churn concentrates first&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Frontend sits at an unstable intersection.&lt;/p&gt;

&lt;p&gt;It’s where product decisions land, design iterates, backend inconsistencies surface, and edge cases become user-visible.&lt;/p&gt;

&lt;p&gt;UI boundaries rarely stay fixed. Flows evolve. Screens merge. State that once felt local needs to be shared. Components quietly turn into systems.&lt;/p&gt;

&lt;p&gt;As a result, frontend absorbs churn earlier and more often than most layers.&lt;/p&gt;

&lt;p&gt;Practices that resist change. or assume stable boundaries. fail fastest here. This isn’t accidental. It’s structural.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. How reasonable practices turn into liabilities
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;When decisions harden into constraints&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Most frontend practices don’t start as dogma. They start as solutions.&lt;/p&gt;

&lt;p&gt;A team hits a real problem. unreadable code, regressions, slow reviews, duplicated logic. and introduces structure to relieve that pain. In that moment, the decision is usually correct.&lt;/p&gt;

&lt;p&gt;Many frontend architecture decisions don’t fail immediately. They fail once the original context disappears.&lt;/p&gt;

&lt;p&gt;Early on, shared understanding substitutes for documentation. The team is small, the constraints are obvious, and everyone knows &lt;em&gt;why&lt;/em&gt; certain choices exist. Patterns are applied with judgment because the reasoning is still alive.&lt;/p&gt;

&lt;p&gt;As the product evolves, that context fades. New engineers copy patterns without knowing which problems they were meant to solve. The code still works, but the assumptions behind its structure are no longer visible.&lt;/p&gt;

&lt;p&gt;Eventually, someone asks: &lt;em&gt;“Why is this done this way?”&lt;/em&gt; And no one can answer.&lt;/p&gt;

&lt;p&gt;At that point, the practice hasn’t failed. it has hardened. The system has changed, but the constraint remains. Change becomes slower, estimates become conditional, and teams start navigating structure instead of solving user problems.&lt;/p&gt;

&lt;p&gt;The issue isn’t that the original decision was wrong. It’s that it stopped being treated as a decision at all.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. The common failure pattern (tool-agnostic)
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Why this repeats across frameworks and eras&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This isn’t about frameworks or trends. The tools change every few years. The failure mode doesn’t.&lt;/p&gt;

&lt;p&gt;The recurring issue:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Early abstraction hardens assumptions&lt;/strong&gt;&lt;br&gt;
Structure is introduced to reduce ambiguity and make the system legible. In the moment, this is usually the right call.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Product evolution invalidates those assumptions&lt;/strong&gt;&lt;br&gt;
Requirements shift, flows merge, and edge cases accumulate. The system changes in ways the original abstraction didn’t anticipate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The abstraction remains because removal is expensive&lt;/strong&gt;&lt;br&gt;
By the time the mismatch is visible, the structure is deeply embedded. Changing it risks regressions, rewrites, and coordination overhead.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result isn’t immediate failure. It’s slow friction.&lt;/p&gt;

&lt;p&gt;Teams spend more time navigating structure than solving user problems. The issue isn’t the tools. it’s what the system was designed to optimize.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Quality vs adaptability
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Why clean code can still be expensive to change&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is where many frontend teams get stuck.&lt;/p&gt;

&lt;p&gt;Practices that once reduced chaos start being used as proof of quality. Clean structure, strict rules, and strong guardrails become proxies for correctness.&lt;/p&gt;

&lt;p&gt;In frontend systems, quality only reveals itself over time. when requirements shift, flows merge, and assumptions quietly break.&lt;/p&gt;

&lt;p&gt;Some practices improve readability and safety today while increasing fragility tomorrow. They make the current state feel orderly, but raise the cost of the next meaningful change.&lt;/p&gt;

&lt;p&gt;This is why a frontend codebase can look immaculate and still feel slow to work in.&lt;/p&gt;

&lt;p&gt;Good frontend code isn’t just easy to read or hard to misuse.&lt;/p&gt;

&lt;p&gt;It’s code that tolerates change without forcing rewrites, architectural debates, or cascading refactors every time the product evolves.&lt;/p&gt;

&lt;p&gt;Adaptability isn’t a lack of discipline.&lt;/p&gt;

&lt;p&gt;It’s a different definition of quality. one that accounts for time, churn, and uncertainty.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. This is not an argument against standards
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Why ownership matters more than rigidity&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Standards matter. Without them, teams drift and duplicate effort.&lt;/p&gt;

&lt;p&gt;The problem isn’t standards. it’s standards that can’t be renegotiated.&lt;/p&gt;

&lt;p&gt;The opposite of rigid best practices isn’t chaos. It’s active ownership.&lt;/p&gt;

&lt;p&gt;Healthy teams treat practices as agreements: revisable, removable, and owned.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. A better definition of “best practice”
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;A decision filter, not a checklist&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Instead of a checklist, treat best practices as a filter.&lt;/p&gt;

&lt;p&gt;A frontend practice is “best” if it lowers the total cost of the &lt;em&gt;next change&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Not just the next pull request. the next product adjustment or shift in direction.&lt;/p&gt;

&lt;p&gt;Helpful tests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does it survive product churn?&lt;/li&gt;
&lt;li&gt;Can a new hire understand why it exists?&lt;/li&gt;
&lt;li&gt;Can it be removed without destabilizing the system?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If not, the practice may still help. but it isn’t universally best.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Renegotiation is the work
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Why maturity shows up in what teams revisit&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This doesn’t produce a new checklist. It changes how teams relate to the practices they already have.&lt;/p&gt;

&lt;p&gt;Useful questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which practices exist only because no one has questioned them recently?&lt;/li&gt;
&lt;li&gt;What would break first if the roadmap doubled?&lt;/li&gt;
&lt;li&gt;What would you remove to make onboarding faster?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These questions surface hidden costs without prescribing solutions.&lt;/p&gt;

&lt;p&gt;The best frontend teams don’t follow best practices blindly. They continuously renegotiate them as the product evolves.&lt;/p&gt;

&lt;p&gt;That renegotiation isn’t inconsistency. it’s professionalism in a system defined by change.&lt;/p&gt;

&lt;p&gt;Frontend best practices don’t fail because teams are careless. They fail when practices stop being treated as decisions and start being treated as facts.&lt;/p&gt;

&lt;p&gt;Knowing when that shift has happened. and having the judgment to respond. is one of the most valuable frontend skills there is.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>systemdesign</category>
      <category>frontend</category>
      <category>product</category>
    </item>
    <item>
      <title>How We Cut Our React App's Bundle Size in Half</title>
      <dc:creator>Ahmed Hinedy</dc:creator>
      <pubDate>Sun, 23 Feb 2025 12:11:35 +0000</pubDate>
      <link>https://dev.to/hinedy/how-we-cut-our-react-apps-bundle-size-in-half-1edn</link>
      <guid>https://dev.to/hinedy/how-we-cut-our-react-apps-bundle-size-in-half-1edn</guid>
      <description>&lt;p&gt;Our React application's bundle size had reached 1.54MB (gzipped). The app worked fine, but loading times kept increasing. This post explains the steps we took to reduce the bundle size in half and its impact on performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Problem
&lt;/h2&gt;

&lt;p&gt;Lighthouse and Chrome DevTools painted a clear picture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pages took too long to become interactive&lt;/li&gt;
&lt;li&gt;Mobile users faced significant load delays&lt;/li&gt;
&lt;li&gt;Users downloaded and parsed more code than they needed for basic interactions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Optimization Strategy
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Route-Based Code Splitting
&lt;/h3&gt;

&lt;p&gt;In our app using &lt;code&gt;createBrowserRouter&lt;/code&gt; from React Router 6, we implemented route-based code-splitting to defer code loading until a user navigates to the relevant route:&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="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;lazy&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createBrowserRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;RouterProvider&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="s2"&gt;react-router-dom&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;LazyLoadedPage&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="s2"&gt;./LazyLoadedPage&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;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createBrowserRouter&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/feature&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&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;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;LazyLoadedPage&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="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;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Strategic Library Loading
&lt;/h3&gt;

&lt;p&gt;Heavy dependencies don't need to load immediately. The key is to move imports inside the functions that use them:&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 - importing at the top level&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PDFDocument&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="s2"&gt;@react-pdf/renderer&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;XLSX&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;xlsx&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 - inline imports when needed&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generatePDF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PDFDocument&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&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="s2"&gt;@react-pdf/renderer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// PDF generation logic&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;exportToExcel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&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;XLSX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&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="s2"&gt;xlsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Excel export logic&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We applied this pattern to several large dependencies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PDF generation (&lt;code&gt;@react-pdf&lt;/code&gt;, ~450KB) → loads only during PDF exports&lt;/li&gt;
&lt;li&gt;Spreadsheet functionality (&lt;code&gt;xlsx&lt;/code&gt;, ~214KB) → waits for export operations&lt;/li&gt;
&lt;li&gt;Date handling → moved to lighter alternatives for common operations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Other common libraries worth deferring in React apps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rich text editors (&lt;code&gt;draft-js&lt;/code&gt;, &lt;code&gt;quill&lt;/code&gt;) → load when editing starts&lt;/li&gt;
&lt;li&gt;Chart libraries (&lt;code&gt;chart.js&lt;/code&gt;, &lt;code&gt;recharts&lt;/code&gt;) → load when viewing data visualizations&lt;/li&gt;
&lt;li&gt;Complex UI components (&lt;code&gt;@mui/x-data-grid&lt;/code&gt;, &lt;code&gt;ag-grid&lt;/code&gt;) → load when data tables mount&lt;/li&gt;
&lt;li&gt;Image manipulation (&lt;code&gt;sharp&lt;/code&gt;, &lt;code&gt;jimp&lt;/code&gt;) → load when editing starts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The pattern remains consistent: identify when users need the functionality, and load it at that moment. This approach is particularly helpful during initial page loads.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Measurement-Driven Optimization
&lt;/h3&gt;

&lt;p&gt;Three tools drove our decisions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;source-map-explorer&lt;/code&gt; analyzed dependency sizes&lt;/li&gt;
&lt;li&gt;Chrome DevTools' Performance tab showed load behavior&lt;/li&gt;
&lt;li&gt;Regular Lighthouse audits tracked improvements&lt;/li&gt;
&lt;/ul&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;Improvement&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Main Bundle Size&lt;/td&gt;
&lt;td&gt;-49.5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;First Contentful Paint&lt;/td&gt;
&lt;td&gt;+28.5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total Blocking Time&lt;/td&gt;
&lt;td&gt;+20%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Speed Index&lt;/td&gt;
&lt;td&gt;+46.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Key Learnings
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Target the right components for code splitting. Focus on larger features that deliver meaningful impact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Performance tools reveal opportunities you might miss otherwise. Regular bundle analysis became essential to our process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Performance optimization doesn't stop. Each improvement reveals new opportunities.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Maintaining Performance
&lt;/h2&gt;

&lt;p&gt;Three practices keep our bundle size in check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Regular bundle analysis during development&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Performance budgets for new feature development, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maximum initial bundle size: 500KB after gzip&lt;/li&gt;
&lt;li&gt;Route-level budgets: 200KB per lazy-loaded route&lt;/li&gt;
&lt;li&gt;Time-to-Interactive budget: &amp;lt; 3.5s on 4G connections&lt;/li&gt;
&lt;li&gt;First Contentful Paint target: &amp;lt; 1.8s&lt;/li&gt;
&lt;li&gt;Third-party script size limit: 100KB total&lt;/li&gt;
&lt;li&gt;Image size budgets: 200KB max per image, WebP format required&lt;/li&gt;
&lt;li&gt;These budgets are enforced through:&lt;/li&gt;
&lt;li&gt;webpack configuration using &lt;code&gt;performance.hints&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;size-limit&lt;/code&gt; checks in CI&lt;/li&gt;
&lt;li&gt;Lighthouse performance scoring thresholds&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Automated performance testing in our CI pipeline using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lighthouse CI for performance metrics&lt;/li&gt;
&lt;li&gt;Bundle size tracking with &lt;code&gt;bundlewatch&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Jest Timer snapshots for runtime performance&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;webpack-bundle-analyzer&lt;/code&gt; in build pipelines&lt;/li&gt;
&lt;li&gt;GitHub Actions workflows triggered on PR deployments&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

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

&lt;p&gt;Performance optimization delivers real user value. We reduced our bundle size by carefully analyzing and making targeted improvements, improving every key performance indicator.&lt;/p&gt;

&lt;p&gt;Three steps can start your optimization journey:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Measure your current state&lt;/li&gt;
&lt;li&gt;Split code strategically&lt;/li&gt;
&lt;li&gt;Monitor consistently&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every kilobyte impacts user experience. Start measuring yours today.&lt;/p&gt;

</description>
      <category>performance</category>
      <category>react</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>HTTP Cookies Demystified: A Web Developer's Guide</title>
      <dc:creator>Ahmed Hinedy</dc:creator>
      <pubDate>Sun, 08 Sep 2024 21:49:47 +0000</pubDate>
      <link>https://dev.to/hinedy/http-cookies-demystified-a-web-developers-guide-5e2d</link>
      <guid>https://dev.to/hinedy/http-cookies-demystified-a-web-developers-guide-5e2d</guid>
      <description>&lt;h2&gt;
  
  
  Understanding HTTP Cookies in Web Development
&lt;/h2&gt;

&lt;p&gt;In this article, we'll explore the ins and outs of HTTP cookies, their significance in web development, and how they compare to alternatives like localStorage. Whether you're new to web development or looking to refine your skills, understanding cookies is key to building robust, efficient, and secure web applications.&lt;/p&gt;

&lt;p&gt;HTTP cookies are small pieces of data stored on a user's device by the web browser that can be used for managing user sessions, tracking user behavior, and enhancing the overall user experience.&lt;/p&gt;

&lt;p&gt;Cookies are regular headers. On a Request, they are stored in the &lt;code&gt;Cookie&lt;/code&gt; header. On a Response they are in the &lt;code&gt;Set-Cookie&lt;/code&gt; header&lt;/p&gt;

&lt;h2&gt;
  
  
  Cookies vs localStorage
&lt;/h2&gt;

&lt;p&gt;When it comes to client-side storage, developers often choose between cookies and localStorage. Let's compare these options:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Localstorage&lt;/strong&gt; is designed to be accessible by javascript, which makes it convenient for storing client-side data. However, this accessibility comes with a significant drawback: it doesn't provide any protection against Cross-Site Scripting (XSS) attacks. There are multiple ways an attacker could exploit an XSS vulnerability to access data stored in localStorage. &lt;/p&gt;

&lt;p&gt;On the other hand, &lt;strong&gt;cookies&lt;/strong&gt; have security flags that make them more secure for storing sensitive data: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;HttpOnly&lt;/em&gt;&lt;/strong&gt; flag prevents client-side JavaScript from accessing the cookie, mitigating XSS risks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Secure&lt;/em&gt;&lt;/strong&gt; flag ensures that the browser only transfers the cookie over SSL, protecting against man-in-the-middle attacks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;SameSite&lt;/em&gt;&lt;/strong&gt; flag helps prevent Cross-Site Request Forgery (CSRF) attacks by ensuring that the cookie is only sent to the origin site.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So cookies are a more secure choice for storing authentication data. However, localStorage can be more appropriate for storing non-sensitive client-side data like user preferences or cached content.localStorage offers larger storage capacity (usually 5-10MB compared to 4KB for cookies) and easier JavaScript access, making it suitable for improving application performance and user experience in scenarios where the enhanced security of cookies isn't necessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does Cookies Work
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F5ce9yflv5x5ivq9987u0.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F5ce9yflv5x5ivq9987u0.PNG" alt="cookies between client and server" width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Setting the Cookie&lt;/strong&gt;: When a user visits a website, the backend server can send a cookie to the browser. This is done via the &lt;code&gt;Set-Cookie&lt;/code&gt; header in the HTTP response.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storing the Cookie&lt;/strong&gt;: The browser automatically stores these cookies. As a developer, you don't need to write any client-side code to save the cookie.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Accessing Cookies&lt;/strong&gt;: On the client side, you can access some of the cookies &lt;em&gt;(not **HttpsOnly&lt;/em&gt;&lt;em&gt;)&lt;/em&gt; using &lt;code&gt;document.cookie&lt;/code&gt;. For example:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Output: "username=John Doe; session_id=1234567890"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sending Cookies&lt;/strong&gt;: The browser automatically sends all relevant cookies (based on domain and path) with every request to the server. This includes regular page loads, AJAX calls, and resource requests like images or scripts from the same domain.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;However, there's an important exception to note: cookies are not automatically sent with cross-origin POST requests. To include cookies with cross-origin requests, you need to enable the &lt;code&gt;withCredentials&lt;/code&gt; option in your client-side API request headers, as shown&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="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;withCredentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; 
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep in mind that this requires the server to respond with the appropriate CORS headers, including &lt;code&gt;Access-Control-Allow-Credentials: true&lt;/code&gt;. If the server does not allow credentials, the browser will still prevent the inclusion of cookies, even if you set &lt;code&gt;withCredentials: true&lt;/code&gt; on the client side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cookie Attributes
&lt;/h2&gt;

&lt;p&gt;Cookies can have various attributes that control their behavior:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Expires&lt;/strong&gt;: Determines how long the cookie should last.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain&lt;/strong&gt;: Specifies which domains the cookie is valid for.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Path&lt;/strong&gt;: Limits the cookie to a specific path on the server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure&lt;/strong&gt;: Ensures the cookie is only sent over HTTPS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HttpOnly&lt;/strong&gt;: Prevents JavaScript from accessing the cookie.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SameSite&lt;/strong&gt;: Controls how the cookie is sent with cross-site requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;IETF Standards provide the definitive guide to cookies. &lt;br&gt;
&lt;a href="https://www.ietf.org/archive/id/draft-ietf-httpbis-rfc6265bis-07.html" rel="noopener noreferrer"&gt;Learn more&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting Cookies
&lt;/h2&gt;

&lt;p&gt;The method of setting a cookie depends on the context:&lt;/p&gt;
&lt;h3&gt;
  
  
  HTTP Headers
&lt;/h3&gt;

&lt;p&gt;This is the common server-side approach. Servers send a &lt;code&gt;Set-Cookie&lt;/code&gt; header in the response, containing cookie details such as name, value, and various attributes like expiry time and domain. This is typically done in server-side languages like PHP, Python, or JavaScript(Express).&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="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/set-cookie&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Set-Cookie&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user=John; HttpOnly; Secure; SameSite=Strict&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;session=1234567890; HttpOnly; Secure; SameSite=Strict; Max-Age=3600&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cookies are set&lt;/span&gt;&lt;span class="dl"&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;h3&gt;
  
  
  JavaScript
&lt;/h3&gt;

&lt;p&gt;JavaScript, through the &lt;code&gt;document.cookie&lt;/code&gt; property, allows you to set cookies directly on the client-side.&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="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;username=John Doe; expires=Thu, 18 Dec 2023 12:00:00 UTC; path=/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, this approach has limitations as it cannot set certain attributes like &lt;strong&gt;&lt;em&gt;HttpOnly&lt;/em&gt;&lt;/strong&gt; which are crucial for security.&lt;/p&gt;

&lt;p&gt;You can refer to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie" rel="noopener noreferrer"&gt;MDN's Extensive documentation&lt;/a&gt; on cookies for more details and examples.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
