<?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: Shubham Ram</title>
    <description>The latest articles on DEV Community by Shubham Ram (@shubhamram).</description>
    <link>https://dev.to/shubhamram</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%2F3940979%2F9cec7aae-874a-4ffc-9fc9-a8260b5d8993.gif</url>
      <title>DEV Community: Shubham Ram</title>
      <link>https://dev.to/shubhamram</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shubhamram"/>
    <language>en</language>
    <item>
      <title>Vendor Chunking: The React Optimization I Wish I'd Known Earlier</title>
      <dc:creator>Shubham Ram</dc:creator>
      <pubDate>Sun, 31 May 2026 16:36:05 +0000</pubDate>
      <link>https://dev.to/shubhamram/vendor-chunking-the-react-optimization-i-wish-id-known-earlier-j7f</link>
      <guid>https://dev.to/shubhamram/vendor-chunking-the-react-optimization-i-wish-id-known-earlier-j7f</guid>
      <description>&lt;p&gt;I ignored my bundle size for months. By the time I checked, my production build was several megabytes of JavaScript in a single file — and every deploy forced my users to download all of it again. Vendor chunking is what I wish I'd known earlier.&lt;/p&gt;

&lt;p&gt;Let's say you are building a project using React, and for that project you need some component library, a library to handle date-related things, or a library to handle your state. So you reach for the usual suspects — Material UI, dayjs, TanStack Query, Redux and so on.&lt;/p&gt;

&lt;p&gt;Initially, everything will work smoothly for you as well as for your end users. But as you keep shipping new features and adding dependencies, the bundle quietly grows. Locally, you don't notice. But in production, it’s the end users who end up paying the price. What happens behind the scenes is that, when dependencies are included in the initial bundle, they can significantly increase the JavaScript downloaded by the browser. As a result, you end up with a poor Lighthouse score, slow initial load times, and a large JavaScript bundle — all of which hurt the user experience.&lt;/p&gt;

&lt;p&gt;Your production build looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; dist/assets/index-xxxx.js → 1.2 MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is exactly the kind of problem vendor chunking is designed to solve.  &lt;/p&gt;

&lt;h3&gt;
  
  
  What is Vendor Chunking?
&lt;/h3&gt;

&lt;p&gt;Vendor chunking is a technique where you can separate the third-party dependencies from your main bundle chunk. So you will have a main chunk which will contain your main application code and a vendor chunk which will contain the third-party dependency code. &lt;/p&gt;

&lt;h3&gt;
  
  
  How does Vendor Chunking help with large bundle size?
&lt;/h3&gt;

&lt;p&gt;When you implement vendor chunking, your application is typically split into at least two separate bundles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Main Chunk: Contains your application code&lt;/li&gt;
&lt;li&gt;Vendor Chunk: Contains third-party dependencies and libraries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a user visits your website for the first time, the browser downloads both chunks and stores them in the cache. This is where caching becomes very useful.&lt;/p&gt;

&lt;p&gt;It’s worth noting that vendor chunking doesn’t come into play on the user’s first visit, because the browser still has to fetch both the chunks. The real performance gains show up when a user revisits the website and the cached vendor chunk can be reused.&lt;/p&gt;

&lt;p&gt;Since third-party dependencies do not change frequently, the vendor chunk usually remains the same across deployments. On the other hand, whenever you ship new features, bug fixes, or other updates, your application code changes — which results in a new main chunk being generated.&lt;/p&gt;

&lt;p&gt;When you generate a new production build, the bundler will again create:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A new main chunk containing the updated application code&lt;/li&gt;
&lt;li&gt;The same vendor chunk, because the dependency code has not changed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now consider this scenario where a user’s browser has already cached both the chunks because the user has already visited your website, and you deploy a new feature to the production. As a result, the user's browser only needs to download the new main chunk, while the cached vendor chunk can be reused. This is how vendor chunks help in improving user experience.&lt;/p&gt;




&lt;h3&gt;
  
  
  Vendor Chunking in Action
&lt;/h3&gt;

&lt;p&gt;Now let's understand this whole thing using the code. I have a &lt;a href="https://github.com/shubham-ram/vendor-chunk" rel="noopener noreferrer"&gt;React project&lt;/a&gt; where I have installed multiple dependencies such as MUI, Chart.js, Lodash, dayjs and React Router. &lt;/p&gt;

