{"componentChunkName":"component---src-templates-content-template-js","path":"/en/part7/vite_internals_and_esbuild","result":{"data":{"markdownRemark":{"html":"<div class=\"content\">\n<p>In the early days, React was somewhat famous for being very difficult to configure the tools required for application development. To make the situation easier, <a href=\"https://github.com/facebookincubator/create-react-app\">Create React App</a> was developed, which eliminated configuration-related problems. <a href=\"https://vitejs.dev/\">Vite</a>, that is used throughout this course, has since replaced Create React App as the standard for new React applications.</p>\n<p>Both Vite and Create React App use <i>bundlers</i> to do the actual work. In this section we will take a closer look at what bundlers actually do, how Vite works under the hood, and how to configure it for different scenarios. We will also briefly examine <a href=\"https://esbuild.github.io/\">esbuild</a>, a low-level bundler that Vite itself uses internally, understanding esbuild helps clarify what bundling fundamentally means.</p>\n<blockquote>\n<h4>What about Webpack?</h4>\n<p>Webpack was the dominant bundler for most of the 2010s and is still encountered in older and enterprise codebases. This course also covered Webpack until spring 2026.</p>\n<p>If you work on a legacy project, knowing that Webpack exists and uses the same core concepts (entry points, loaders/plugins, output) is useful. However, setting up a new project with Webpack in 2026 is not recommended. Its configuration is complex, and modern tools like Vite provide a dramatically better developer experience. We will not cover Webpack configuration in this course.</p>\n</blockquote>\n<h3>Bundling</h3>\n<p>We have implemented our applications by dividing our code into separate modules that have been <i>imported</i> to places that require them. Even though ES6 modules are defined in the ECMAScript standard, not all execution environments handle module-based code automatically. Even modern browsers benefit from having dependencies pre-processed and optimized before delivery.</p>\n<p>For this reason, code that is divided into modules is <i>bundled</i> for production, meaning that the source code files are transformed and combined into an optimized set of files that the browser can efficiently load. When we ran <i>npm run build</i> in earlier parts of this course, Vite performed this bundling. The output appears in the <i>dist</i> directory:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">├── assets\n│   ├── index-d526a0c5.css\n│   ├── index-e92ae01e.js\n│   └── react-35ef61ed.svg\n├── index.html\n└── vite.svg</code></pre></div>\n<p>The <i>index.html</i> at the root loads the bundled JavaScript with a <i>script</i> tag:</p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\"><span class=\"token doctype\"><span class=\"token punctuation\">&lt;!</span><span class=\"token doctype-tag\">doctype</span> <span class=\"token name\">html</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>html</span> <span class=\"token attr-name\">lang</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>en<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>head</span><span class=\"token punctuation\">></span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">charset</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>UTF-8<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>icon<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">type</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>image/svg+xml<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>/vite.svg<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>viewport<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>width=device-width, initial-scale=1.0<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>title</span><span class=\"token punctuation\">></span></span>Vite + React<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>title</span><span class=\"token punctuation\">></span></span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>script</span> <span class=\"token attr-name\">type</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>module<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">crossorigin</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>/assets/index-e92ae01e.js<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token script\"></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>script</span><span class=\"token punctuation\">></span></span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>stylesheet<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>/assets/index-d526a0c5.css<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></span>  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>head</span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>body</span><span class=\"token punctuation\">></span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>root<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>body</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>html</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<p>The CSS is also bundled into a single file.</p>\n<p>In practice, bundling starts from an entry point, that is typically <i>main.jsx</i>. Vite includes not only the code from the entry point but also everything it imports, recursively, until the full dependency graph has been resolved.</p>\n<p>Since part of the imported files are packages like React, Redux, and Axios, the bundled JavaScript file will also contain the contents of each of these libraries.</p>\n<blockquote>\n<p>Before bundlers were available, the old approach was based on the fact that the index.html file loaded all of the separate JavaScript files of the application with the help of script tags. This resulted in decreased performance, since the loading of each separate file results in some overhead. For this reason, these days the preferred method is to bundle the code into a single file. Bundling also  enables optimizations like minification and tree-shaking (removing unused code).</p>\n</blockquote>\n<h3>How Vite works</h3>\n<p>Vite has two distinct operating modes that work quite differently.</p>\n<p><strong>Development mode</strong> (<i>npm run dev</i>) doesn't bundle your code at all. Instead, Vite starts a dev server that serves your source files as native ES modules, letting the browser resolve imports directly. This is why startup is nearly instant regardless of project size.\nOne exception: third-party dependencies from node_modules are pre-bundled by esbuild before the server starts. This handles two problems: many npm packages are still in CommonJS format (which browsers can't consume natively), and some libraries consist of hundreds of tiny internal files that would otherwise trigger hundreds of separate requests. esbuild converts and consolidates them, caches the result on disk, and subsequent starts are near-instant.</p>\n<p><strong>Production mode</strong> (<i>npm run build</i>) uses <a href=\"https://rollupjs.org/\">Rollup</a> for bundling with esbuild still handling other tasks such as transpilation (JSX, TypeScript) and minification. Rollup was designed from the ground up for ES modules, which makes it exceptionally good at <i>tree-shaking</i> that is a technique that statically analyzes which exports from each module are actually used and removes the rest from the final bundle. For example, if you import only one utility function from a large library, tree-shaking ensures that the rest of that library's code is not included in the bundle. This can significantly reduce bundle size.</p>\n<p>The division of labor, esbuild for speed, Rollup for bundle quality, is central to Vite's design.</p>\n<blockquote>\n<p>You might wonder why Vite doesn't just use esbuild for production bundling too, given how fast it is. The reason is that esbuild's bundling output, while correct, produces less optimized results for advanced scenarios: it has limited support for code splitting, does not produce the same level of chunk optimization, and its plugin ecosystem for bundle-level transformations is still maturing. Rollup's output is more predictable and better tuned for the complex dependency graphs that real applications produce. Vite's authors <a href=\"https://vitejs.dev/guide/why.html#why-not-bundle-with-esbuild\">have stated</a> that they intend to switch to esbuild for production bundling once its capabilities close this gap.</p>\n</blockquote>\n<h3>Understanding esbuild</h3>\n<p>To understand what bundling fundamentally involves, it is useful to work with <a href=\"https://esbuild.github.io/\">esbuild</a> directly, without the abstraction layer that Vite adds on top. Let us build a minimal React environment from scratch.</p>\n<p>Let us now create a simple React app with the following directory structure:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">├── dist\n│   └── index.html\n├── src\n│   ├── index.jsx\n│   └── App.jsx\n└── package.json</code></pre></div>\n<p>We start by installing React and react-dom:</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> <span class=\"token function\">install</span> react react-dom</code></pre></div>\n<p>We also need to install esbuild:</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> <span class=\"token function\">install</span> --save-dev esbuild</code></pre></div>\n<p>At the start we add two scripts to the <i>package.json</i>:</p>\n<div class=\"gatsby-highlight\" data-language=\"json\"><pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n  <span class=\"token property\">\"scripts\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token property\">\"build\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"esbuild src/main.jsx --bundle --outfile=dist/main.js --jsx=automatic\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"serve\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"npx serve dist\"</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>For the app we need the file <i>dist/index.html</i> that loads the JavaScript bundle:</p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\"><span class=\"token doctype\"><span class=\"token punctuation\">&lt;!</span><span class=\"token doctype-tag\">DOCTYPE</span> <span class=\"token name\">html</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>html</span> <span class=\"token attr-name\">lang</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>en<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>head</span><span class=\"token punctuation\">></span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">charset</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>UTF-8<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>title</span><span class=\"token punctuation\">></span></span>esbuild app<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>title</span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>head</span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>body</span><span class=\"token punctuation\">></span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>root<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>script</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>./main.js<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token script\"></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>script</span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>body</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>html</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<p>The entry point <i>src/main.jsx</i> is the typical one:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\"><span class=\"token keyword\">import</span> React <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span>\n<span class=\"token keyword\">import</span> ReactDOM <span class=\"token keyword\">from</span> <span class=\"token string\">'react-dom/client'</span>\n<span class=\"token keyword\">import</span> App <span class=\"token keyword\">from</span> <span class=\"token string\">'./App'</span>\n\nReactDOM<span class=\"token punctuation\">.</span><span class=\"token function\">createRoot</span><span class=\"token punctuation\">(</span>document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">'root'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">App</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>The simple application component <i>src/App.jsx</i> is as follows:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\"><span class=\"token keyword\">import</span> React<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> useState <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">App</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>counter<span class=\"token punctuation\">,</span> setCounter<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n      </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">count: </span><span class=\"token punctuation\">{</span>counter<span class=\"token punctuation\">}</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n      </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>button</span> <span class=\"token attr-name\">onClick</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">setCounter</span><span class=\"token punctuation\">(</span>counter <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">increment&lt;/ button>\n    </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n  )\n}\n\nexport default App</span></code></pre></div>\n<p>Now we can bundle the app:</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> run build</code></pre></div>\n<p>The output is a single <i>dist/main.js</i> that contains your application code along with the React library bundled together.</p>\n<p>We can now run the bundled app with <i>npm run serve</i>. This uses the <a href=\"https://www.npmjs.com/package/serve\">serve</a> package to start a local static file server for the <i>dist</i> directory, making the application available at <i><a href=\"http://localhost:3000\">http://localhost:3000</a></i>:</p>\n<picture><img src=\"/static/522129acbde0dbed877c31cc930e70d5/5a190/es1.png\" srcset=\"/static/522129acbde0dbed877c31cc930e70d5/772e8/es1.png 200w,\n/static/522129acbde0dbed877c31cc930e70d5/e17e5/es1.png 400w,\n/static/522129acbde0dbed877c31cc930e70d5/5a190/es1.png 800w,\n/static/522129acbde0dbed877c31cc930e70d5/187fa/es1.png 1194w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>esbuild also supports <a href=\"https://en.wikipedia.org/wiki/Minification_(programming)\">minification</a> through command-line flags. Minification removes whitespace and comments, shortens variable names, and applies other size optimizations. The bundle will be notably large because it includes the full React library. Minification reduces its size significantly.</p>\n<p>Let us now enable minification:</p>\n<div class=\"gatsby-highlight\" data-language=\"json\"><pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n  <span class=\"token property\">\"scripts\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token property\">\"build\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"esbuild src/main.jsx --bundle --minify --outfile=dist/main.js --jsx=automatic\"</span><span class=\"token punctuation\">,</span></span>    <span class=\"token property\">\"serve\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"npx serve dist\"</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Minification brings the bundle size down from around 1.1 MB to around 190 KB, a substantial reduction.</p>\n<p>Minification has a catch: if the application throws a runtime error, the browser's developer tools will point to a line in the minified <i>main.js</i>, which is all but impossible to read:</p>\n<picture><img src=\"/static/d286056763101d1c7847718d33d19b54/5a190/es2.png\" srcset=\"/static/d286056763101d1c7847718d33d19b54/772e8/es2.png 200w,\n/static/d286056763101d1c7847718d33d19b54/e17e5/es2.png 400w,\n/static/d286056763101d1c7847718d33d19b54/5a190/es2.png 800w,\n/static/d286056763101d1c7847718d33d19b54/c1b63/es2.png 1200w,\n/static/d286056763101d1c7847718d33d19b54/dca52/es2.png 1550w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>The solution is a <a href=\"https://developer.mozilla.org/en-US/docs/Glossary/Source_map\">source map</a>: a companion file (<i>dist/main.js.map</i>) that records how every line of the minified bundle corresponds to the original source. With it enabled, a stack trace points to the exact line in <i>App.jsx</i> or <i>main.jsx</i> instead of somewhere inside an unreadable wall of minified code.</p>\n<p>We can enable source maps by adding the <i>--sourcemap</i> flag:</p>\n<div class=\"gatsby-highlight\" data-language=\"json\"><pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n  <span class=\"token property\">\"scripts\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token property\">\"build\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"esbuild src/main.jsx --bundle --minify --sourcemap --outfile=dist/main.js --jsx=automatic\"</span><span class=\"token punctuation\">,</span></span>    <span class=\"token property\">\"serve\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"npx serve dist\"</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Now the error makes sense:</p>\n<picture><img src=\"/static/59995011009c554b7793ea87167cbd71/5a190/es3.png\" srcset=\"/static/59995011009c554b7793ea87167cbd71/772e8/es3.png 200w,\n/static/59995011009c554b7793ea87167cbd71/e17e5/es3.png 400w,\n/static/59995011009c554b7793ea87167cbd71/5a190/es3.png 800w,\n/static/59995011009c554b7793ea87167cbd71/c1b63/es3.png 1200w,\n/static/59995011009c554b7793ea87167cbd71/7be33/es3.png 1558w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>Note that source maps are invaluable during development and debugging, but you may want to leave them out of a public production build. Because a source map contains your original source code, anyone who opens the browser's developer tools can read your unminified application logic. If that is a concern, simply omit the <i>--sourcemap</i> flag from the production build command.</p>\n<h3>Transpilation</h3>\n<p>Alongside bundling, esbuild performs another essential task: <i>transpilation</i>. Transpilation means converting source code written in one form of JavaScript into another form, typically from modern or extended syntax into plain JavaScript that browsers can execute.</p>\n<p>Browsers understand standard JavaScript, but JSX is not valid JavaScript, no browser can parse it directly. When we write:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\"><span class=\"token keyword\">const</span> element <span class=\"token operator\">=</span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">App</span></span> <span class=\"token punctuation\">/></span></span></code></pre></div>\n<p>it must be transpiled it into something the browser can run:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> element <span class=\"token operator\">=</span> React<span class=\"token punctuation\">.</span><span class=\"token function\">createElement</span><span class=\"token punctuation\">(</span>App<span class=\"token punctuation\">,</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>This is why transpilation is a required step for any React project, not an optional optimization. esbuild performs it automatically during bundling. With the <i>--jsx=automatic</i> flag, esbuild handles JSX without any external tool. In the old Webpack-based workflow you had to install and configure <a href=\"https://babeljs.io/\">Babel</a> and related packages to transpile the JSX for the browser. With esbuild, files ending in <i>.jsx</i> are transpiled out of the box.</p>\n<h3>Development environment</h3>\n<p>So far, every change requires running <i>npm run build</i> and manually refreshing the browser, a slow loop that quickly becomes tedious. esbuild's built-in <a href=\"https://esbuild.github.io/api/#serve\">development server</a> solves this. Add a <i>dev</i> script to <i>package.json</i>:</p>\n<div class=\"gatsby-highlight\" data-language=\"json\"><pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n  <span class=\"token property\">\"scripts\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token property\">\"build\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"esbuild src/main.jsx --bundle --minify --sourcemap --outfile=dist/main.js --jsx=automatic\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"serve\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"npx serve dist\"</span><span class=\"token punctuation\">,</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token property\">\"dev\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"esbuild src/main.jsx --bundle --outfile=dist/main.js --jsx=automatic --servedir=./dist --watch\"</span></span>  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Running <i>npm run dev</i> does two things at once. Firstly <a href=\"https://esbuild.github.io/api/#watch\">--watch</a> tells esbuild to watch all imported source files for changes and rebuild the bundle automatically whenever any of them is saved. Secondly <a href=\"https://esbuild.github.io/api/#serve\">--servedir</a> starts a lightweight HTTP server that serves the contents of the <i>dist</i> directory, your <i>index.html</i> and the freshly built <i>main.js</i> at <i><a href=\"http://localhost:8000\">http://localhost:8000</a></i>.</p>\n<p>The <i>--servedir</i> flag is what makes both pieces work together: without it, esbuild would only rebuild in watch mode but not serve anything. With it, the server always delivers the latest bundle so you only need to refresh the browser after saving a file.</p>\n<p>Note that unlike Vite's dev server, esbuild does not support hot module replacement. Changes to your source code require a manual browser refresh to take effect.</p>\n<p>The clarity of esbuild's interface illustrates what a bundler fundamentally does: it takes an entry point, follows all imports, and produces an optimized output. Vite builds on top of this foundation and adds the developer experience layer, a dev server, hot module replacement, and sensible defaults for React projects.</p>\n<p>Now that we have a clearer picture of what bundling and transpilation fundamentally involve, let us return to Vite and look at how it can be configured.</p>\n<h3>Vite configuration</h3>\n<p>For most React projects, Vite works without any configuration at all. However, when you do need to customize behavior, you edit <i>vite.config.js</i> (or <i>vite.config.ts</i>).</p>\n<p>A minimal Vite configuration for a React project looks like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> defineConfig <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'vite'</span>\n<span class=\"token keyword\">import</span> react <span class=\"token keyword\">from</span> <span class=\"token string\">'@vitejs/plugin-react'</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token function\">defineConfig</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">plugins</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token function\">react</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>The <i>@vitejs/plugin-react</i> plugin enables JSX transformation, fast refresh (hot module replacement that preserves component state), and other React-specific features.</p>\n<h4>Development server configuration</h4>\n<p>You can configure the development server's port and other settings under the <i>server</i> key:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token function\">defineConfig</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">plugins</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token function\">react</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">server</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">port</span><span class=\"token operator\">:</span> <span class=\"token number\">3000</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">open</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>        <span class=\"token comment\">// open browser automatically</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<h4>Proxying API requests</h4>\n<p>When developing locally, your React app typically runs on one port (e.g., 3000) while your backend runs on another (e.g., 3001). The browser's same-origin policy would normally block requests between them. Vite's proxy setting solves this without requiring CORS configuration on the backend:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token function\">defineConfig</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">plugins</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token function\">react</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">server</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">port</span><span class=\"token operator\">:</span> <span class=\"token number\">3000</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">proxy</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token string-property property\">'/api'</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token literal-property property\">target</span><span class=\"token operator\">:</span> <span class=\"token string\">'http://localhost:3001'</span><span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">changeOrigin</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>With this configuration, any request your React app makes to <i>/api/notes</i> is automatically forwarded to <i><a href=\"http://localhost:3001/api/notes\">http://localhost:3001/api/notes</a></i> by Vite's dev server. Your frontend code never needs to include <i>localhost:3001</i> in its URLs during development.</p>\n<h4>Environment variables</h4>\n<p>Vite has built-in support for environment variables using <i>.env</i> files. This is the modern replacement for manually injecting constants into the bundle.</p>\n<p>Create a <i>.env</i> file in the project root:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">VITE_BACKEND_URL=http://localhost:3001/api/notes</code></pre></div>\n<p>And a <i>.env.production</i> file for production values:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">VITE_BACKEND_URL=https://myapp.fly.dev/api/notes</code></pre></div>\n<p><strong>Important:</strong> all environment variables exposed to the browser must be prefixed with <i>VITE_</i>. Variables without this prefix remain server-side only and are not included in the bundle. This is a deliberate security measure to prevent accidentally leaking secrets.</p>\n<p>Access the variable in your application code via <i>import.meta.env</i>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">App</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> notes <span class=\"token operator\">=</span> <span class=\"token function\">useNotes</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">import</span><span class=\"token punctuation\">.</span>meta<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">VITE_BACKEND_URL</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span>\n      <span class=\"token punctuation\">{</span>notes<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">}</span> notes on server <span class=\"token punctuation\">{</span><span class=\"token keyword\">import</span><span class=\"token punctuation\">.</span>meta<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">VITE_BACKEND_URL</span><span class=\"token punctuation\">}</span>\n    <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span>\n  <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Vite automatically selects the correct <i>.env</i> file based on the mode:</p>\n<ul>\n<li><i>npm run dev</i> uses <i>.env</i> and <i>.env.development</i></li>\n<li><i>npm run build</i> uses <i>.env</i> and <i>.env.production</i></li>\n</ul>\n<p>Add <i>.env.production</i> to <i>.gitignore</i> if it contains sensitive values, and use <i>.env.example</i> to document what variables are required.</p>\n<h4>Transpilation</h4>\n<p>Vite handles code transpilation automatically. During development, esbuild transpiles your TypeScript and JSX on demand. It is fast enough to do this per-file without a noticeable delay. During production builds, Rollup handles the bundling while esbuild handles transpilation.</p>\n<p>The default transpilation target in Vite is modern browsers that support native ES modules (Chrome 87+, Firefox 78+, Safari 14+, Edge 88+). If you need to support older browsers, you can configure the target explicitly and add the <i>@vitejs/plugin-legacy</i> plugin:</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> <span class=\"token function\">install</span> --save-dev @vitejs/plugin-legacy</code></pre></div>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> defineConfig <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'vite'</span>\n<span class=\"token keyword\">import</span> react <span class=\"token keyword\">from</span> <span class=\"token string\">'@vitejs/plugin-react'</span>\n<span class=\"token keyword\">import</span> legacy <span class=\"token keyword\">from</span> <span class=\"token string\">'@vitejs/plugin-legacy'</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token function\">defineConfig</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">plugins</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n    <span class=\"token function\">react</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function\">legacy</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n      <span class=\"token literal-property property\">targets</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'defaults'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'not IE 11'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>The legacy plugin automatically generates a separate bundle for older browsers using Babel.</p>\n<h4>CSS</h4>\n<p>Vite handles CSS without any configuration. Simply import a CSS file from your JavaScript:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token string\">'./index.css'</span></code></pre></div>\n<p>Vite will process it and include it in the build. In production, CSS is extracted into a separate file. During development, it is injected via <i>&#x3C;style></i> tags with hot reload support.</p>\n<p>Vite also natively supports <a href=\"https://github.com/css-modules/css-modules\">CSS Modules</a> for scoped styles. Any file ending in <i>.module.css</i> is treated as a CSS Module:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> styles <span class=\"token keyword\">from</span> <span class=\"token string\">'./App.module.css'</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">App</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span>\n  <span class=\"token operator\">&lt;</span>div className<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>styles<span class=\"token punctuation\">.</span>container<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>\n    hello vite\n  <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span>\n<span class=\"token punctuation\">)</span></code></pre></div>\n<p>CSS preprocessors like <a href=\"https://sass-lang.com/\">Sass</a> can be added by simply installing the preprocessor, no plugin or configuration needed:</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> <span class=\"token function\">install</span> --save-dev sass</code></pre></div>\n<p>After that, <i>.scss</i> files work automatically.</p>\n<h4>Minification</h4>\n<p>When running <i>npm run build</i>, Vite minifies the output. Minification removes whitespace and comments, shortens variable names, and applies other size optimizations. The result is a much smaller file that loads faster in the browser.</p>\n<p>Vite uses esbuild for JavaScript minification and a built-in CSS minifier for stylesheets.</p>\n<h4>Source maps</h4>\n<p>Source maps allow browser developer tools to map errors and breakpoints back to your original source code rather than the minified bundle. Without them, a stack trace pointing to line 1 of <i>main.js</i> is nearly useless for debugging.</p>\n<p>In development, Vite generates source maps automatically. For production builds, you can enable them explicitly:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token function\">defineConfig</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">plugins</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token function\">react</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">build</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">sourcemap</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Note that production source maps increase build time and expose your source code to anyone who looks at the network tab. In many cases it is better to upload source maps to an error monitoring service (such as Sentry) and keep them off the public server.</p>\n<h4>Plugins</h4>\n<p>Vite's functionality is extended through <a href=\"https://vite.dev/plugins/\">plugins</a>. The plugin ecosystem has grown rapidly and covers most common needs. Some widely used plugins include:</p>\n<ul>\n<li><i>@vitejs/plugin-react</i> — React support (JSX, fast refresh)</li>\n<li><i>@vitejs/plugin-legacy</i> — legacy browser support</li>\n<li><i>vite-plugin-svgr</i> — import SVG files as React components</li>\n<li><i>rollup-plugin-visualizer</i> — bundle size analysis</li>\n</ul>\n<p>Plugins are specified in the <i>plugins</i> array in <i>vite.config.js</i>. They follow the same interface as Rollup plugins, so many Rollup plugins also work with Vite.</p>\n<h4>Polyfills</h4>\n<p>A <i>polyfill</i> is code that implements a feature for browsers that do not natively support it. Transpilation alone is not sufficient for features that are syntactically valid but unimplemented. For example, a browser might parse <i>Promise</i> correctly but have no implementation of it.</p>\n<p>With Vite, polyfills are handled by the plugin <i>@vitejs/plugin-legacy</i>, which automatically includes the necessary polyfills based on your browser targets. If you need a specific polyfill without the legacy plugin, you can install it directly and import it at the top of your entry file.</p>\n<p>You can check browser support for specific APIs at <a href=\"https://caniuse.com\">https://caniuse.com</a> or <a href=\"https://developer.mozilla.org/\">Mozilla's MDN documentation</a>.</p>\n</div>","frontmatter":{"mainImage":{"publicURL":"/static/2184b1c35920cfc7a09e10660dea04eb/part-7.svg"},"part":7,"letter":"b","lang":"en"}}},"pageContext":{"part":7,"letter":"b","lang":"en"}},"staticQueryHashes":["3128451518"]}