&lt;p&gt;Before Vendor Chunking, the build will look something like this:&lt;/p&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%2Frbfbdgpx1jsi0a2iw1de.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%2Frbfbdgpx1jsi0a2iw1de.png" alt="Build Before Vendor Chunking" width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: I've disabled tree-shaking for this demo to keep the bundle size large and make the impact of vendor chunking more visible. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The build will contain only one JS file and the browser has to download this large ~4.6 MB file.&lt;/p&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%2Fl6qjt14dsfydef1l6lvn.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%2Fl6qjt14dsfydef1l6lvn.png" alt="Network call with old build files" width="724" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now I will implement vendor chunking by adding this code block in my vite.config.ts file:&lt;/p&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%2Fdzg3oycz7gasuic3kz73.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%2Fdzg3oycz7gasuic3kz73.png" alt="Vite config for vendor chunking: {'output':{'codeSplitting':{'groups':[{'test': /node_modules/,'name':'vendor'}]}}}" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: I'm using Vite v8, which uses Rolldown as the bundler. If you're on an older Vite version with Rollup, the config syntax will be different&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So after this, the build will look something like this:&lt;/p&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%2Ft1t6qt17fg9s7k1l52e7.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%2Ft1t6qt17fg9s7k1l52e7.png" alt="Build after implementing vendor chunk" width="799" height="399"&gt;&lt;/a&gt;&lt;br&gt;
As you can see, now we have two JS files: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;index-XXX.js which contains our main application code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;vendor-XXX.js which contains code of all third party packages&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now the browser has to download both of these files so that our application loads correctly. Here comes the crazy part. Let’s update the code and try to generate the new production build. Here’s what it will generate:&lt;/p&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%2F69bo7ogrqctbnaun7c9o.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%2F69bo7ogrqctbnaun7c9o.png" alt="Build files after updating code" width="799" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you compare the files with the previous build, you will find that only index-xx.js changed, while vendor-xx.js stays the same, because we didn’t upgrade any package versions; we only updated the application code.&lt;br&gt;
Now when a user revisits our website, the browser will only fetch the new index-xx.js from the server, vendor-xx.js will be served from cache. &lt;/p&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%2Ft88rhgbb8o2kufp5f3no.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%2Ft88rhgbb8o2kufp5f3no.png" alt="Network tab after code update" width="724" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is how vendor chunking helps in performance improvement for web applications.&lt;/p&gt;




&lt;h3&gt;
  
  
  Splitting Vendors Further
&lt;/h3&gt;

&lt;p&gt;So far we have bundled all the dependencies into a single chunk. This works well for small to medium applications, but as the dependency list grows, a single vendor chunk has a drawback. If you update the version of any library, a new vendor chunk will be generated and users have to re-download the whole thing - even if 95% of the code is same. &lt;/p&gt;

&lt;p&gt;To tackle this issue, we can split vendors into multiple chunks. For example, you can keep your UI library in one chunk, your utility libraries in another, and your charting library in a third:&lt;/p&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%2F7ou7s6m91xgc8j22xbhy.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%2F7ou7s6m91xgc8j22xbhy.png" alt="Vite config for splitting chunk further: {'output':{'codeSplitting':{'groups':[{'test':/node_modules\/(@mui|@emotion)/,'name':'ui'},{'test': /node_modules\/(lodash|dayjs)/,'name':'utils'},{'test': /node_modules\/(chart\.js|react-chartjs-2)/,'name':'charts'},{'test': /node_modules/,'name':'vendor'}]}}} " width="800" height="741"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The final node_modules group is a catch-all so dependencies like React land in a vendor chunk too, rather than your main bundle.&lt;/p&gt;

&lt;p&gt;After this config, your build output will look something like this:&lt;/p&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%2Floaqgdpzivhzxit4fzbz.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%2Floaqgdpzivhzxit4fzbz.png" alt="Splitting vendor chunks further" width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Just don't go overboard with splitting — too many small chunks can hurt performance due to HTTP overhead and less effective compression&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Wrapping Up
&lt;/h3&gt;

&lt;p&gt;Vendor chunking is one of those optimizations that costs you a few lines of config and pays you back on every deploy. The core idea is simple: your application code changes often, third-party code doesn't — so why force your users to re-download libraries they already have?&lt;/p&gt;

&lt;p&gt;If you haven't audited your production bundle in a while, run a build and take a look. You might be surprised how much of it is third-party code waiting to be cached properly.&lt;/p&gt;

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