<?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: Fogel</title>
    <description>The latest articles on DEV Community by Fogel (@fogel).</description>
    <link>https://dev.to/fogel</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1121214%2Fb26e9636-2684-4081-bdbc-541101ebb04f.png</url>
      <title>DEV Community: Fogel</title>
      <link>https://dev.to/fogel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fogel"/>
    <language>en</language>
    <item>
      <title>How Default Settings and Bad Habits Are Draining Your Claude Code Budget</title>
      <dc:creator>Fogel</dc:creator>
      <pubDate>Wed, 23 Sep 2026 09:24:47 +0000</pubDate>
      <link>https://dev.to/fogel/how-default-settings-and-bad-habits-are-draining-your-claude-code-budget-484m</link>
      <guid>https://dev.to/fogel/how-default-settings-and-bad-habits-are-draining-your-claude-code-budget-484m</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Many developers use Claude Code and look for ways to reduce token consumption by using skills and external tools.&lt;br&gt;&lt;br&gt;
But what if I told you that Claude Code includes several features enabled by default that silently impact your costs - through additional background API calls, bloating your context window, and breaking the prompt cache?&lt;/p&gt;

&lt;p&gt;Beyond settings, our workflow habits have a significant impact. The way we run commands, fix mistakes, ask side questions, and manage long sessions can dramatically affect context size and the number of API calls made.&lt;/p&gt;

&lt;p&gt;This article focuses on costs during ongoing work with Claude Code. For this purpose, I analyzed configuration files, environment variables, and actual API network traffic to understand what is really being sent to the model under the hood.&lt;br&gt;&lt;br&gt;
The goal isn't to argue that you should turn off every single feature, but rather to raise awareness of their hidden costs, allowing you to choose whether the benefit of each feature justifies its price.&lt;/p&gt;

&lt;p&gt;This article is a follow-up to &lt;a href="https://dev.to/fogel/how-to-reduce-claude-codes-initial-context-and-avoid-prompt-cache-breaks-12fg"&gt;my previous article&lt;/a&gt;, where I explained how you can save up to 49% on a session's initial context.&lt;/p&gt;
&lt;h3&gt;
  
  
  Baseline Assumptions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Claude Code version 2.1.278&lt;/li&gt;
&lt;li&gt;Claude Opus 5 model, unless specified otherwise.&lt;/li&gt;
&lt;li&gt;A Claude subscription which, according to Claude Code documentation, utilizes a one-hour TTL cache.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Features that consume tokens
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Session recap
&lt;/h3&gt;

&lt;p&gt;When we are in the middle of a session and no interaction occurs for at least 3 minutes, Claude Code generates a short summary of the conversation.&lt;/p&gt;
&lt;h4&gt;
  
  
  Is it added to the context?
&lt;/h4&gt;

&lt;p&gt;The short summary is not added to the context.&lt;/p&gt;
&lt;h4&gt;
  
  
  Does this action consume tokens?
&lt;/h4&gt;

&lt;p&gt;Yes. Generating the summary triggers an additional background API request that reuses the session's prompt cache. This action can run multiple times throughout a single session.&lt;/p&gt;
&lt;h4&gt;
  
  
  My recommendation
&lt;/h4&gt;

&lt;p&gt;I recommend disabling it. If you ever need a summary, you can easily trigger it manually using the &lt;code&gt;/recap&lt;/code&gt; command.&lt;/p&gt;
&lt;h4&gt;
  
  
  How to disable
&lt;/h4&gt;

&lt;p&gt;You can disable this via the &lt;a href="https://code.claude.com/docs/en/interactive-mode#session-recap" rel="noopener noreferrer"&gt;&lt;code&gt;/config&lt;/code&gt;&lt;/a&gt; menu or by setting &lt;a href="https://code.claude.com/docs/en/settings-reference#awaysummaryenabled" rel="noopener noreferrer"&gt;&lt;code&gt;awaySummaryEnabled: false&lt;/code&gt;&lt;/a&gt; in your &lt;code&gt;settings.json&lt;/code&gt; file.&lt;/p&gt;
&lt;h3&gt;
  
  
  Prompt suggestions
&lt;/h3&gt;

&lt;p&gt;After receiving a response from Claude, it usually provides a prompt suggestion as a follow-up, which you can accept by pressing &lt;code&gt;Tab&lt;/code&gt; and then &lt;code&gt;Enter&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  Is it added to the context?
&lt;/h4&gt;

&lt;p&gt;Not added, as long as you don't use the suggested prompt.&lt;/p&gt;
&lt;h4&gt;
  
  
  Does this action consume tokens?
&lt;/h4&gt;

&lt;p&gt;The prompt suggestion typically occurs after every single response Claude gives us. It runs as an additional background API request that reuses the session's prompt cache. This action can run many times during a session.&lt;/p&gt;
&lt;h4&gt;
  
  
  My recommendation
&lt;/h4&gt;

&lt;p&gt;I rarely use Claude's suggestions, so the cost of this feature isn't worth it for me.&lt;/p&gt;
&lt;h4&gt;
  
  
  How to disable
&lt;/h4&gt;

&lt;p&gt;You can disable this via the &lt;a href="https://code.claude.com/docs/en/interactive-mode#prompt-suggestions" rel="noopener noreferrer"&gt;&lt;code&gt;/config&lt;/code&gt;&lt;/a&gt; menu, or by setting &lt;code&gt;promptSuggestionEnabled: false&lt;/code&gt; in &lt;code&gt;settings.json&lt;/code&gt;, or by using the environment variable &lt;code&gt;CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION: false&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;opusplan&lt;/code&gt; model setting
&lt;/h3&gt;

&lt;p&gt;This represents an automatic hybrid approach.&lt;br&gt;
When the &lt;a href="https://code.claude.com/docs/en/prompt-caching#changing-permission-mode" rel="noopener noreferrer"&gt;&lt;code&gt;opusplan&lt;/code&gt;&lt;/a&gt; model is set, the transition between Opus and Sonnet models happens dynamically when entering or exiting plan mode.&lt;br&gt;&lt;br&gt;
Switching models mid-conversation invalidates the prompt cache, resulting in paying 20x to 80x more to rewrite tokens to the cache.&lt;/p&gt;
&lt;h3&gt;
  
  
  Auto memory
&lt;/h3&gt;

&lt;p&gt;Auto memory allows Claude to accumulate knowledge and insights between sessions automatically without requiring us to write anything manually.&lt;/p&gt;
&lt;h4&gt;
  
  
  Is it added to the context?
&lt;/h4&gt;

&lt;p&gt;Yes. You can read a detailed breakdown of its impact on the context in my previous article - &lt;a href="https://dev.to/fogel/how-to-reduce-claude-codes-initial-context-and-avoid-prompt-cache-breaks-12fg"&gt;How to Reduce Claude Code's Initial Context and Avoid Prompt Cache Breaks&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  Does this action consume tokens?
&lt;/h4&gt;

&lt;p&gt;Yes. During the conversation with Claude, the auto memory file (&lt;code&gt;MEMORY.md&lt;/code&gt;) is updated, which consumes tokens.&lt;/p&gt;
&lt;h4&gt;
  
  
  My recommendation
&lt;/h4&gt;

&lt;p&gt;I find it unnecessary. It can cause conflicts between the memory and other information in the context, and it takes up valuable context space.&lt;/p&gt;
&lt;h4&gt;
  
  
  How to disable
&lt;/h4&gt;

&lt;p&gt;You can &lt;a href="https://code.claude.com/docs/en/memory#enable-or-disable-auto-memory" rel="noopener noreferrer"&gt;disable&lt;/a&gt; this via &lt;code&gt;/memory&lt;/code&gt;, or by adding &lt;code&gt;"autoMemoryEnabled": false&lt;/code&gt; to your &lt;code&gt;settings.json&lt;/code&gt;, or by setting &lt;code&gt;CLAUDE_CODE_DISABLE_AUTO_MEMORY=1&lt;/code&gt;.  &lt;/p&gt;
&lt;h3&gt;
  
  
  Auto mode
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Claude Code features several &lt;a href="https://code.claude.com/docs/en/permission-modes#available-modes" rel="noopener noreferrer"&gt;permission modes&lt;/a&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;default - Manual mode&lt;/li&gt;
&lt;li&gt;acceptEdits&lt;/li&gt;
&lt;li&gt;plan&lt;/li&gt;
&lt;li&gt;auto&lt;/li&gt;
&lt;li&gt;dontAsk&lt;/li&gt;
&lt;li&gt;bypassPermissions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that &lt;code&gt;default&lt;/code&gt; is not the actual default behavior. It is simply the name of the manual mode. The actual default permission mode is &lt;code&gt;auto&lt;/code&gt; mode.&lt;br&gt;&lt;br&gt;
Auto mode allows a classifier model to decide on its own whether to approve an action or not. This classifier model uses &lt;a href="https://code.claude.com/docs/en/permission-modes#when-auto-mode-falls-back" rel="noopener noreferrer"&gt;Claude Sonnet 5&lt;/a&gt; (as seen under "Cost and latency" in the link).&lt;br&gt;&lt;br&gt;
&lt;code&gt;plan&lt;/code&gt; mode uses &lt;code&gt;auto&lt;/code&gt; mode when available.&lt;/p&gt;
&lt;h4&gt;
  
  
  Does this action consume tokens?
&lt;/h4&gt;

&lt;p&gt;Yes. Every permission decision automatically sends an API call to the classifier model, consuming additional tokens.&lt;/p&gt;
&lt;h4&gt;
  
  
  My recommendation
&lt;/h4&gt;

&lt;p&gt;Use &lt;code&gt;acceptEdits&lt;/code&gt; mode combined with pre-approving specific commands. For example:&lt;/p&gt;

&lt;p&gt;JSON&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"defaultMode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"acceptEdits"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allow"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Bash(npm run build)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bash(npm test:*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bash(git diff:*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bash(git status)"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  How to disable
&lt;/h4&gt;

&lt;h5&gt;
  
  
  Disable Auto Mode entirely
&lt;/h5&gt;

&lt;p&gt;You can completely prevent the use of auto mode by setting &lt;code&gt;disableAutoMode: "disable"&lt;/code&gt; in &lt;code&gt;settings.json&lt;/code&gt;. This will force the use of &lt;code&gt;default&lt;/code&gt; (manual) mode as the default.&lt;/p&gt;

&lt;h5&gt;
  
  
  Prevent Auto Mode during Plan Mode
&lt;/h5&gt;

&lt;p&gt;Additionally, you can prevent auto mode usage during plan mode by toggling "Use auto mode during plan" in &lt;code&gt;/config&lt;/code&gt; or set &lt;code&gt;"useAutoModeDuringPlan": false&lt;/code&gt; in &lt;code&gt;settings.json&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shell mode with &lt;code&gt;!&lt;/code&gt; prefix
&lt;/h3&gt;

&lt;p&gt;You can &lt;a href="https://code.claude.com/docs/en/interactive-mode#shell-mode-with-prefix" rel="noopener noreferrer"&gt;run shell commands directly in Claude Code&lt;/a&gt; by prefixing the command with &lt;code&gt;!&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;!&lt;/span&gt; npm &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In practice, the shell command executes immediately on your machine, and behind the scenes, Claude Code sends both the command and its subsequent output as a prompt. Claude then responds to this prompt.&lt;/p&gt;

&lt;p&gt;We could have simply prompted &lt;code&gt;npm test&lt;/code&gt; and let Claude Code run it via the shell tool, but that would result in two API calls instead of one and inflate the context even further.&lt;/p&gt;

&lt;h4&gt;
  
  
  Is it added to the context?
&lt;/h4&gt;

&lt;p&gt;Yes, both the shell command and its output are added to the context.&lt;/p&gt;

&lt;h4&gt;
  
  
  Does this action consume tokens?
&lt;/h4&gt;

&lt;p&gt;Yes, the shell command and its output are sent as a prompt, consuming tokens as usual. Claude will independently decide how to respond to this output unless we guided it beforehand.&lt;/p&gt;

&lt;h4&gt;
  
  
  My recommendation
&lt;/h4&gt;

&lt;p&gt;I prefer to review the shell output myself to decide what to do with it before Claude receives it.&lt;br&gt;&lt;br&gt;
Therefore, I configure Claude so the shell command and its output are not sent as a prompt, but only added to the context.&lt;br&gt;&lt;br&gt;
Once it is in the context, I can write a specific prompt telling Claude exactly what to do with that output. Additionally, this gives us the option to change our minds - if we regret running the command, we can use &lt;code&gt;/rewind&lt;/code&gt; to remove the shell command and its output from the context before any API call is made.&lt;/p&gt;
&lt;h4&gt;
  
  
  How to disable
&lt;/h4&gt;

&lt;p&gt;You can configure it so the output is added to the context without triggering a new API call by setting &lt;code&gt;respondToBashCommands: false&lt;/code&gt; in &lt;code&gt;settings.json&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Language Server Protocol (LSP) plugins
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://code.claude.com/docs/en/tools-reference#lsp-tool-behavior" rel="noopener noreferrer"&gt;LSP&lt;/a&gt; is a tool designed for two main purposes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It immediately identifies syntax/type errors and warnings in your code right after a file edit.&lt;/li&gt;
&lt;li&gt;It serves as a highly effective code navigation tool.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There is a Claude Code plugin that connects to the LSP, allowing Claude to receive this data and fix code issues without needing an extra build step to identify them. Furthermore, it allows for much more precise code navigation compared to standard grep-based searches.&lt;/p&gt;
&lt;h4&gt;
  
  
  Is it added to the context?
&lt;/h4&gt;

&lt;p&gt;Yes, it is added as a tool named "LSP" along with its schema.&lt;br&gt;
When used, the tool call (&lt;code&gt;tool_use&lt;/code&gt;) and the LSP's response (&lt;code&gt;tool_result&lt;/code&gt;) are added to the context like any other tool.&lt;/p&gt;
&lt;h4&gt;
  
  
  Does this action consume tokens?
&lt;/h4&gt;

&lt;p&gt;Using LSP actually saves tokens for the following reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;After every file edit, the LSP automatically reports errors and warnings, allowing Claude to fix issues without a separate build step.&lt;/li&gt;
&lt;li&gt;Code navigation is much more precise and efficient than running a &lt;code&gt;grep&lt;/code&gt; command and analyzing the output, which would otherwise fill the context with a large number of irrelevant results.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
  
  
  My recommendation
&lt;/h4&gt;

&lt;p&gt;I believe it is crucial to use this plugin because it saves extra token-consuming API calls and performs actions faster than standard commands Claude would otherwise use, such as &lt;code&gt;grep&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
Check out this &lt;a href="https://www.reddit.com/r/ClaudeCode/comments/1rh5pcm/enable_lsp_in_claude_code_code_navigation_goes/" rel="noopener noreferrer"&gt;Reddit post&lt;/a&gt; comparing code navigation using Claude Code with and without LSP. The performance difference is clear.&lt;/p&gt;
&lt;h4&gt;
  
  
  Installing the plugin
&lt;/h4&gt;

&lt;p&gt;The LSP binary and the Claude Code plugin depend on the programming language used in your project. You can find the list of LSP binaries and Claude Code plugins &lt;a href="https://code.claude.com/docs/en/discover-plugins#code-intelligence" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
You must install the LSP binary on your machine before installing the Claude plugin.&lt;/p&gt;
&lt;h3&gt;
  
  
  Context command (&lt;code&gt;/context&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;A command that outputs the number of tokens in the context, divided by categories (system prompt, system tools, messages, etc.).&lt;/p&gt;
&lt;h4&gt;
  
  
  Is it added to the context?
&lt;/h4&gt;

&lt;p&gt;The text printed to the screen adds ~2,100 tokens to the context.&lt;br&gt;
Every time you run the command, another 2,100 tokens are added (in addition to the previous ones).&lt;/p&gt;
&lt;h4&gt;
  
  
  Does this action consume tokens?
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;/context&lt;/code&gt; command &lt;a href="https://platform.claude.com/docs/en/build-with-claude/token-counting#pricing-and-rate-limits" rel="noopener noreferrer"&gt;is not billed for tokens&lt;/a&gt; because it makes API calls for token counting, not for model inference.&lt;br&gt;
However, because it injects 2,100 tokens into your context, you will pay for those tokens on every single subsequent prompt you send!&lt;/p&gt;
&lt;h4&gt;
  
  
  My recommendation
&lt;/h4&gt;

&lt;p&gt;Add the token count of the context window to your terminal's &lt;code&gt;statusline&lt;/code&gt; so you are always aware of your context window during a session.&lt;br&gt;&lt;br&gt;
Additionally, use this command only at the beginning of a conversation to understand how much space different components (skills, MCPs, etc.) consume, in order to perform context engineering.&lt;/p&gt;
&lt;h2&gt;
  
  
  Workflow Best Practices (Beyond Settings)
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Delegate verbose operations to subagents
&lt;/h3&gt;

&lt;p&gt;Subagents are specialized AI assistants that handle specific types of tasks.&lt;/p&gt;

&lt;p&gt;If the main agent were to perform tasks like reading massive log files, it would fill your main conversation's context with irrelevant information. Instead, the main agent can &lt;a href="https://code.claude.com/docs/en/costs#delegate-verbose-operations-to-subagents" rel="noopener noreferrer"&gt;delegate verbose tasks to a subagent&lt;/a&gt;, which does the heavy work and returns only the relevant conclusions to the main agent.&lt;/p&gt;

&lt;p&gt;A subagent has its own context without the parent's conversation history and does not use the &lt;a href="https://code.claude.com/docs/en/sub-agents#how-forks-differ-from-other-subagents" rel="noopener noreferrer"&gt;parent's cache&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can create a custom subagent and configure its initial context, including parameters such as: model to use, effort level, skills to preload, persistent memory scope, and whether to load the &lt;code&gt;CLAUDE.md&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;When using built-in subagents (Explore, Plan, General-purpose) in Claude Code, you can specify which model to use on a &lt;a href="https://code.claude.com/docs/en/sub-agents#choose-a-model" rel="noopener noreferrer"&gt;per-invocation basis&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Example:&lt;/strong&gt; &lt;em&gt;Spawn an Explore subagent on Haiku to find X&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Use subagents wisely, or you will end up with unnecessary token consumption.&lt;/p&gt;
&lt;h3&gt;
  
  
  Side questions with &lt;code&gt;/btw&lt;/code&gt; command
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://code.claude.com/docs/en/interactive-mode#side-questions-with-/btw" rel="noopener noreferrer"&gt;The &lt;code&gt;/btw&lt;/code&gt; command&lt;/a&gt; is designed for asking a side question about your current session (including the full conversation history) without adding the question and the answer to your main conversation's context, and without using tools.&lt;br&gt;&lt;br&gt;
Because it uses the existing context, it successfully reads from the cache. However, note that the cache write will be for 5 minutes, unlike the 1 hour used in the main conversation.&lt;/p&gt;
&lt;h3&gt;
  
  
  Rewinding the conversation
&lt;/h3&gt;

&lt;p&gt;If Claude provides an incorrect answer due to a poor prompt or a misunderstanding, don't argue with it in subsequent messages. Explaining "No, that's not what I meant, please undo that and try X" compounds unnecessary context that you will pay for on every subsequent turn.&lt;/p&gt;

&lt;p&gt;Instead, run &lt;a href="https://code.claude.com/docs/en/prompt-caching#rewinding-the-conversation" rel="noopener noreferrer"&gt;&lt;code&gt;/rewind&lt;/code&gt;&lt;/a&gt; to roll back the conversation to the turn before the mistake occurred. Fix your initial prompt and regenerate. Your context window stays lean, clean, and focused.&lt;/p&gt;
&lt;h3&gt;
  
  
  Course-correct early (The ESC Key)
&lt;/h3&gt;

&lt;p&gt;When you see Claude starting to generate an answer and realize it's heading in the wrong direction, you can stop it immediately by pressing the &lt;code&gt;ESC&lt;/code&gt; key.&lt;/p&gt;
&lt;h4&gt;
  
  
  Is it added to the context?
&lt;/h4&gt;

&lt;p&gt;Yes, your prompt and Claude’s partial response are added to the context.&lt;br&gt;&lt;br&gt;
Since this is irrelevant data, you can &lt;a href="https://code.claude.com/docs/en/costs#work-efficiently-on-complex-tasks" rel="noopener noreferrer"&gt;rewind&lt;/a&gt; the context to a previous state using the &lt;code&gt;/rewind&lt;/code&gt; command.&lt;/p&gt;
&lt;h4&gt;
  
  
  Does this action consume tokens?
&lt;/h4&gt;

&lt;p&gt;The act of stopping the generation does not consume tokens. You only pay for what Claude generated up to that point.&lt;br&gt;&lt;br&gt;
Stopping it early actually saves you from paying for the remaining output tokens Claude would have wasted on completing a wrong answer.&lt;br&gt;
Output tokens are significantly more expensive than input tokens (often 5x the price).&lt;/p&gt;
&lt;h3&gt;
  
  
  Beware of Cache Misses on Idle Sessions
&lt;/h3&gt;

&lt;p&gt;To maximize the benefits of prompt caching on Claude subscriptions, avoid leaving an active session &lt;a href="https://code.claude.com/docs/en/prompt-caching#cache-lifetime" rel="noopener noreferrer"&gt;idle for more than an hour&lt;/a&gt; without completing the task.&lt;/p&gt;

&lt;p&gt;If the 1-hour &lt;a href="https://code.claude.com/docs/en/costs#why-usage-climbs-in-a-long-session" rel="noopener noreferrer"&gt;cache expires&lt;/a&gt;, your next prompt will force a full cache rewrite of your entire context. Depending on the model, a cache write is 20x to 80x more expensive than a cache read under &lt;a href="https://code.claude.com/docs/en/prompt-caching#which-ttl-each-request-gets" rel="noopener noreferrer"&gt;1-hour cache TTL&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  My recommendation
&lt;/h4&gt;

&lt;p&gt;Always try to complete your task with Claude without leaving the session idle for over an hour. &lt;/p&gt;

&lt;p&gt;Treat your sessions like focused sprints. Aim to finish your current interaction with Claude before taking a long break. Stepping away for more than an hour expires the cache, forcing a full cache rewrite for the entire context.&lt;/p&gt;
&lt;h3&gt;
  
  
  Resetting to a Clean Session
&lt;/h3&gt;

&lt;p&gt;When we want to start a fresh session, we use the &lt;code&gt;/clear&lt;/code&gt; command.&lt;/p&gt;
&lt;h4&gt;
  
  
  Is it added to the context?
&lt;/h4&gt;

&lt;p&gt;While this initiates a new session, it ironically adds the &lt;code&gt;/clear&lt;/code&gt; command itself into the new context, along with text explaining that this is a user command. This adds ~130 tokens.&lt;/p&gt;
&lt;h4&gt;
  
  
  Does this action consume tokens?
&lt;/h4&gt;

&lt;p&gt;No. The command itself is executed locally and does not trigger an API call or consume tokens.&lt;/p&gt;
&lt;h4&gt;
  
  
  Workaround
&lt;/h4&gt;

&lt;p&gt;If you want a truly empty context, you have two options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Restart the Claude Code CLI entirely.&lt;/li&gt;
&lt;li&gt;Run the &lt;code&gt;/rewind&lt;/code&gt; command and revert to the message that says "/clear". This gives you a completely empty context.
&lt;strong&gt;Bug Note:&lt;/strong&gt; There is currently a bug in Claude Code where rewinding to the very beginning of the conversation causes the Skills list to fail to load into the context. This means that if you later want to use a skill, Claude will have to read the skill files manually, which wasting tokens.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Efficient and cost-effective development with Claude Code isn't just about smart prompting. It requires a deep understanding of what happens behind the scenes to make informed use of tokens and properly manage context.&lt;br&gt;
As we've seen, reducing costs comes down to two key areas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Precise system settings:&lt;/strong&gt; Disabling default background features (recap summaries, prompt suggestions, classifier auto-modes) and enabling efficient tools like LSP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disciplined workflow habits:&lt;/strong&gt; Interrupting generations early with &lt;code&gt;ESC&lt;/code&gt;, rolling back mistakes with &lt;code&gt;/rewind&lt;/code&gt;, managing side questions with &lt;code&gt;/btw&lt;/code&gt;, and delegating verbose text-analysis tasks to subagents.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ultimately, the goal isn't to turn off every feature or limit your developer experience, but to manage your environment wisely - ensuring that every token you pay for brings real value to your codebase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here is a summary of the settings discussed in this article:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"promptSuggestionEnabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"awaySummaryEnabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"autoMemoryEnabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"respondToBashCommands"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"disableAutoMode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"useAutoModeDuringPlan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"defaultMode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"acceptEdits"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allow"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Bash(git status)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Bash(git diff:*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Bash(npm test:*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Bash(npm run build)"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>claude</category>
      <category>claudecode</category>
      <category>ai</category>
      <category>context</category>
    </item>
    <item>
      <title>How to Reduce Claude Code's Initial Context and Avoid Prompt Cache Breaks</title>
      <dc:creator>Fogel</dc:creator>
      <pubDate>Wed, 23 Sep 2026 09:24:30 +0000</pubDate>
      <link>https://dev.to/fogel/how-to-reduce-claude-codes-initial-context-and-avoid-prompt-cache-breaks-12fg</link>
      <guid>https://dev.to/fogel/how-to-reduce-claude-codes-initial-context-and-avoid-prompt-cache-breaks-12fg</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Lately, discussions around token optimization in Claude Code have focused primarily on skills, external tools, and optimizing &lt;code&gt;CLAUDE.md&lt;/code&gt;. However, I noticed there is much less discussion about the massive savings you can achieve simply by configuring Claude Code's built-in settings correctly.&lt;/p&gt;

&lt;p&gt;Curious about what the Claude Code harness actually adds behind the scenes, I decided to dive into its settings and environment variables. The results were much more interesting than I expected, which inspired me to write a series of articles on the topic.&lt;/p&gt;

&lt;p&gt;In this article, I will break down the components of the &lt;strong&gt;Initial Context&lt;/strong&gt; that Claude Code builds at the beginning of a new session. I'll analyze how many tokens these components consume and whether they dynamically change between sessions (which causes cache invalidation). &lt;/p&gt;

&lt;p&gt;The goal of this article isn't to reduce the context to the absolute bare minimum. The goal is to remove data that is not useful for our work with Claude Code while preserving the capabilities we actually need for our workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Initial Context?
&lt;/h2&gt;

&lt;p&gt;The Initial Context is the foundational information that Claude Code adds at the beginning of a session. Part of it is sent as a top-level System Prompt within the &lt;code&gt;system&lt;/code&gt; array, and another part is added immediately after the first user prompt inside the &lt;code&gt;messages&lt;/code&gt; array.&lt;/p&gt;

&lt;p&gt;The initial context consists of the following elements:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inside the &lt;code&gt;tools&lt;/code&gt; array:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tools like Write, Read, Artifact, Glob, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Inside the &lt;code&gt;system&lt;/code&gt; array:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;System prompts&lt;/li&gt;
&lt;li&gt;Memory instructions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Inside the &lt;code&gt;messages&lt;/code&gt; array:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CLAUDE.md&lt;/li&gt;
&lt;li&gt;Git instructions&lt;/li&gt;
&lt;li&gt;Deferred tools list (without schemas)&lt;/li&gt;
&lt;li&gt;Built-in agents&lt;/li&gt;
&lt;li&gt;Skills&lt;/li&gt;
&lt;li&gt;Information from the IDE&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The earlier a token appears in the conversation with Claude, the more expensive its cumulative cost becomes. This is because every new prompt we send to the model includes the Initial Context and the entire conversation history. Therefore, since the initial context accompanies us from the very first message, it has the highest cumulative impact on token consumption.&lt;/p&gt;

&lt;p&gt;Furthermore, the more irrelevant text you feed into models, the more they tend to lose focus. The context should contain as much relevant information as possible, and as little irrelevant information as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does Prompt Caching work?
&lt;/h2&gt;

&lt;p&gt;Every time you send a prompt to Claude, the entire context (initial context + conversation history) is sent along with it. Instead of reprocessing the same text over and over again, Claude can read previously processed text from its cache, process only the new text, and write that new text to the cache. This makes responses significantly faster and drastically reduces costs.&lt;/p&gt;

&lt;p&gt;This mechanism relies on &lt;strong&gt;Prefix Matching&lt;/strong&gt;: The model reads sequentially from the cache starting from the beginning of the prompt, until it reaches the first change in the text. The moment a single character changes in the middle of the context, all the information following it is no longer read from the cache - it is rewritten to the cache at full price. &lt;br&gt;
Therefore, our goal is to keep the beginning of our context as static as possible and avoid dynamic content.&lt;/p&gt;

&lt;p&gt;According to Claude's &lt;a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#pricing" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;, reading tokens from the cache costs a fraction of the base input token price. Currently, writing to a 1-hour cache costs 2x the base input token price, while a cache read costs at most 0.1x the base input token price. &lt;br&gt;
For example, with Claude Opus 5, writing to a 1-hour cache costs $10 per million tokens, while reading from it costs only $0.50 per million tokens - a &lt;strong&gt;20x&lt;/strong&gt; price difference. Furthermore, in Claude Opus 5.5, this gap widens to a massive &lt;strong&gt;40x&lt;/strong&gt; price difference, and models like Claude Fable 5.1 push this gap to a significant &lt;strong&gt;80x&lt;/strong&gt; price difference!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If we don't send a prompt to Claude within the defined cache TTL (5 minutes or 1 hour), the cache expires. The next time we send a message, the entire context will be rewritten to the cache from scratch instead of being read from it.&lt;/p&gt;
&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;I found that Claude Code adds several components to the initial context that aren't necessarily needed for every task. By applying the configurations detailed in this article, I reduced the Initial Context from &lt;strong&gt;35,011 tokens to 17,862 tokens&lt;/strong&gt; (a ~49% reduction). Furthermore, the number of tokens forced to be rewritten to the cache in subsequent sessions dropped from &lt;strong&gt;7,333 to 0&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Ultimately, you can decide which of these components are essential for your specific workflow with Claude Code.&lt;/p&gt;
&lt;h3&gt;
  
  
  Results by Component
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Added to Context&lt;/th&gt;
&lt;th&gt;Cache Invalidation Risk&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Artifact&lt;/td&gt;
&lt;td&gt;11,403 tokens&lt;/td&gt;
&lt;td&gt;Always breaks the cache&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Git instructions&lt;/td&gt;
&lt;td&gt;~500 tokens&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auto memory&lt;/td&gt;
&lt;td&gt;738 tokens + &lt;code&gt;MEMORY.md&lt;/code&gt; content&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skills&lt;/td&gt;
&lt;td&gt;~2,100 tokens&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Docs MCP&lt;/td&gt;
&lt;td&gt;~1,701 tokens&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IDE Integration&lt;/td&gt;
&lt;td&gt;~100 tokens (manually removable)&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Bonus:&lt;/strong&gt; I also discovered how Claude Code's payload ordering breaks the cache on the very first prompt, and how starting every session with a generic "Hi" can save you ~65% on your initial prompt costs.&lt;/p&gt;
&lt;h2&gt;
  
  
  How were the tests performed?
&lt;/h2&gt;

&lt;p&gt;To truly understand what Claude Code adds to the context, I intercepted and analyzed the network traffic of the API requests Claude Code makes when sending a message. &lt;br&gt;
I mapped the &lt;code&gt;tools&lt;/code&gt;, &lt;code&gt;system&lt;/code&gt;, and &lt;code&gt;messages&lt;/code&gt; arrays in the payload against the available configurations in &lt;a href="https://code.claude.com/docs/en/settings#available-settings" rel="noopener noreferrer"&gt;&lt;code&gt;settings.json&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://code.claude.com/docs/en/env-vars#variables" rel="noopener noreferrer"&gt;environment variables&lt;/a&gt;. For every overlapping setting, I compared the API request before and after the change, comparing both content and token count.&lt;/p&gt;
&lt;h3&gt;
  
  
  How did I measure the number of tokens?
&lt;/h3&gt;

&lt;p&gt;I used two methods:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The &lt;code&gt;/context&lt;/code&gt; command:&lt;/strong&gt; Behind the scenes, this command triggers several API calls to count the number of input tokens for different parts of the system prompt and tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A Regular Prompt:&lt;/strong&gt; I also sent a simple prompt ("hi") to trigger a full-context API call. The API response indicates exactly how many tokens were read from the cache and how many were written to it.
In addition, I compared the context text sent before and after each configuration change to understand the specific setting's contribution to the session's context.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Test Environment
&lt;/h2&gt;

&lt;p&gt;The tests presented in this article were performed using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Code version 2.1.278.&lt;/li&gt;
&lt;li&gt;Model: Claude Opus 5 (unless otherwise specified).&lt;/li&gt;
&lt;li&gt;A Claude subscription which, according to Claude Code documentation, utilizes a one-hour TTL cache.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: These results were measured in this specific environment. Initial context structure, token counts, and caching behavior may vary across Claude Code versions and models.&lt;br&gt;
Also note that according to Claude's documentation, models from version 4.7 and above use a different tokenizer and consume up to 30% more tokens. Therefore, for Claude 4.7 and above, the quantitative token savings will be even more significant.&lt;/p&gt;


&lt;h2&gt;
  
  
  Deep Dive by Component
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Artifact
&lt;/h3&gt;

&lt;p&gt;Artifacts allow us to generate and share web pages via a private URL on claude.ai. For my own use cases, I don't need this feature, so I decided to test its impact on the Initial Context. It is enabled by default.&lt;/p&gt;
&lt;h4&gt;
  
  
  What does it add to the context?
&lt;/h4&gt;

&lt;p&gt;Comparing the context with Artifact enabled vs. disabled revealed:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;Scratchpad Directory&lt;/code&gt; path is added to the system prompt in the &lt;code&gt;messages&lt;/code&gt; array (&lt;strong&gt;222 tokens&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;Artifact-specific skills and descriptions are added (which can also be viewed using &lt;code&gt;/context all&lt;/code&gt;)

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;design&lt;/code&gt; (&lt;strong&gt;340 tokens&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;artifact-design&lt;/code&gt; (&lt;strong&gt;70 tokens&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;artifact-diagramming&lt;/code&gt; (&lt;strong&gt;70 tokens&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;artifact-capabilities&lt;/code&gt; (&lt;strong&gt;220 tokens&lt;/strong&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;An &lt;code&gt;Artifact&lt;/code&gt; tool is added (&lt;strong&gt;10,481 tokens&lt;/strong&gt;).
&lt;strong&gt;Total addition: 11,403 tokens.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
  
  
  Impact on Prompt Caching
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;Scratchpad Directory&lt;/code&gt; path added to the system prompt in the &lt;code&gt;messages&lt;/code&gt; array contains a unique Session ID. Because this ID changes between sessions, it alters the system prompt and guarantees a cache miss.&lt;/p&gt;

&lt;p&gt;Therefore, I decided to measure the impact of that cache miss on the number of tokens that had to be written to the cache instead of read from it.&lt;/p&gt;

&lt;p&gt;To prove this, I compared cache writes across four new, clean sessions, sending identical prompts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Artifact Enabled:&lt;/strong&gt; All tokens (34,724) were written to the cache (initial run).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Artifact Enabled:&lt;/strong&gt; The system prompt changed because the directory name changed in the new session, breaking the prefix matching. &lt;strong&gt;7,333 tokens&lt;/strong&gt; were rewritten to the cache.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Artifact Disabled:&lt;/strong&gt; The system prompt changed because the Artifact tool and Scratchpad Directory text were removed, causing a cache miss. &lt;strong&gt;22,972 tokens&lt;/strong&gt; were rewritten.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Artifact Disabled:&lt;/strong&gt; The system prompt remained completely static, so there was no cache miss. &lt;strong&gt;0 tokens were rewritten&lt;/strong&gt;, everything was read from the cache.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
  
  
  Summary of disabling Artifact:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Saves 11,403 tokens on every single prompt.&lt;/li&gt;
&lt;li&gt;Prevents guaranteed cache misses between sessions caused by content that changes in the system prompt. Converting a 7,333-token write into a read is particularly significant (remember the 20x to 80x price difference).&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  How to disable:
&lt;/h4&gt;

&lt;p&gt;Add &lt;code&gt;"enableArtifact": false&lt;/code&gt; to your global or project &lt;code&gt;settings.json&lt;/code&gt;, or set the environment variable: &lt;code&gt;CLAUDE_CODE_DISABLE_ARTIFACT=1&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Git Instructions
&lt;/h3&gt;

&lt;p&gt;When working inside a Git repository, Claude Code adds your current Git status and recent commits into the system prompt in the &lt;code&gt;messages&lt;/code&gt; array. This is enabled by default.&lt;/p&gt;
&lt;h4&gt;
  
  
  What does it add to the context?
&lt;/h4&gt;

&lt;p&gt;I compared the context with Git instructions enabled vs. disabled.&lt;br&gt;
It adds approximately &lt;strong&gt;500 tokens&lt;/strong&gt; to the system prompt.&lt;/p&gt;
&lt;h4&gt;
  
  
  Impact on Prompt Caching
&lt;/h4&gt;

&lt;p&gt;Because the status of files in your working directory and your recent commits change frequently, this introduces a high risk of cache misses. I tested this by creating a new file and starting a new session - this caused &lt;strong&gt;6,415 tokens&lt;/strong&gt; to be rewritten to the cache.&lt;/p&gt;
&lt;h4&gt;
  
  
  Trade-offs
&lt;/h4&gt;

&lt;p&gt;If disabled, Claude won't automatically know what branch you are on or what the current Git status is, unless it explicitly runs a git command to check.&lt;/p&gt;
&lt;h4&gt;
  
  
  My Recommendation
&lt;/h4&gt;

&lt;p&gt;Since this is highly dynamic information and Claude Code can easily retrieve it using terminal commands when needed, it is better to avoid including it in the system prompt.&lt;/p&gt;
&lt;h4&gt;
  
  
  How to disable:
&lt;/h4&gt;

&lt;p&gt;Add &lt;code&gt;"includeGitInstructions": false&lt;/code&gt; to &lt;code&gt;settings.json&lt;/code&gt;, either globally or at the project level. Another option is to set: &lt;code&gt;CLAUDE_CODE_DISABLE_GIT_INSTRUCTIONS=1&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Auto Memory
&lt;/h3&gt;

&lt;p&gt;Auto memory allows Claude to accumulate knowledge across sessions automatically without requiring manual input. It is enabled by default.&lt;/p&gt;
&lt;h4&gt;
  
  
  What does it add to the context?
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Instructions for managing memory located in the system prompt (&lt;strong&gt;~738 tokens&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;The actual content of the &lt;code&gt;MEMORY.md&lt;/code&gt; file (Claude loads up to the first 200 lines or 25K, whichever comes first).
Therefore, the actual number of tokens added by this component varies.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
  
  
  Impact on Prompt Caching
&lt;/h4&gt;

&lt;p&gt;Because &lt;code&gt;MEMORY.md&lt;/code&gt; gets updated, changes to this file between sessions will break the cache. &lt;/p&gt;
&lt;h4&gt;
  
  
  Ongoing Token Consumption During the Conversation
&lt;/h4&gt;

&lt;p&gt;In addition, the act of Claude Code updating the auto-memory contents (&lt;code&gt;MEMORY.md&lt;/code&gt;) during a conversation consumes additional tokens beyond those required to load the context.&lt;/p&gt;
&lt;h4&gt;
  
  
  Summary of disabling Auto Memory:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Saves 738 tokens from the system prompt.&lt;/li&gt;
&lt;li&gt;Saves the tokens required for the first 200 lines or first 25K of &lt;code&gt;MEMORY.md&lt;/code&gt;, whichever comes first.&lt;/li&gt;
&lt;li&gt;Prevents cache invalidation caused by changes to &lt;code&gt;MEMORY.md&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Prevents logical conflicts between Auto Memory and other information in the context, such as &lt;code&gt;CLAUDE.md&lt;/code&gt; or our conversation history.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  How to disable:
&lt;/h4&gt;

&lt;p&gt;You can disable auto memory using &lt;code&gt;/memory&lt;/code&gt;, or add &lt;code&gt;"autoMemoryEnabled": false&lt;/code&gt; to the global &lt;code&gt;settings.json&lt;/code&gt;, or set &lt;code&gt;CLAUDE_CODE_DISABLE_AUTO_MEMORY=1&lt;/code&gt;.&lt;br&gt;
See the &lt;a href="https://code.claude.com/docs/en/memory#enable-or-disable-auto-memory" rel="noopener noreferrer"&gt;Claude Code memory documentation&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Skills
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Disabling Skill Auto-Invocation
&lt;/h4&gt;

&lt;p&gt;When a new skill is added, its name and description are added to the context. A skill can be triggered in two ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Claude decides to use it based on its description (Auto-invocation).&lt;/li&gt;
&lt;li&gt;The user explicitly invokes the skill using &lt;code&gt;/skill-name&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can disable auto-invocation (the first way). If you do, the skill's description is removed from the initial context, saving tokens, but you will have to call it manually using /skill-name.&lt;/p&gt;

&lt;p&gt;Here are several ways to disable auto-invocation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Specific skill:&lt;/strong&gt; Add &lt;a href="https://code.claude.com/docs/en/skills#control-who-invokes-a-skill" rel="noopener noreferrer"&gt;&lt;code&gt;disable-model-invocation: true&lt;/code&gt;&lt;/a&gt;  to the skill's frontmatter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;All project skills:&lt;/strong&gt; Use the &lt;a href="https://code.claude.com/docs/en/skills#override-skill-visibility-from-settings" rel="noopener noreferrer"&gt;&lt;code&gt;skillOverrides&lt;/code&gt;&lt;/a&gt; setting. Use it for skills whose SKILL.md you don’t want to edit, like skills you didn't write yourself. (Note: this doesn't affect plugin skills. Plugin skills must be managed using &lt;code&gt;/plugin&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;All skills (including plugins):&lt;/strong&gt; A clever workaround to prevent auto-invocation for all skills, including plugin skills, is using the setting &lt;code&gt;"skillListingMaxDescChars": 1&lt;/code&gt;. This truncates all descriptions, saving at least &lt;strong&gt;~2,000 tokens&lt;/strong&gt; when including the built-in skills.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Disabling Built-in Skills
&lt;/h4&gt;

&lt;p&gt;Claude Code includes several built-in skills (like &lt;code&gt;keybindings-help&lt;/code&gt; or &lt;code&gt;claude-api&lt;/code&gt;) that you might rarely use.&lt;br&gt;
The full list of built-in skills can be viewed using: &lt;code&gt;/context all&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Context addition:&lt;/strong&gt; Names and descriptions of bundled skills add about &lt;strong&gt;2,134 tokens&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;How to disable:&lt;/strong&gt; Add &lt;code&gt;"disableBundledSkills": true&lt;/code&gt; to &lt;code&gt;settings.json&lt;/code&gt;. (Note: This completely removes them, meaning you cannot invoke them manually either).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  5. Claude Docs MCP
&lt;/h3&gt;

&lt;p&gt;This is a connector that links to Claude Docs on claude.ai. It allows Claude to create, read, edit, comment on, and export documents stored in your claude.ai account. They're not files in your repository.&lt;/p&gt;
&lt;h4&gt;
  
  
  What does it add to the context?
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Instructions on how to use its tools and resources, located in the system prompt in the &lt;code&gt;messages&lt;/code&gt; array (&lt;strong&gt;~1,031 tokens&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;The MCP tools of Claude Docs are loaded (which can also be viewed using &lt;code&gt;/context all&lt;/code&gt;)

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;mcp__claude_ai_Claude_Docs__batch&lt;/code&gt; (&lt;strong&gt;163 tokens&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mcp__claude_ai_Claude_Docs__guide&lt;/code&gt; (&lt;strong&gt;212 tokens&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mcp__claude_ai_Claude_Docs__update&lt;/code&gt; (&lt;strong&gt;295 tokens&lt;/strong&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It adds approximately &lt;strong&gt;1,701 tokens&lt;/strong&gt; to the context.&lt;/p&gt;
&lt;h4&gt;
  
  
  Impact on Prompt Caching
&lt;/h4&gt;

&lt;p&gt;It doesn't affect prompt caching.&lt;/p&gt;
&lt;h4&gt;
  
  
  My Recommendation
&lt;/h4&gt;

&lt;p&gt;Since I don't see a reason to use this within Claude Code, I prefer to disable it.&lt;/p&gt;
&lt;h4&gt;
  
  
  How to disable
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;/mcp&lt;/code&gt;, select "claude.ai Claude Docs" and disable it.&lt;/li&gt;
&lt;li&gt;Alternatively, remove or disconnect the connector in your claude.ai settings under Connectors. That affects every client using your account, not just Claude Code.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'd recommend disabling it via &lt;code&gt;/mcp&lt;/code&gt; if you only want to turn it off for Claude Code.&lt;/p&gt;
&lt;h3&gt;
  
  
  6. IDE Integration
&lt;/h3&gt;

&lt;p&gt;If you run Claude Code inside an IDE terminal (like VS Code), it automatically connects to the IDE. &lt;br&gt;
Personally, I often have a file open in the IDE (sometimes with text selected) that is completely unrelated to what I'm asking Claude to do in the terminal.&lt;br&gt;
In that situation, the IDE adds the text &lt;code&gt;[⧉ In filename.ext]&lt;/code&gt; or &lt;code&gt;[⧉ X lines selected]&lt;/code&gt; to the beginning of the terminal prompt line, even though it may not be relevant to the current conversation.&lt;br&gt;
This increases token consumption, can reduce the model's focus, and may even lead to incorrect answers.&lt;br&gt;
You can easily remove it with backspace, just as you would with any other part of the prompt.&lt;/p&gt;
&lt;h4&gt;
  
  
  What does it add to the context?
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;The name of the currently active file in the IDE (Adds &lt;strong&gt;~100 tokens&lt;/strong&gt;). You can remove it manually from the prompt.&lt;/li&gt;
&lt;li&gt;Currently selected lines of the open file in the IDE (Adds a dynamic token count).&lt;/li&gt;
&lt;li&gt;Errors showing in the IDE's "Problems" tab (Adds dynamic token count).&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
  
  
  Impact on Prompt Caching
&lt;/h4&gt;

&lt;p&gt;Because it is added to the end of the context, it doesn't affect prompt caching.&lt;/p&gt;
&lt;h4&gt;
  
  
  My Recommendation
&lt;/h4&gt;

&lt;p&gt;I personally prefer that Claude does not automatically consider whichever file happens to be open in my IDE, so I disable the "Attach Open File" setting.&lt;/p&gt;
&lt;h4&gt;
  
  
  How to disable:
&lt;/h4&gt;

&lt;p&gt;You can &lt;a href="https://code.claude.com/docs/en/vs-code#reference-files-and-folders" rel="noopener noreferrer"&gt;prevent Claude Code from adding the currently open file in the editor&lt;/a&gt;  by disabling the &lt;a&gt;&lt;strong&gt;Attach Open File setting&lt;/strong&gt;&lt;/a&gt; in your VSCode settings. When disabled, only the text you actively select is added.&lt;/p&gt;

&lt;p&gt;You can also open VS Code settings (&lt;code&gt;Cmd+,&lt;/code&gt; on Mac or &lt;code&gt;Ctrl+,&lt;/code&gt; on Windows/Linux), go to Extensions -&amp;gt; Claude Code, and uncheck &lt;strong&gt;Attach Open File&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Extra Insight: The First Prompt Cache Trap
&lt;/h2&gt;

&lt;p&gt;While analyzing the API payloads, I noticed something interesting: there is a specific System Prompt block that is not sent as part of the &lt;code&gt;system&lt;/code&gt; array. Instead, it is added to the &lt;code&gt;messages&lt;/code&gt; array immediately after the user's first prompt.&lt;/p&gt;

&lt;p&gt;This added System Prompt block contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Code CLI Environment&lt;/li&gt;
&lt;li&gt;The deferred tools list&lt;/li&gt;
&lt;li&gt;Built-in agents&lt;/li&gt;
&lt;li&gt;Skills list&lt;/li&gt;
&lt;li&gt;IDE integration data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because Prompt Caching relies on Prefix Matching (matching from the start of the text until the first change), &lt;strong&gt;sending a different first prompt in a new session breaks the sequence immediately.&lt;/strong&gt; &lt;br&gt;
As a result, that entire massive system block added after your first prompt is treated as "new" text and is written to the cache at the 20x to 80x price!&lt;/p&gt;

&lt;p&gt;I tested two sequential sessions (with Artifact disabled, as it always breaks prompt caching):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Cache Read&lt;/th&gt;
&lt;th&gt;Cache Write&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Two sessions with the &lt;strong&gt;same&lt;/strong&gt; first prompt&lt;/td&gt;
&lt;td&gt;23,978 tokens&lt;/td&gt;
&lt;td&gt;0 tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Two sessions with a &lt;strong&gt;different&lt;/strong&gt; first prompt&lt;/td&gt;
&lt;td&gt;17,566 tokens&lt;/td&gt;
&lt;td&gt;6,412 tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As you can see, changing your first prompt causes Claude to rewrite 6,412 tokens of the system prompt to the cache.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Practical Workaround: The Static "Hi"
&lt;/h3&gt;

&lt;p&gt;To prevent this cache break, I tested a workflow where I open every new session with a static prompt (e.g., "Hi"). Once Claude responds, I send my actual prompt. &lt;/p&gt;

&lt;p&gt;I compared the costs of asking &lt;em&gt;"What model are you using?"&lt;/em&gt; in two scenarios:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario A: Sending the question (actual prompt) directly as the first prompt&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Cache Read&lt;/th&gt;
&lt;th&gt;Cache Write&lt;/th&gt;
&lt;th&gt;Total Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Prompt 1: "What model are you using?"&lt;/td&gt;
&lt;td&gt;17,566&lt;/td&gt;
&lt;td&gt;6,416&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.072943&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Scenario B: Starting with a Fixed First Prompt (&lt;code&gt;"Hi"&lt;/code&gt;), then asking the question (actual prompt)&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Cache Read&lt;/th&gt;
&lt;th&gt;Cache Write&lt;/th&gt;
&lt;th&gt;Total Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Prompt 1: "Hi"&lt;/td&gt;
&lt;td&gt;23,978&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;$0.011989&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prompt 2: "What model are you using?"&lt;/td&gt;
&lt;td&gt;23,978&lt;/td&gt;
&lt;td&gt;146&lt;/td&gt;
&lt;td&gt;$0.013449&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;47,956&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;146&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.025438&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt;&lt;br&gt;
Even though Scenario B required two API calls and processed double the total tokens, &lt;strong&gt;the overall cost dropped by 65%&lt;/strong&gt;. We successfully converted an expensive cache write into a cheap cache read.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This workaround only saves money if you are starting a new session within 1 hour of your previous prompt. If your cache has completely expired, you will pay for a full rewrite regardless, so you might as well send your actual prompt first (in our example: "What model are you using?").&lt;/p&gt;


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

&lt;p&gt;The goal of this optimization is to achieve a context window that only contains data actively contributing to the current session, while keeping that data as static as possible to maximize prompt caching.&lt;/p&gt;

&lt;p&gt;By understanding the API payload structure and tweaking Claude Code's settings, we achieved four major goals:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Token savings:&lt;/strong&gt; Reduced the initial context from 35,011 to 17,862 tokens, a 49% drop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompt cache stability:&lt;/strong&gt; Eliminated dynamic text in the initial context (like the Scratchpad path) that breaks prefix matching and causes cache misses, dropping token rewrites from 7,333 to 0.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model focus:&lt;/strong&gt; Removed irrelevant background information (like randomly opened IDE files), allowing Claude to focus entirely on the actual prompt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workaround for the first prompt cache trap:&lt;/strong&gt; Understanding that a system prompt block containing skills and other metadata is inserted after the first user prompt inside the &lt;code&gt;messages&lt;/code&gt; array allows us to use a fixed opening prompt (such as &lt;code&gt;"Hi"&lt;/code&gt;). This saves approximately 65% on the cost of the initial prompt in sessions where the previous session occurred within the last hour.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every developer should decide which of these components are worth their token cost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here is a summary of the settings discussed in this article:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;~/.claude/settings.json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;.claude/settings.json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;project&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"CLAUDE_CODE_DISABLE_ARTIFACT"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"CLAUDE_CODE_DISABLE_GIT_INSTRUCTIONS"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"CLAUDE_CODE_DISABLE_AUTO_MEMORY"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"disableBundledSkills"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"skillListingMaxDescChars"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Disabling Claude Docs MCP:&lt;/strong&gt; Run &lt;code&gt;/mcp&lt;/code&gt;, select "claude.ai Claude Docs" and disable it.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/fogel/how-default-settings-and-bad-habits-are-draining-your-claude-code-budget-484m"&gt;next article&lt;/a&gt;, we will focus on workflows and configurations to save tokens during active, ongoing conversations, rather than just the initial context. Stay tuned!&lt;/p&gt;

</description>
      <category>claude</category>
      <category>claudecode</category>
      <category>ai</category>
      <category>context</category>
    </item>
    <item>
      <title>Potential issues with barrel files in Jest</title>
      <dc:creator>Fogel</dc:creator>
      <pubDate>Wed, 22 May 2024 09:02:23 +0000</pubDate>
      <link>https://dev.to/fogel/potential-issues-with-barrel-files-in-jest-1nkl</link>
      <guid>https://dev.to/fogel/potential-issues-with-barrel-files-in-jest-1nkl</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In the previous article, &lt;a href="https://dev.to/fogel/potential-issues-with-barrel-files-in-webpack-4bf2"&gt;&lt;em&gt;Potential issues with barrel files in Webpack&lt;/em&gt;&lt;/a&gt;, we discussed the potential issues of using barrel files in Webpack. In this article, we will focus on the issues of using them in Jest tests.&lt;/p&gt;

&lt;p&gt;For a comprehensive understanding of barrel files and their use cases, I recommend reading the previous article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Barrel files in Jest
&lt;/h2&gt;

&lt;p&gt;Unlike Webpack, Jest does not have a tree shaking feature. This means that when you import modules through barrel files, Jest will include all the exported modules from barrel files in your tests, even those that are not used. This behavior can lead to two significant issues: slow performance and unexpected test results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Issues
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Performance Impact
&lt;/h3&gt;

&lt;p&gt;One of the most common complaints from developers who use Jest often report slow test execution times when their code includes barrel files &lt;a href="https://github.com/jestjs/jest/issues/11234" rel="noopener noreferrer"&gt;#1&lt;/a&gt;. While this might not be noticeable in smaller projects, it becomes a significant issue in larger ones.&lt;/p&gt;

&lt;p&gt;This issue arises because Jest needs to load all the modules exported from a barrel file, regardless of their usage. This can significantly increase loading time, especially if the barrel file contains numerous modules.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;

&lt;p&gt;To illustrate this issue, let's consider the &lt;em&gt;&lt;a href="https://github.com/FogelAI/jest-barrel-issues-article/tree/main/examples/perf-impact" rel="noopener noreferrer"&gt;perf-impact&lt;/a&gt;&lt;/em&gt; example repository.&lt;br&gt;
In this repository, we want to test the Javascript file &lt;em&gt;&lt;a href="https://github.com/FogelAI/jest-barrel-issues-article/tree/main/examples/perf-impact/src/indirect-import.js" rel="noopener noreferrer"&gt;indirect-import.js&lt;/a&gt;&lt;/em&gt; that imports only the &lt;code&gt;Reexported1&lt;/code&gt; specifier from a barrel file &lt;em&gt;&lt;a href="https://github.com/FogelAI/jest-barrel-issues-article/tree/main/examples/perf-impact/src/components/index.js" rel="noopener noreferrer"&gt;index.js&lt;/a&gt;&lt;/em&gt;, which re-exports 100 modules.&lt;/p&gt;

&lt;p&gt;Let's create a test for this file named &lt;em&gt;&lt;a href="https://github.com/FogelAI/jest-barrel-issues-article/tree/main/examples/perf-impact/src/indirect-import.test.js" rel="noopener noreferrer"&gt;indirect-import.test.js&lt;/a&gt;&lt;/em&gt; and run &lt;code&gt;npm run test&lt;/code&gt; and observe the performance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fvt0gtpk73abnfugzmy9p.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fvt0gtpk73abnfugzmy9p.PNG" alt="Execution time without a Babel plugin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The test execution takes an average of 2.865 seconds, which is significant for a single test. Imagine the time it would take for hundreds of tests relying on barrel files!&lt;/p&gt;

&lt;p&gt;Why is it slow? When importing from barrel files, Jest loads all the modules, even unused ones, impacting performance.&lt;br&gt;
We need a solution for this poor test performance.&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;One solution could be to avoid using barrel files altogether, but this would negatively impact our developer experience.&lt;/p&gt;

&lt;p&gt;Another solution can be using a tool that will automatically transform indirect imports to direct imports.&lt;br&gt;
To address this, I developed a Babel plugin, &lt;a href="https://github.com/FogelAI/babel-plugin-transform-barrels" rel="noopener noreferrer"&gt;&lt;code&gt;babel-plugin-transform-barrels&lt;/code&gt;&lt;/a&gt;, that transforms indirect imports (through barrel files) into direct imports.&lt;/p&gt;

&lt;p&gt;Let's apply the &lt;code&gt;babel-plugin-transform-barrels&lt;/code&gt; plugin solution as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clone the &lt;em&gt;&lt;a href="https://github.com/FogelAI/jest-barrel-issues-article/tree/main/examples/perf-impact" rel="noopener noreferrer"&gt;perf-impact&lt;/a&gt;&lt;/em&gt; repository to a new &lt;code&gt;perf-impact-with-barrel-plugin&lt;/code&gt; repository.&lt;/li&gt;
&lt;li&gt;Install the &lt;a href="https://github.com/FogelAI/babel-plugin-transform-barrels" rel="noopener noreferrer"&gt;&lt;code&gt;babel-plugin-transform-barrels&lt;/code&gt;&lt;/a&gt; plugin.&lt;/li&gt;
&lt;li&gt;Copy the &lt;a href="https://github.com/FogelAI/babel-plugin-transform-barrels/blob/main/config/jest/babelTransform.js" rel="noopener noreferrer"&gt;&lt;code&gt;babelTransform.js&lt;/code&gt;&lt;/a&gt; file into the folder &lt;code&gt;config\jest&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Adapt the &lt;code&gt;babelTransform.js&lt;/code&gt; file to the current repository.&lt;/li&gt;
&lt;li&gt;In the &lt;code&gt;jest.config.js&lt;/code&gt; file, reference the &lt;code&gt;transform&lt;/code&gt; object to the &lt;code&gt;babelTransform.js&lt;/code&gt; file instead of the &lt;code&gt;regularTransform.js&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;Run the command &lt;code&gt;npm run test&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.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%2Ftwmzichiolg3fqeiuqx1.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ftwmzichiolg3fqeiuqx1.PNG" alt="Execution time with a Babel plugin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, see that the test time dropped from 2.865 seconds to 1.31 seconds, which is a reduction of more than 50%. This improvement is very significant!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;br&gt;
The above steps have been implemented in the &lt;em&gt;&lt;a href="https://github.com/FogelAI/jest-barrel-issues-article/tree/main/examples/perf-impact-with-barrel-plugin" rel="noopener noreferrer"&gt;perf-impact-with-barrel-plugin&lt;/a&gt;&lt;/em&gt; repository.&lt;/p&gt;

&lt;p&gt;Now that we’ve addressed the performance issue, let’s move on to the next issue.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Unexpected Test Results
&lt;/h3&gt;

&lt;p&gt;Another issue can arise when we import a module from a barrel file that contains unused modules, some of these unused modules can affect the test results in unexpected ways.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;

&lt;p&gt;To illustrate this issue, let's consider the &lt;em&gt;&lt;a href="https://github.com/FogelAI/jest-barrel-issues-article/tree/main/examples/unexpected-results" rel="noopener noreferrer"&gt;unexpected-results&lt;/a&gt;&lt;/em&gt; example repository.&lt;br&gt;
In this repository, we want to test the Javascript file &lt;em&gt;&lt;a href="https://github.com/FogelAI/jest-barrel-issues-article/tree/main/examples/unexpected-results/src/indirect-import.js" rel="noopener noreferrer"&gt;indirect-import.js&lt;/a&gt;&lt;/em&gt; that imports only &lt;code&gt;FirstReexported&lt;/code&gt; specifier from a barrel file &lt;em&gt;&lt;a href="https://github.com/FogelAI/jest-barrel-issues-article/tree/main/examples/unexpected-results/src/components/index.js" rel="noopener noreferrer"&gt;index.js&lt;/a&gt;&lt;/em&gt;, which re-exports all the specifiers from the &lt;code&gt;Reexported&lt;/code&gt; and &lt;code&gt;DropFiles&lt;/code&gt; modules.&lt;/p&gt;

&lt;p&gt;Let's create a test for this Javascript file named &lt;em&gt;&lt;a href="https://github.com/FogelAI/jest-barrel-issues-article/tree/main/examples/unexpected-results/src/indirect-import.test.js" rel="noopener noreferrer"&gt;indirect-import.test.js&lt;/a&gt;&lt;/em&gt; and run &lt;code&gt;npm run test&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F2wayhilq3pjihshczwim.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F2wayhilq3pjihshczwim.PNG" alt="Test failed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see that the test failed. As we can see in the details of the test's result, the failure is caused by the module &lt;code&gt;DropFiles&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But why did the test fail because of an unused module that we didn't want to import? As mentioned earlier, when we import from a barrel file, all the re-exported modules will be loaded, even the unused modules. &lt;/p&gt;

&lt;p&gt;Again, the barrel file caused a problem for us!&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;The solution here is the same as the previous example of &lt;code&gt;perf-impact&lt;/code&gt;. We need to transform the imports from indirect imports (through barrel files) to direct imports.&lt;/p&gt;

&lt;p&gt;Let's do the same steps as the previous example.&lt;/p&gt;

&lt;p&gt;Let's apply the &lt;code&gt;babel-plugin-transform-barrels&lt;/code&gt; plugin solution as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clone the &lt;em&gt;&lt;a href="https://github.com/FogelAI/jest-barrel-issues-article/tree/main/examples/unexpected-results" rel="noopener noreferrer"&gt;unexpected-results&lt;/a&gt;&lt;/em&gt; repository to a new &lt;code&gt;unexpected-results-with-barrel-plugin&lt;/code&gt; repository.&lt;/li&gt;
&lt;li&gt;Install the &lt;a href="https://github.com/FogelAI/babel-plugin-transform-barrels" rel="noopener noreferrer"&gt;&lt;code&gt;babel-plugin-transform-barrels&lt;/code&gt;&lt;/a&gt; plugin.&lt;/li&gt;
&lt;li&gt;Copy the &lt;a href="https://github.com/FogelAI/babel-plugin-transform-barrels/blob/main/config/jest/babelTransform.js" rel="noopener noreferrer"&gt;&lt;code&gt;babelTransform.js&lt;/code&gt;&lt;/a&gt; file into the folder &lt;code&gt;config\jest&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Adapt the &lt;code&gt;babelTransform.js&lt;/code&gt; file to the current repository.&lt;/li&gt;
&lt;li&gt;In the &lt;code&gt;jest.config.js&lt;/code&gt; file, reference the &lt;code&gt;transform&lt;/code&gt; object to the &lt;code&gt;babelTransform.js&lt;/code&gt; file instead of the &lt;code&gt;regularTransform.js&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;Run the command &lt;code&gt;npm run test&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fxt21jfyrfwoemvndwqga.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fxt21jfyrfwoemvndwqga.PNG" alt="Unexpected results example with a Babel plugin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can see that the test passes successfully!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;br&gt;
The above steps have been implemented in the &lt;em&gt;&lt;a href="https://github.com/FogelAI/jest-barrel-issues-article/tree/main/examples/unexpected-results-with-barrel-plugin" rel="noopener noreferrer"&gt;unexpected-results-with-barrel-plugin&lt;/a&gt;&lt;/em&gt; repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;While using barrel files can offer benefits for developer experience, it can also lead to performance issues and unexpected test results in Jest. To resolve them, use the &lt;a href="https://github.com/FogelAI/babel-plugin-transform-barrels" rel="noopener noreferrer"&gt;&lt;code&gt;babel-plugin-transform-barrels&lt;/code&gt;&lt;/a&gt; plugin, which transforms indirect imports (through barrel files) into direct imports.&lt;/p&gt;

&lt;p&gt;This plugin effectively maintains developer experience with test performance and reliability.&lt;/p&gt;

&lt;p&gt;I hope this article has provided you a deeper understanding of the issues with using barrel files in Jest and how the &lt;a href="https://github.com/FogelAI/babel-plugin-transform-barrels" rel="noopener noreferrer"&gt;&lt;code&gt;babel-plugin-transform-barrels&lt;/code&gt;&lt;/a&gt; can be a valuable tool in your testing toolkit.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>jest</category>
      <category>testing</category>
    </item>
    <item>
      <title>Boost Your Webpage Load Performance with the new Webpack plugin</title>
      <dc:creator>Fogel</dc:creator>
      <pubDate>Thu, 05 Oct 2023 13:50:28 +0000</pubDate>
      <link>https://dev.to/fogel/boost-your-webpage-load-performance-with-the-new-webpack-plugin-1kko</link>
      <guid>https://dev.to/fogel/boost-your-webpage-load-performance-with-the-new-webpack-plugin-1kko</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;A website’s initial loading speed can significantly impact user experience and SEO. Slow loading times can bother many users.&lt;br&gt;
To address this issue, I’ve developed a new Webpack plugin called &lt;a href="https://github.com/FogelAI/html-webpack-preload-react-router"&gt;&lt;code&gt;html-webpack-preload-react-router&lt;/code&gt;&lt;/a&gt;. This plugin improves the initial loading speed of a website by reading the react router plain objects and then preloading only the essential async chunk files and performing data fetching. All of that occurs in parallel during the initial load.&lt;/p&gt;
&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;When using react router with code splitting (lazy loading) the process of loading a website is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Downloading and executing the initial HTML file.&lt;/li&gt;
&lt;li&gt;The HTML fetches and executes only the initial Javascripts and CSS chunks.&lt;/li&gt;
&lt;li&gt;The react router code examines the current URL path and runs &lt;code&gt;loader&lt;/code&gt; method if defined.&lt;/li&gt;
&lt;li&gt;The react router code examines the current URL path and fetching and executing only the relevant chunk files based on &lt;code&gt;element&lt;/code&gt; property.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each step involves a network request and happens sequentially. It is a waste of time! In this article we show a solution that 2nd, 3rd and 4th steps will be parallelized network requests, which significantly reducing loading times and improving user experience.&lt;/p&gt;
&lt;h3&gt;
  
  
  A regular initial webpage loading example
&lt;/h3&gt;

&lt;p&gt;Before I show the solution I want to show through a basic example the network waterwall of the traditional react webpage like we described in the &lt;em&gt;Background&lt;/em&gt; section.&lt;/p&gt;

&lt;p&gt;In this example, the &lt;code&gt;Products&lt;/code&gt; component is code splitted through lazy loading.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/html-webpack-preload-react-router/blob/main/examples/regular/src/pages/Products/products.route.js"&gt;products.route.js&lt;/a&gt;&lt;/em&gt;&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;//...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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="cm"&gt;/* webpackChunkName: 'Products' */&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Products&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="c1"&gt;//...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So Let's see in DevTools the network waterwall when we navigate to &lt;em&gt;&lt;a href="https://regular-81820.web.app/products"&gt;https://regular-81820.web.app/products&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AAL6RyDl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/or98l99f85rhandj1oux.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AAL6RyDl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/or98l99f85rhandj1oux.jpg" alt="Regular waterfall" width="800" height="109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We see that there are 4 network requests in a row and this we want to parallelize as much as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;After I read the great article by &lt;em&gt;Almog Gabay&lt;/em&gt; on Client-Side Rendering (CSR), particularly the &lt;em&gt;&lt;a href="https://github.com/theninthsky/client-side-rendering#preloading-async-pages"&gt;Preloading Async pages&lt;/a&gt;&lt;/em&gt; section, I tought to myself why not using react router plain objects for another purposes like preloading with help from Webpack? The idea was to have a single array of plain objects serving multiple purposes - routing and preloading. After experimenting with various edge cases, I successfully created a stable Webpack plugin. This plugin generates an HTML file that handles preloading of async chunk files derived from React Router’s plain objects and also preloads data from the database (this feature is currently limited to GET requests).&lt;/p&gt;

&lt;h3&gt;
  
  
  A new webpack plugin - &lt;em&gt;html-webpack-preload-react-router&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;The plugin &lt;a href="https://github.com/FogelAI/html-webpack-preload-react-router"&gt;&lt;code&gt;html-webpack-preload-react-router&lt;/code&gt;&lt;/a&gt; is easy to install and setup. It gets as an argument the path for the entry route of the website.&lt;br&gt;
In each object of react router plain objects we need to give the chunk name in a property called &lt;code&gt;chunkName&lt;/code&gt;. The value needs to be the same value of the magic comment &lt;code&gt;webpackChunkName&lt;/code&gt; of &lt;code&gt;import()&lt;/code&gt;.&lt;br&gt;
In addition, because we make a fetching from database, we can preload also the data by configure the property &lt;code&gt;data&lt;/code&gt;.&lt;br&gt;
It will be easier to understand throughout an example.&lt;/p&gt;
&lt;h3&gt;
  
  
  A preloading initial webpage loading example
&lt;/h3&gt;

&lt;p&gt;Let's use the same website example of &lt;em&gt;A regular initial webpage loading example&lt;/em&gt;.&lt;br&gt;
And do the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install the plugin.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install --save-dev html-webpack-preload-react-router&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure the &lt;code&gt;webpack.config.js&lt;/code&gt; file:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/html-webpack-preload-react-router/blob/main/examples/preloading/webpack.config.js"&gt;webpack.config.js&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight diff"&gt;&lt;code&gt;   const HtmlWebpackPlugin = require("html-webpack-plugin");
&lt;span class="gi"&gt;+  const ReactRouterPreloadChunksPlugin = require("html-webpack-preload-react-router");
+  const entryRouteFilename = path.resolve(`./src/pages/entryRoute.route.js`);
&lt;/span&gt;   module.exports = {
      //...
      plugins: [
         new MiniCssExtractPlugin(),
         //...
&lt;span class="gi"&gt;+        new ReactRouterPreloadChunksPlugin({
+           entryRoute: entryRouteFilename,
+        }),
&lt;/span&gt;      ]
      //...
   };
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Add &lt;code&gt;chunkName&lt;/code&gt; property for each object in the routing of react router plain objects.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/html-webpack-preload-react-router/blob/main/examples/preloading/src/pages/Products/products.route.js"&gt;products.route.js&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight diff"&gt;&lt;code&gt;   export const productsRoutes = [
     {
       path: "",
&lt;span class="gi"&gt;+      chunkName: "Products",
&lt;/span&gt;       id: "products",
       loader: () =&amp;gt; fetch("https://dummyjson.com/products").then((res) =&amp;gt; res.json()),
       element: &amp;lt;Products /&amp;gt;,
       children: [
         {
           path: ":productid",
&lt;span class="gi"&gt;+          chunkName: "Product",
&lt;/span&gt;           element: &amp;lt;Product /&amp;gt;,
         },
       ],
     },
   ];
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Add &lt;code&gt;data&lt;/code&gt; property for each object in the routing of react router plain objects that fetch a data.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/html-webpack-preload-react-router/blob/main/examples/preloading/src/pages/Products/products.route.js"&gt;products.route.js&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight diff"&gt;&lt;code&gt;   export const productsRoutes = [
     {
       path: "",
       chunkName: "Products",
       id: "products",
       loader: () =&amp;gt;
         fetch("https://dummyjson.com/products").then((res) =&amp;gt; res.json()),
       element: &amp;lt;Products /&amp;gt;,
       children: [
         {
           path: ":productid",
           chunkName: "Product",
           element: &amp;lt;Product /&amp;gt;,
         },
       ],
&lt;span class="gi"&gt;+      data: {
+        url: "https://dummyjson.com/products",
+        crossorigin: "anonymous",
+      },
&lt;/span&gt;     },
   ];
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So let's see in DevTools the network waterwall when navigating to &lt;em&gt;&lt;a href="https://preloading-ea687.web.app/products"&gt;https://preloading-ea687.web.app/products&lt;/a&gt;&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R2fdv-Q2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cnupak6mppws8ej0biel.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R2fdv-Q2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cnupak6mppws8ej0biel.jpg" alt="Preloading waterfall" width="800" height="98"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can see in the DevTools that there are 2 network group requests (instead 4 in a row), each group has network requests in parallel (first is &lt;code&gt;products&lt;/code&gt; and second are &lt;code&gt;main.9aa6dd.js&lt;/code&gt;, &lt;code&gt;Products.023320.js&lt;/code&gt; and &lt;code&gt;products&lt;/code&gt; in parallel). This is because the HTML is using preloading for async chunk files according to the URL path. It improves our website's performance!&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus - Navigation bar
&lt;/h2&gt;

&lt;p&gt;After we saw that we can use react router plain objects for 2 purposes of routing and preloading, I found a third purpose of using - navigation bar.&lt;br&gt;
In each object of the react router plain objects we need to give the link text in a property called &lt;code&gt;linkText&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It will be easier to understand throughout an example.&lt;/p&gt;
&lt;h3&gt;
  
  
  A navigation bar example
&lt;/h3&gt;

&lt;p&gt;Let's use the same website example of &lt;em&gt;A preloading initial webpage loading example&lt;/em&gt;.&lt;br&gt;
And do the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Change the react router plain objects &lt;code&gt;entryRoute&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/html-webpack-preload-react-router/blob/main/examples/navbar/src/pages/entryRoute.route.js"&gt;entryRoute.route.js&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight diff"&gt;&lt;code&gt;   export const entryRoute = [
     {
       path: "",
       element: &amp;lt;Layout /&amp;gt;,
&lt;span class="gi"&gt;+      id: "links",
+      loader: () =&amp;gt; entryRoute[0].children,
&lt;/span&gt;       //...
     },
   ];
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Change the &lt;code&gt;Layout&lt;/code&gt; component for reading link texts from the react router plain objects &lt;code&gt;entryRoute&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/html-webpack-preload-react-router/blob/main/examples/navbar/src/pages/Layout.js"&gt;Layout.js&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight diff"&gt;&lt;code&gt;   //...
   function Layout() {
&lt;span class="gi"&gt;+    let links = useRouteLoaderData("links");
&lt;/span&gt;     return (
       &amp;lt;nav&amp;gt;
         &amp;lt;ul&amp;gt;
&lt;span class="gd"&gt;-          &amp;lt;li&amp;gt;
-            &amp;lt;Link to="/"&amp;gt;Home&amp;lt;/Link&amp;gt;
-          &amp;lt;/li&amp;gt;
-          &amp;lt;li&amp;gt;
-            &amp;lt;Link to="/about"&amp;gt;About&amp;lt;/Link&amp;gt;
-          &amp;lt;/li&amp;gt;
-          &amp;lt;li&amp;gt;
-            &amp;lt;Link to="/products"&amp;gt;Products&amp;lt;/Link&amp;gt;
-          &amp;lt;/li&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+          {links.map((link) =&amp;gt; {
+            return (
+              &amp;lt;li&amp;gt;
+                &amp;lt;Link to={link.path?.replace("/*", "")}&amp;gt;{link.linkText}&amp;lt;/Link&amp;gt;
+              &amp;lt;/li&amp;gt;
+            );
+          })}
&lt;/span&gt;         &amp;lt;/ul&amp;gt;
       &amp;lt;/nav&amp;gt;
       //...
     );  
   }
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now we can see that the navigation bar works the same but use the data from react router plain objects. It is easier to maintain a single source of truth rather than 3 different sources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this article, we tried a new webpack plugin &lt;a href="https://github.com/FogelAI/html-webpack-preload-react-router"&gt;&lt;code&gt;html-webpack-preload-react-router&lt;/code&gt;&lt;/a&gt; , which collaborates seamlessly with React Router’s plain objects. It generates a production html file that preloads async chunk files and fetched data based on the current URL path. It parallelizes network requests, which makes our webpage load faster! Additionally, React Router’s plain objects can be utilized for the navigation bar.&lt;/p&gt;

&lt;p&gt;In short, now we can use the react router plain objects as a single source of truth for 3 purposes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Routing.&lt;/li&gt;
&lt;li&gt;Preloading async chunk files and fetched data from database (GET requests).&lt;/li&gt;
&lt;li&gt;Navigation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It makes our website's code easy to understand and maintained and improve the performance of initial loading webpages in our website.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed to read my article and hope you will try my new Webpack plugin &lt;a href="https://github.com/FogelAI/html-webpack-preload-react-router"&gt;&lt;code&gt;html-webpack-preload-react-router&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>webpack</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Potential issues with barrel files in Webpack</title>
      <dc:creator>Fogel</dc:creator>
      <pubDate>Tue, 18 Jul 2023 12:09:37 +0000</pubDate>
      <link>https://dev.to/fogel/potential-issues-with-barrel-files-in-webpack-4bf2</link>
      <guid>https://dev.to/fogel/potential-issues-with-barrel-files-in-webpack-4bf2</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Barrel files make the development more convenient, but how do they impact the bundle files generated by Webpack?&lt;/p&gt;

&lt;p&gt;In this article, we will discuss the question above. I will demonstrate how to configure Webpack to work with barrel files and dynamic import and how it's recommended to create modules. As incorrect config of Webpack can lead to different issues, some of them being performance issues as a result of unused code and others being visual issues.&lt;/p&gt;

&lt;p&gt;We will examine several solutions and go through a process together to find the optimal solution.&lt;/p&gt;

&lt;p&gt;This article assumes familiarity with optimization configuration of Webpack. Therefore, If you're new to this topic, I recommend reading my previous article on &lt;a href="https://dev.to/fogel/tree-shaking-in-webpack-5apj"&gt;&lt;em&gt;Tree shaking in Webpack&lt;/em&gt;&lt;/a&gt; before continuing reading this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;If you utilize barrel files with code splitting and employ regular CSS imports in your projects, I highly recommend using the &lt;a href="https://github.com/FogelAI/babel-plugin-transform-barrels" rel="noopener noreferrer"&gt;&lt;code&gt;babel-plugin-transform-barrels&lt;/code&gt;&lt;/a&gt; plugin instead of manually configuring &lt;code&gt;sideEffects&lt;/code&gt;. This plugin will help prevent unexpected visual issues on your webpage and effectively reduce the size of your bundle files.&lt;/p&gt;

&lt;p&gt;Furthermore, if code splitting is part of your development approach, I suggest creating modules with only one export each, whenever possible. This practice significantly decreases the size of your bundle files.&lt;/p&gt;

&lt;p&gt;Additionally, for code splitting scenarios, I highly recommend leveraging the &lt;code&gt;splitChunks&lt;/code&gt; configuration as explained in this article. This configuration allows for the elimination of duplicate code of common modules found in different chunks and will create a common chunk for common modules, resulting in optimized bundle files.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are barrel files (index.js)?
&lt;/h2&gt;

&lt;p&gt;Before we dive into the issues and because most of them were caused by barrel files, I want to explain what barrel files are and their appropriate use cases. I will focus on the advantages, but you can learn more about their advantages and disadvantages in the &lt;em&gt;Additional Resources&lt;/em&gt; section below.&lt;/p&gt;

&lt;p&gt;A barrel is a file that re-exports other modules' exports into a single file. In my opinion, it is better to use one level of barrel files in the folder structure. It's not recommended to create a barrel file for every folder.&lt;/p&gt;

&lt;p&gt;Developers use barrel files (index.js) for the following development purposes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;It makes the code more readable by shortening import path and decreasing the number of lines of code.&lt;/p&gt;
&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Without barrel files&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/Button/Button&lt;/span&gt;&lt;span class="dl"&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;Avatar&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/Avatar/Avatar&lt;/span&gt;&lt;span class="dl"&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;List&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/List/List&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;em&gt;With barrel files&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Avatar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;List&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When creating a third-party library and wanting to make specific functions public for consumers.&lt;/p&gt;

&lt;p&gt;The following quote from &lt;em&gt;yuchant&lt;/em&gt; on &lt;a href="https://github.com/vercel/next.js/issues/12557#issuecomment-1309240211" rel="noopener noreferrer"&gt;Github issue&lt;/a&gt; provides a good explanation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Barrel files are effectively an API. A specific interface that distinguishes private vs public code.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Changes in the module's internal structure don't affect the library's consumers.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Additional Resources:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://steven-lemon182.medium.com/are-typescript-barrel-files-an-anti-pattern-72a713004250" rel="noopener noreferrer"&gt;Are TypeScript Barrel Files an Anti-pattern?&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Barrel files in Webpack
&lt;/h2&gt;

&lt;p&gt;After we have seen the advantages of using barrel files and how they improve our developer experience, now we will see their usage and how they affect the bundle files.&lt;/p&gt;

&lt;p&gt;As we have already learned in the previous article about &lt;a href="https://dev.to/fogel/tree-shaking-in-webpack-5apj"&gt;&lt;em&gt;Tree shaking in Webpack&lt;/em&gt;&lt;/a&gt;, when there is no use of optimization, every module and its dependencies that exist in the code will be included in bundle files. So when we import a barrel file module, all the re-exported modules included inside it will be included in the bundle files, even modules that are not in use. This will increase the size of the bundle files and consequently harm performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimization properties
&lt;/h3&gt;

&lt;p&gt;Because barrel files can increase dramatically our bundle files size, we will use barrel files with &lt;code&gt;usedExports&lt;/code&gt; and &lt;code&gt;sideEffects&lt;/code&gt; optimization properties to eliminate unused code. Therefore in our example, modules in barrel files whose exports are not used will not be included in the final bundle files.&lt;/p&gt;

&lt;p&gt;First, let's look at the main files of the example:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/optimization-issues/examples/1-optimization/webpack.config.js" rel="noopener noreferrer"&gt;webpack.config.js&lt;/a&gt;&lt;/em&gt;&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MiniCssExtractPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mini-css-extract-plugin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;optimization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;usedExports&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="na"&gt;sideEffects&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="na"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;rules&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;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;css$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/node_modules/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;MiniCssExtractPlugin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;css-loader&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="c1"&gt;//...&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/optimization-issues/examples/1-optimization/src/App.js" rel="noopener noreferrer"&gt;App.js&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;GreenSection&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;./components/Sections/GreenSection/GreenSection&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;RedSection&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;./components/Sections/RedSection/RedSection&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;BlueStrong&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;./components/Strongs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BlueStrong&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Blue strong component (Direct Import)&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;BlueStrong&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;hr&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;GreenSection&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;hr&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RedSection&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/optimization-issues/examples/1-optimization/src/components/Sections/GreenSection/GreenSection.js" rel="noopener noreferrer"&gt;GreenSection.js&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GreenText&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;../../Texts&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;GreenButton&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;../../Buttons/GreenButton/GreenButton&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;getTenNumber&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;../../../tools/numberFunctions/numberFunctions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;GreenSection&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;tenNum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getTenNumber&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;GreenText&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Green text component (Indirect import - Barrel)&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;GreenText&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;GreenText&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Green ten number: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tenNum&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;GreenText&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;GreenButton&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Green button component (Direct import)&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;GreenButton&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;GreenSection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/optimization-issues/examples/1-optimization/src/components/Sections/RedSection/RedSection.js" rel="noopener noreferrer"&gt;RedSection.js&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RedText&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;../../Texts&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;RedButton&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;../../Buttons/RedButton/RedButton&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;getThousandNumber&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;../../../tools/numberFunctions/numberFunctions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;RedSection&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;thousandNum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getThousandNumber&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RedText&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Red text component (Indirect import - Barrel)&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;RedText&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RedText&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Red thousand number: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;thousandNum&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;RedText&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RedButton&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Red button component (Direct import)&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;RedButton&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;RedSection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before we bundle our example, let's briefly review the code above and especially the imported modules.&lt;/p&gt;

&lt;p&gt;Let's take a look at &lt;code&gt;App.js&lt;/code&gt;, we can see that three components are in use: &lt;code&gt;BlueStrong&lt;/code&gt;, &lt;code&gt;GreenSection&lt;/code&gt; and &lt;code&gt;RedSection&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GreenSection.js&lt;/code&gt; and &lt;code&gt;RedSection.js&lt;/code&gt; modules are performing module imports according to the appropriate color from subdirectories of &lt;code&gt;Buttons&lt;/code&gt; and &lt;code&gt;Texts&lt;/code&gt;, as well as importing a module &lt;code&gt;numberFunctions.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The only module that we will import indirectly from a barrel file will be from &lt;code&gt;Texts&lt;/code&gt;. The remaining modules will be imported directly as we have always done.&lt;/p&gt;

&lt;p&gt;Each appropriate module of color inside the subdirectories of &lt;code&gt;Buttons&lt;/code&gt;, &lt;code&gt;Strongs&lt;/code&gt; and &lt;code&gt;Texts&lt;/code&gt; has imported also a CSS file for each.&lt;/p&gt;

&lt;p&gt;After we did a short brief about how the code is implemented, we will describe in short what we expect to see in the rendered webpage. The first line should be in the blue color, 2-4 lines should be in green color and 5-7 lines should be in red color.&lt;/p&gt;

&lt;p&gt;We can see in the &lt;code&gt;webpack.config.js&lt;/code&gt; file, that there is a rule about CSS files that use the loader of &lt;code&gt;mini-css-extract-plugin&lt;/code&gt;, so each time Webpack parse the CSS files it process the loader and will inject the content of the CSS files into chunk file. In our example it will be &lt;code&gt;main.css&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;During the bundling process, we expect that it will produce two files (JS and CSS files).&lt;/p&gt;

&lt;p&gt;Now run &lt;code&gt;npx webpack&lt;/code&gt; in the terminal window.&lt;/p&gt;

&lt;p&gt;The build process created two files as expected: &lt;code&gt;main.js&lt;/code&gt; and &lt;code&gt;main.css&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's take a look at the browser and check the rendered page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Ftaksf482wm87oi5l0xfv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ftaksf482wm87oi5l0xfv.png" alt="1-optimization-rendered"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The page was rendered as expected.&lt;/p&gt;

&lt;p&gt;Now let's analyze the bundle files.&lt;/p&gt;

&lt;p&gt;It would be easier to understand if we organized all bundle files in a table according to the following columns:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Bundle file name.&lt;/li&gt;
&lt;li&gt;List of modules that combined to the bundle file. It's after &lt;code&gt;sideEffects&lt;/code&gt; optimization effect.&lt;/li&gt;
&lt;li&gt;The included functions (Actual) inside the bundle file. It's after &lt;code&gt;usedExports&lt;/code&gt; optimization effect.&lt;/li&gt;
&lt;li&gt;The functions that the bundle file should include (Expected) for the most optimized desired bundle file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Javascript bundle files&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Bundle file&lt;/th&gt;
&lt;th&gt;Bundled modules&lt;/th&gt;
&lt;th&gt;Actual functions&lt;/th&gt;
&lt;th&gt;Expected functions&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;main.js&lt;/td&gt;
&lt;td&gt;App.js, Button.js, GreenButton.js,&lt;br&gt;RedButton.js, GreenSection.js, RedSection.js,&lt;br&gt;BlueStrong.js, Strong.js, Texts/index.js,&lt;br&gt;GreenText.js, RedText.js, Text.js,&lt;br&gt;numberFunctions.js&lt;/td&gt;
&lt;td&gt;App, Button, GreenButton,&lt;br&gt;RedButton, GreenSection, RedSection,&lt;br&gt;BlueStrong, Strong, GreenText,&lt;br&gt;RedText, Text, getTenNumber,&lt;br&gt;getThousandNumber&lt;/td&gt;
&lt;td&gt;App, Button, GreenButton,&lt;br&gt;RedButton, GreenSection, RedSection,&lt;br&gt;BlueStrong, Strong, GreenText,&lt;br&gt;RedText, Text, getTenNumber,&lt;br&gt;getThousandNumber&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Let's take a look in the JS bundle file:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/optimization-issues/examples/1-optimization/dist/main.js" rel="noopener noreferrer"&gt;main.js&lt;/a&gt;&lt;/em&gt;&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;//...&lt;/span&gt;
&lt;span class="cm"&gt;/* unused harmony export getHundredNumber */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getTenNumber&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getHundredNumber&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getThousandNumber&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/optimization-issues/examples/1-optimization/dist/main.js" rel="noopener noreferrer"&gt;main.js&lt;/a&gt; file, we can see that Webpack bundled all the used functions, including the unused &lt;code&gt;getHundredNumber&lt;/code&gt; function, which is marked as an &lt;code&gt;unused harmony export&lt;/code&gt; by the &lt;code&gt;usedExports&lt;/code&gt; property. Note that the &lt;code&gt;RedText&lt;/code&gt; component is imported from &lt;code&gt;"Texts/index.js"&lt;/code&gt;, which is a barrel file, so all re-exported modules of the barrel file should be included, such as the &lt;code&gt;BlueText&lt;/code&gt; module. But because we use the &lt;code&gt;sideEffects&lt;/code&gt; property and the &lt;code&gt;BlueText&lt;/code&gt; module is not used and doesn't have side effects, it is excluded from the bundled file.&lt;/p&gt;

&lt;p&gt;Let's analyze the CSS bundle files:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CSS bundle files&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Bundle file&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Actual classes&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Expected classes&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;main.css&lt;/td&gt;
&lt;td&gt;Text, RedText, BlueText, GreenText,&lt;br&gt;Button, GreenButton, RedButton,&lt;br&gt;Strong, BlueStrong&lt;/td&gt;
&lt;td&gt;Text, RedText, GreenText, Button,&lt;br&gt;GreenButton, RedButton, Strong,&lt;br&gt;BlueStrong&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In the &lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/optimization-issues/examples/1-optimization/dist/main.css" rel="noopener noreferrer"&gt;main.css&lt;/a&gt; file, we can see an unused class selector for &lt;code&gt;.BlueText&lt;/code&gt; because we imported a &lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/optimization-issues/examples/1-optimization/src/components/Texts/index.js" rel="noopener noreferrer"&gt;barrel file module&lt;/a&gt; that includes the unused &lt;code&gt;BlueText&lt;/code&gt; module. While the &lt;code&gt;BlueText&lt;/code&gt; module was being evaluated, the &lt;code&gt;BlueText.css&lt;/code&gt; file was extracted by the &lt;code&gt;mini-css-extract-plugin&lt;/code&gt; plugin and added to the &lt;code&gt;main.css&lt;/code&gt; file. Afterwards, &lt;code&gt;BlueText&lt;/code&gt; was eliminated from &lt;code&gt;main.js&lt;/code&gt; due to the &lt;code&gt;sideEffects: true&lt;/code&gt; property. We will continue to monitor this unnecessary CSS selector. Note that unnecessary CSS selectors only come from unused modules that are re-exported in used barrel files. For example, there is no &lt;code&gt;.BlueButton&lt;/code&gt; CSS selector because &lt;code&gt;GreenButton&lt;/code&gt; and &lt;code&gt;RedButton&lt;/code&gt; are directly imported rather than through a barrel file.&lt;/p&gt;

&lt;p&gt;So we have an issue that we want to solve: we don't want the unnecessary &lt;code&gt;.BlueText&lt;/code&gt; CSS selector and we want our JS and CSS to be as small as possible.&lt;/p&gt;

&lt;h4&gt;
  
  
  We have two ways to solve it:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Change the imports of the &lt;code&gt;GreenText&lt;/code&gt; and &lt;code&gt;RedText&lt;/code&gt; to be direct imports instead of indirect imports (&lt;code&gt;index.js&lt;/code&gt; - barrel file), so this will prevent the &lt;code&gt;BlueText&lt;/code&gt; module and its CSS file from being loaded. This is similar to why the &lt;code&gt;.BlueButton&lt;/code&gt; CSS selector is not present in the CSS file because &lt;code&gt;GreenButton&lt;/code&gt; and &lt;code&gt;RedButton&lt;/code&gt; are directly imported.&lt;/li&gt;
&lt;li&gt;Since the &lt;code&gt;BlueText.js&lt;/code&gt; module has an unused export and our project only has side effects in CSS files, we can manually define which modules have side effects using the config option &lt;code&gt;sideEffects: ["*.css"]&lt;/code&gt; and then the remaining modules with unused exports like &lt;code&gt;BlueText.js&lt;/code&gt; will be flagged as having no side effects. This will prevent evaluation of the &lt;code&gt;BlueText.js&lt;/code&gt; module and extraction of its CSS file content through the loader.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Dynamic import (Lazy loading in React)
&lt;/h3&gt;

&lt;p&gt;After we saw that using barrel files can cause unused CSS files content to be included in CSS bundle file and we disscused the optional solutions, now I want to check the using barrel files inside a module that dynamically imported.&lt;/p&gt;

&lt;p&gt;Dynamic import of a module is usually used when we want to load the module in specific conditions (inside &lt;code&gt;if&lt;/code&gt; statement or event handler). If these conditions are not met, the code inside this module will not be evaluated, so we don't really need to download this module while the conditions are not met. So here Webpack comes to help. Webpack will create a bundle file for each module that is dynamically imported and for its dependencies and only download and evaluate this module when the conditions are met.&lt;/p&gt;

&lt;p&gt;For example, in React there is a package named &lt;code&gt;react-router-dom&lt;/code&gt; that allows render specific components for a specific URL path and render different components for a different URL path. In this case, it's recommended to use in lazy loading to make the components' modules downloaded from the server only when they are used. To make it happen, Webpack will create a new bundle file for each lazy loaded module with its dependencies.&lt;/p&gt;

&lt;p&gt;As described in &lt;a href="https://webpack.js.org/api/module-methods/#import-1" rel="noopener noreferrer"&gt;Webpack website&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Dynamically load modules. Calls to import() are treated as split points, meaning the requested module and its children are split out into a separate chunk.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dynamic import in Webpack is important for improving performance of initial loading because it allows us to only download and evaluate what is needed on each webpage. This means we can include in the bundle file only the necessary modules for the initial loading and as a result make smaller bundle file that then make our webpage load faster.&lt;/p&gt;

&lt;p&gt;For our example, and to keep it simple, we will change only the imports of &lt;code&gt;RedSection.js&lt;/code&gt; and &lt;code&gt;GreenSection.js&lt;/code&gt; to be dynamic imports without conditionally use them so both of them always will be downloaded in the initial loading of the webpage. We expect that Webpack will create three JS bundle files instead one.&lt;/p&gt;

&lt;p&gt;As we remember, &lt;code&gt;RedSection.js&lt;/code&gt; and &lt;code&gt;GreenSection.js&lt;/code&gt; modules have two direct common modules: &lt;code&gt;Texts/index.js&lt;/code&gt; and &lt;code&gt;numberFunctions.js&lt;/code&gt; that uses different functions inside them. How webpack will handle it? Are the common modules will be included only in both bundle files? Or maybe only in the main bundle file? Or maybe a fourth bundle file will be created for common modules? The answer we will see after the bundling process of the example.&lt;/p&gt;

&lt;p&gt;Let's create an example and see the files it produces.&lt;/p&gt;

&lt;p&gt;Clone the previous &lt;code&gt;1-optimization-sideEffects&lt;/code&gt; example into a new &lt;code&gt;2-lazy-loading&lt;/code&gt; example and make the following changes to the &lt;code&gt;App.js&lt;/code&gt; file:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/optimization-issues/examples/1-lazy-loading/App.js" rel="noopener noreferrer"&gt;App.js&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- import GreenSection from "./components/Sections/GreenSection/GreenSection";
- import RedSection from "./components/Sections/RedSection/RedSection";
&lt;/span&gt;  import { BlueStrong } from "./components/Strongs/BlueStrong/BlueStrong";
&lt;span class="gi"&gt;+ import { lazy, Suspense } from "react";
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gi"&gt;+ const GreenSection = lazy(() =&amp;gt; import(/* webpackChunkName: 'GreenSection' */ "./components/Sections/GreenSection/GreenSection"));
+ const RedSection = lazy(() =&amp;gt; import(/* webpackChunkName: 'RedSection' */ "./components/Sections/RedSection/RedSection"));
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;  function App() {
    return (
      &amp;lt;&amp;gt;
&lt;span class="gi"&gt;+       &amp;lt;Suspense fallback={&amp;lt;&amp;gt;&amp;lt;/&amp;gt;}&amp;gt;
&lt;/span&gt;            &amp;lt;BlueStrong&amp;gt;Blue strong component (Direct Import)&amp;lt;/BlueStrong&amp;gt;
            &amp;lt;hr /&amp;gt;
            &amp;lt;GreenSection /&amp;gt;
            &amp;lt;hr /&amp;gt;
            &amp;lt;RedSection /&amp;gt;
&lt;span class="gi"&gt;+       &amp;lt;/Suspense&amp;gt;
&lt;/span&gt;      &amp;lt;/&amp;gt;
    );
  }
&lt;span class="err"&gt;
&lt;/span&gt;  export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now run &lt;code&gt;npx webpack&lt;/code&gt; in the terminal window.&lt;/p&gt;

&lt;p&gt;This produces the following files:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;main.js&lt;/code&gt; and &lt;code&gt;main.css&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GreenSection.js&lt;/code&gt; and &lt;code&gt;GreenSection.css&lt;/code&gt; - &lt;em&gt;New files&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RedSection.js&lt;/code&gt; and &lt;code&gt;RedSection.css&lt;/code&gt; - &lt;em&gt;New files&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's take a look at the rendered page in the browser:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fhzo46cvv9ryjz6zobydo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fhzo46cvv9ryjz6zobydo.png" alt="2-lazy-loading-rendered"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We see that the &lt;em&gt;Green button component (direct import)&lt;/em&gt;, which is part of the &lt;code&gt;GreenSection&lt;/code&gt;, has turned black instead of being green. Why did this happen?&lt;/p&gt;

&lt;p&gt;First, let's take a look at the DevTools:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Flvgzybq44iumj8qml004.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Flvgzybq44iumj8qml004.png" alt="2-lazy-loading-greenbutton-css"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see that the &lt;code&gt;.Button&lt;/code&gt; CSS selector appears twice. The &lt;code&gt;GreenSection.css&lt;/code&gt; file loads both &lt;code&gt;.Button&lt;/code&gt; and &lt;code&gt;.GreenButton&lt;/code&gt;, but then &lt;code&gt;.Button&lt;/code&gt; is loaded again but from the &lt;code&gt;RedSection.css&lt;/code&gt; file. Loading the &lt;code&gt;.Button&lt;/code&gt; CSS selector only once from &lt;code&gt;GreenSection.css&lt;/code&gt; file will solve this problem. This happens because the &lt;code&gt;Button.js&lt;/code&gt; module loaded twice instead of once, causing it to override the green color with black. The order in which CSS properties (in our case &lt;code&gt;color&lt;/code&gt;) are applied is determined by their order of loading, where properties from class selectors loaded later will override those from earlier class selectors.&lt;/p&gt;

&lt;p&gt;Now let's analyze our bundle files.&lt;/p&gt;

&lt;p&gt;It would be easier to understand if we organized all bundle files in a table according to the following columns:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Bundle file name.&lt;/li&gt;
&lt;li&gt;List of modules that combined to the bundle file. It's after &lt;code&gt;sideEffects&lt;/code&gt; optimization effect.&lt;/li&gt;
&lt;li&gt;The included functions (Actual) inside the bundle file. It's after &lt;code&gt;usedExports&lt;/code&gt; optimization effect.&lt;/li&gt;
&lt;li&gt;The functions that the bundle file should include (Expected) for the most optimized desired bundle file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Javascript bundle files&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Bundle file&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Bundled modules&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Actual functions&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Expected functions&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;main.js&lt;/td&gt;
&lt;td&gt;App.js, BlueStrong.js, Strong.js&lt;/td&gt;
&lt;td&gt;BlueStrong, Strong&lt;/td&gt;
&lt;td&gt;BlueStrong, Strong&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GreenSection.js&lt;/td&gt;
&lt;td&gt;Button.js, GreenButton.js, GreenSection.js,&lt;br&gt;GreenText.js, RedText.js, Text.js,&lt;br&gt;Texts/index.js, numberFunctions.js&lt;/td&gt;
&lt;td&gt;Button, GreenButton, GreenSection,&lt;br&gt;GreenText, RedText, Text,&lt;br&gt;getTenNumber, getThousandNumber&lt;/td&gt;
&lt;td&gt;GreenText, GreenButton, GreenSection,&lt;br&gt;getTenNumber&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RedSection.js&lt;/td&gt;
&lt;td&gt;Button.js, RedButton.js, RedSection.js,&lt;br&gt;GreenText.js, RedText.js, Text.js,&lt;br&gt;Texts/index.js, numberFunctions.js&lt;/td&gt;
&lt;td&gt;Button, RedButton, RedSection, GreenText,&lt;br&gt;RedText, Text, getTenNumber,&lt;br&gt;getThousandNumber&lt;/td&gt;
&lt;td&gt;RedText, RedButton, RedSection,&lt;br&gt;getThousandNumber&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;*common.js&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Text, Button&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note: The &lt;code&gt;common.js&lt;/code&gt; is not produced by the build process. It's my suggestion for a bundle file for functions that are used by more than one JS bundle file.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explanation of JS bundle files&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First, we will check in what bundle files the common modules &lt;code&gt;Texts/index.js&lt;/code&gt; and &lt;code&gt;numberFunctions.js&lt;/code&gt; of &lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/optimization-issues/examples/2-lazy-loading/src/components/Sections/GreenSection/GreenSection.js" rel="noopener noreferrer"&gt;GreenSection.js&lt;/a&gt; and &lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/optimization-issues/examples/2-lazy-loading/src/components/Sections/RedSection/RedSection.js" rel="noopener noreferrer"&gt;RedSection.js&lt;/a&gt; source files are included. It can be seen in the table above that they are included inside &lt;code&gt;RedSection.js&lt;/code&gt; and &lt;code&gt;GreenSection.js&lt;/code&gt; bundle files. We expected that the &lt;code&gt;usedExports&lt;/code&gt; and &lt;code&gt;sideEffects&lt;/code&gt; optimization properties would eliminate the unused code separately in each &lt;code&gt;RedSection.js&lt;/code&gt; and &lt;code&gt;GreenSection.js&lt;/code&gt; bundle files. Unfortunately Webpack doesn't do that. We can see in both bundle files that the content of the imported modules are the same to the first example where only &lt;code&gt;BlueText.js&lt;/code&gt; module and &lt;code&gt;getHundredNumber&lt;/code&gt; function are eliminated. Unfortunately, the &lt;code&gt;usedExports&lt;/code&gt; and &lt;code&gt;sideEffects&lt;/code&gt; optimizations performed on the entire code are the same as in the first example without dynamic imports. Therefore, the &lt;code&gt;RedSection.js&lt;/code&gt; bundle file will include also the unused &lt;code&gt;GreenText.js&lt;/code&gt; module and &lt;code&gt;getTenNumber&lt;/code&gt; function and the &lt;code&gt;GreenSection.js&lt;/code&gt; bundle file will include also the unused &lt;code&gt;RedText.js&lt;/code&gt; module and &lt;code&gt;getThousandNumber&lt;/code&gt; function.
The &lt;code&gt;Texts/index.js&lt;/code&gt; and &lt;code&gt;numberFunctions.js&lt;/code&gt; modules have different solutions.
For &lt;code&gt;Texts/index.js&lt;/code&gt;, we can use the same solution I suggested in the first example.
For &lt;code&gt;numberFunctions.js&lt;/code&gt;, we can use the solution of separating the module to 3 different modules that each one will have one function and then import the function from his specific module.&lt;/li&gt;
&lt;li&gt;In addition, &lt;code&gt;Text.js&lt;/code&gt; and &lt;code&gt;Button.js&lt;/code&gt; are indirectly common modules imported from &lt;code&gt;Texts/index.js&lt;/code&gt;, &lt;code&gt;GreenButton.js&lt;/code&gt; and &lt;code&gt;RedButton.js&lt;/code&gt; modules. Therefore, &lt;code&gt;Text.js&lt;/code&gt; and &lt;code&gt;Button.js&lt;/code&gt; modules content appear in both &lt;code&gt;GreenSection.js&lt;/code&gt; and &lt;code&gt;RedSection.js&lt;/code&gt; bundle files that uses the same functions (&lt;code&gt;Text&lt;/code&gt; and &lt;code&gt;Button&lt;/code&gt; functions). This results a duplicate code, and our goal is to reduce their size.
To solve this issue, we should try creating a separate bundle file for common modules which have the same used functions of both sections. Since &lt;code&gt;Text.js&lt;/code&gt; and &lt;code&gt;Button.js&lt;/code&gt; are modules with one function each, we can conclude that both sections are using the same functions from these modules.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's analyze the CSS bundle files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CSS bundle files&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Bundle file&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Actual classes&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Expected classes&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;main.css&lt;/td&gt;
&lt;td&gt;BlueStrong, Strong&lt;/td&gt;
&lt;td&gt;BlueStrong, Strong&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GreenSection.css&lt;/td&gt;
&lt;td&gt;Text, RedText, BlueText, GreenText,&lt;br&gt;Button, GreenButton&lt;/td&gt;
&lt;td&gt;GreenText, GreenButton&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RedSection.css&lt;/td&gt;
&lt;td&gt;Text, RedText, BlueText, GreenText,&lt;br&gt;Button, RedButton&lt;/td&gt;
&lt;td&gt;RedText, RedButton&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;common.css&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Text, Button&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Explanation of CSS bundle files:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;main.css&lt;/code&gt; file has class selectors for &lt;code&gt;.Strong&lt;/code&gt; and &lt;code&gt;.BlueStrong&lt;/code&gt; because we use the &lt;code&gt;BlueStrong&lt;/code&gt; component in the &lt;code&gt;App.js&lt;/code&gt; file and it works as expected.&lt;/li&gt;
&lt;li&gt;In the CSS bundle files of &lt;code&gt;GreenSection.css&lt;/code&gt; and &lt;code&gt;RedSection.css&lt;/code&gt; modules, we can see that the &lt;code&gt;.BlueText&lt;/code&gt; CSS class selector appears even when the &lt;code&gt;BlueText&lt;/code&gt; component isn't used. We already talked about the reason why it happened in the first example and that there are two ways to solve it and we will try these options later.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;.GreenText&lt;/code&gt; appears in &lt;code&gt;RedSection.css&lt;/code&gt; and &lt;code&gt;.RedText&lt;/code&gt; appears in &lt;code&gt;GreenSection.css&lt;/code&gt;, even though both of them aren't useful and need to be eliminated. It happened because their modules (&lt;code&gt;GreenText.js&lt;/code&gt; and &lt;code&gt;RedText.js&lt;/code&gt;) are imported from the barrel file of &lt;code&gt;Texts/index.js&lt;/code&gt;. Later we will see if the solution for &lt;code&gt;.BlueText&lt;/code&gt; will help us solve this issue as well.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's summarize the issues for the example of lazy loading:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;Green button component (direct import)&lt;/em&gt; button has a black color instead green.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getTenNumber&lt;/code&gt; and &lt;code&gt;getThousandNumber&lt;/code&gt; functions exist in both &lt;code&gt;GreenSection.js&lt;/code&gt; and &lt;code&gt;RedSection.js&lt;/code&gt; bundle files instead, &lt;code&gt;getTenNumber&lt;/code&gt; should only be included in &lt;code&gt;GreenSection.js&lt;/code&gt; and &lt;code&gt;getThousandNumber&lt;/code&gt; should only be included in &lt;code&gt;RedSection.js&lt;/code&gt;. The same applies to the unused &lt;code&gt;RedText&lt;/code&gt; in the &lt;code&gt;GreenSection.js&lt;/code&gt; bundle file and the unused &lt;code&gt;GreenText&lt;/code&gt; in the &lt;code&gt;RedSection.js&lt;/code&gt; bundle file. Why did this happen? Because the optimizations of &lt;code&gt;usedExports&lt;/code&gt; and &lt;code&gt;sideEffects&lt;/code&gt; occurred to the entire code and not separately to each bundle file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Text.js&lt;/code&gt; and &lt;code&gt;Button.js&lt;/code&gt; modules appear in two bundle files of &lt;code&gt;GreenSection.js&lt;/code&gt; and &lt;code&gt;RedSection.js&lt;/code&gt; instead of in one common bundle file for both sections.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.BlueText&lt;/code&gt; exists in both bundle CSS files even though it is unused. &lt;code&gt;.RedText&lt;/code&gt; should be eliminated from &lt;code&gt;GreenSection.css&lt;/code&gt; bundle file and &lt;code&gt;.GreenText&lt;/code&gt; should be eliminated from &lt;code&gt;RedSection.css&lt;/code&gt; bundle file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Splitting bundle files can cause new issues. Some of these issues can affect performance, while others can cause unexpected visual issues that are more critical because they affect the user experience. So first, let's try to fix style issues and unnecessary duplicate code by using the optimization configuration of the &lt;code&gt;splitChunks&lt;/code&gt; property. After that, we will address unused functions and CSS selectors to decrease the size of bundle files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a separate bundle file for common modules
&lt;/h3&gt;

&lt;p&gt;In the previous chapter on dynamic import, we saw that each dynamic import in Webpack produces JS and CSS bundle files. In addition, commonly used modules exist in all bundle files that use these modules. As a result, there are CSS classes that are loaded twice and also duplicate Javascript code. This behavior causes four issues, one of which is an unexpected visual issue.&lt;/p&gt;

&lt;p&gt;To address this, we can use the &lt;code&gt;splitChunks&lt;/code&gt; property to create a bundle file of common modules.&lt;/p&gt;

&lt;p&gt;Let's clone the previous example &lt;code&gt;2-lazy-loading&lt;/code&gt; to &lt;code&gt;3-splitChunks&lt;/code&gt; and change the Webpack config file as follows:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/optimization-issues/examples/3-splitChunks/webpack.config.js" rel="noopener noreferrer"&gt;webpack.config.js&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;//...
&lt;span class="p"&gt;module.exports = {
&lt;/span&gt;  mode: "development",
  optimization: {
    usedExports: true,
    sideEffects: true,
&lt;span class="gi"&gt;+   splitChunks: {
+     cacheGroups: {
+       default: false,
+       defaultVendors: false,
+       src: {
+     test: /[\\/]src[\\/]/,
+     minSize: 0,
+     priority: 100,
+     name: (module, chunks) =&amp;gt; {
+       const allChunksNames = chunks.map(({ name }) =&amp;gt; name).join(".");
+       return `${allChunksNames}`;
+     },
+     chunks: "all",
+   },
+     },
+   },
&lt;/span&gt;  },
//...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's briefly explain what &lt;code&gt;splitChunks&lt;/code&gt; is doing with the configuration above. It traverses each module that includes the &lt;code&gt;src&lt;/code&gt; directory in its path and assigns a bundle file name to each traversed module through the &lt;code&gt;name&lt;/code&gt; property. The bundle file name of the traversed module will be the name of the chunk names (&lt;code&gt;webpackChunkName&lt;/code&gt; magic comment inside &lt;code&gt;import()&lt;/code&gt; statement) of dynamically imported modules that include this traversed module. For example the module &lt;code&gt;numberFunctions.js&lt;/code&gt; is included in &lt;code&gt;GreenSection.js&lt;/code&gt; and &lt;code&gt;RedSection.js&lt;/code&gt; source files that are dynamically imported, so the bundle file name that the module &lt;code&gt;numberFunctions.js&lt;/code&gt; should be inside is &lt;code&gt;GreenSection.RedSection.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I think my configuration above is better than the configuration described in the article &lt;a href="https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366" rel="noopener noreferrer"&gt;&lt;em&gt;webpack 4: Code Splitting, chunk graph and the splitChunks optimization&lt;/em&gt;&lt;/a&gt; because I control the name of the bundle files to be the name of the dynamically imported modules.&lt;/p&gt;

&lt;p&gt;Now run &lt;code&gt;npx webpack&lt;/code&gt; in the terminal window.&lt;/p&gt;

&lt;p&gt;It produces the following files:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;main.js&lt;/code&gt; and &lt;code&gt;main.css&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GreenSection.js&lt;/code&gt; and &lt;code&gt;GreenSection.css&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RedSection.js&lt;/code&gt; and &lt;code&gt;RedSection.css&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GreenSection.RedSection.js&lt;/code&gt; and &lt;code&gt;GreenSection.RedSection.css&lt;/code&gt; - &lt;em&gt;New files&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In comparison to the previous example &lt;code&gt;2-lazy-loading&lt;/code&gt;, it generated &lt;code&gt;GreenSection.RedSection.js&lt;/code&gt; and &lt;code&gt;GreenSection.RedSection.css&lt;/code&gt; bundle files in addition.&lt;/p&gt;

&lt;p&gt;Now let's take a look in the browser and check the rendered page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F8qp8fxhq7yryss3mq9or.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F8qp8fxhq7yryss3mq9or.png" alt="3-splitChunks-rendered"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We see that the &lt;em&gt;Green button component (direct import)&lt;/em&gt; is rendered with the green color as expected.&lt;/p&gt;

&lt;p&gt;Let's inspect the &lt;code&gt;button&lt;/code&gt; element:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fbeo456n8478079z0l0rj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fbeo456n8478079z0l0rj.png" alt="3-splitChunks-greenbutton-css"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see that the &lt;code&gt;.Button&lt;/code&gt; CSS selector now appears only once in the common bundle file &lt;code&gt;GreenSection.RedSection.css&lt;/code&gt;, so with the &lt;code&gt;splitChunks&lt;/code&gt; property, we have finally solved this visual issue.&lt;/p&gt;

&lt;p&gt;Let's analyze the bundle files:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Javascript bundle files&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Bundle file&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Bundled modules&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Actual functions&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Expected functions&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;main.js&lt;/td&gt;
&lt;td&gt;App.js, BlueStrong.js, Strong.js&lt;/td&gt;
&lt;td&gt;BlueStrong, Strong&lt;/td&gt;
&lt;td&gt;BlueStrong, Strong&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GreenSection.js&lt;/td&gt;
&lt;td&gt;GreenButton.js, GreenSection.js&lt;/td&gt;
&lt;td&gt;GreenButton, GreenSection&lt;/td&gt;
&lt;td&gt;GreenText, GreenButton, GreenSection,&lt;br&gt;getTenNumber&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RedSection.js&lt;/td&gt;
&lt;td&gt;RedButton.js, RedSection.js&lt;/td&gt;
&lt;td&gt;RedButton, RedSection&lt;/td&gt;
&lt;td&gt;RedText, RedButton, RedSection,&lt;br&gt;getThousandNumber&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GreenSection.RedSection.js&lt;/td&gt;
&lt;td&gt;Button.js, GreenText.js, RedText.js,&lt;br&gt;Text.js, Texts/index.js,&lt;br&gt;numberFuntions.js&lt;/td&gt;
&lt;td&gt;Button, GreenText, RedText,&lt;br&gt;Text, getTenNumber,&lt;br&gt;getThousandNumber&lt;/td&gt;
&lt;td&gt;Text, Button&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Explanation of JS bundle files&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If we take a look at the file &lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/optimization-issues/examples/3-splitChunks/dist/GreenSection.RedSection.js" rel="noopener noreferrer"&gt;GreenSection.RedSection.js&lt;/a&gt;, we can see that commonly used modules of the &lt;code&gt;GreenSection.js&lt;/code&gt; and &lt;code&gt;RedSection.js&lt;/code&gt; modules are included, such as the &lt;code&gt;Button.js&lt;/code&gt; and &lt;code&gt;Text.js&lt;/code&gt; modules, as expected. So we have solved this issue.
Note: The &lt;code&gt;Button.js&lt;/code&gt; and &lt;code&gt;Text.js&lt;/code&gt; modules are indirectly imported modules through &lt;code&gt;RedText.js&lt;/code&gt;, &lt;code&gt;GreenText.js&lt;/code&gt;, &lt;code&gt;GreenButton.js&lt;/code&gt; and &lt;code&gt;RedButton.js&lt;/code&gt; modules.&lt;/li&gt;
&lt;li&gt;The bundle file &lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/optimization-issues/examples/3-splitChunks/dist/GreenSection.RedSection.js" rel="noopener noreferrer"&gt;GreenSection.RedSection.js&lt;/a&gt; also includes the &lt;code&gt;GreenText&lt;/code&gt;, &lt;code&gt;RedText&lt;/code&gt;, &lt;code&gt;getTenNumber&lt;/code&gt;, and &lt;code&gt;getThousandNumber&lt;/code&gt; functions. These functions should not be in this common bundle file and they are part of the common bundle file because Webpack splits bundle files according to their used common module and not used common function. According to our case, the &lt;code&gt;GreenSection.js&lt;/code&gt; and &lt;code&gt;RedSection.js&lt;/code&gt; modules import the same modules &lt;code&gt;Texts/index.js&lt;/code&gt; and &lt;code&gt;numberFunctions.js&lt;/code&gt;, so these modules and their dependencies are included in the common bundle module &lt;code&gt;GreenSection.RedSection.js&lt;/code&gt;.
The desired result we wantis that &lt;code&gt;GreenText&lt;/code&gt; and &lt;code&gt;getTenNumber&lt;/code&gt; should be in the &lt;code&gt;GreenSection.js&lt;/code&gt; bundle file and &lt;code&gt;RedText&lt;/code&gt; and &lt;code&gt;getThousandNumber&lt;/code&gt; should be in the &lt;code&gt;RedSection.js&lt;/code&gt; bundle file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's analyze the CSS bundle files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CSS bundle files&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Bundle file&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Actual classes&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Expected classes&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;main.css&lt;/td&gt;
&lt;td&gt;BlueStrong, Strong&lt;/td&gt;
&lt;td&gt;BlueStrong, Strong&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GreenSection.css&lt;/td&gt;
&lt;td&gt;GreenButton&lt;/td&gt;
&lt;td&gt;GreenText, GreenButton&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RedSection.css&lt;/td&gt;
&lt;td&gt;RedButton&lt;/td&gt;
&lt;td&gt;RedText, RedButton&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GreenSection.RedSection.css&lt;/td&gt;
&lt;td&gt;Text, RedText, BlueText, GreenText, Button&lt;/td&gt;
&lt;td&gt;Text, Button&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Explanation of CSS bundle files:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;.BlueText&lt;/code&gt; is included in &lt;code&gt;GreenSection.RedSection.css&lt;/code&gt; even though it is unused. This happened because we import a barrel file of &lt;code&gt;Texts/index.js&lt;/code&gt; that first loads the re-exported modules and while evaluating these modules it extracted CSS contents by the CSS loader and then eliminates unused code. It happened for the same reason as in the first example.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.RedText&lt;/code&gt; and &lt;code&gt;.GreenText&lt;/code&gt; are included in &lt;code&gt;GreenSection.RedSection.css&lt;/code&gt;, when they should included in &lt;code&gt;RedSection.css&lt;/code&gt; and &lt;code&gt;GreenSection.css&lt;/code&gt;, respectively. This happened for the same reason as we mentioned about their JS files, that they are indirectly imported through a barrel file. Webpack creates a common bundle file because the common module of &lt;code&gt;Text/index.js&lt;/code&gt; is imported in both &lt;code&gt;GreenSection.js&lt;/code&gt; and in &lt;code&gt;RedSection.js&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's summarize the current opened issues:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Summary of Javascript issues:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;GreenText&lt;/code&gt; and &lt;code&gt;RedText&lt;/code&gt; modules are included in the common bundle file &lt;code&gt;GreenSection.RedSection.js&lt;/code&gt; instead in their specific bundle files &lt;code&gt;GreenSection.js&lt;/code&gt; and &lt;code&gt;RedSection.js&lt;/code&gt;, respectively. Because they are imported indirectly through a barrel file &lt;code&gt;Texts/index.js&lt;/code&gt; that it is the common module. If we will want to render one section file instead of the two sections, then we will download unused code. For example, if we load a page that renders only &lt;code&gt;GreenSection&lt;/code&gt; component but conditionally renders &lt;code&gt;RedSection&lt;/code&gt; component, then the downloaded bundle will include &lt;code&gt;RedText.js&lt;/code&gt; even though we don't need it now.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GreenSection.RedSection.js&lt;/code&gt; bundle file include &lt;code&gt;getTenNumber&lt;/code&gt; and &lt;code&gt;getThousandNumber&lt;/code&gt; functions instead &lt;code&gt;GreenSection.js&lt;/code&gt; bundle file include only &lt;code&gt;getTenNumber&lt;/code&gt; and &lt;code&gt;RedSection.js&lt;/code&gt; bundle file include only &lt;code&gt;getThousandNumber&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Summary of CSS issues:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;.BlueText&lt;/code&gt; exist in common bundle CSS &lt;code&gt;GreenSection.RedSection.css&lt;/code&gt; even it is unused.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.RedText&lt;/code&gt; and &lt;code&gt;.GreenText&lt;/code&gt; shouldn't be in &lt;code&gt;GreenSection.RedSection.css&lt;/code&gt; bundle file. They should be in &lt;code&gt;RedSection.css&lt;/code&gt; and &lt;code&gt;GreenSection.css&lt;/code&gt;, respectively. The behavior of &lt;code&gt;.RedText&lt;/code&gt; and &lt;code&gt;.GreenText&lt;/code&gt; happened because the using of barrel file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Our conclusions for now:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using direct import instead of indirect import (barrel files) solves most of the issues.&lt;/li&gt;
&lt;li&gt;Using one function per module instead of multiple functions per module solves the issues of the &lt;code&gt;numberFunctions&lt;/code&gt; module.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Manual configuration of &lt;code&gt;sideEffects&lt;/code&gt; solution
&lt;/h3&gt;

&lt;p&gt;One of our conclusions in the previous example was that the use of barrel files can cause issues when dynamic import is used. It seems that &lt;code&gt;usedExports&lt;/code&gt; marks unused exports for the whole code as a one bundle file only and not for each separate bundle file. When we made direct imports with the &lt;code&gt;GreenButton&lt;/code&gt; and &lt;code&gt;RedButton&lt;/code&gt; components, it worked properly.&lt;/p&gt;

&lt;p&gt;In my &lt;a href="https://dev.to/fogel/tree-shaking-in-webpack-5apj"&gt;&lt;em&gt;Tree shaking in Webpack&lt;/em&gt;&lt;/a&gt; article, we learned that we can manually configure which modules in our project have side effects and which don't.&lt;/p&gt;

&lt;p&gt;Also from that article, we know for sure that CSS files are considered to have side effects, so we need to flag them with side effects. Barrel files in our case only have re-exported functions, so we can say that we don't use direct imports from barrel files and they also don't have side effects, so we can flag barrel files without side effects.&lt;/p&gt;

&lt;p&gt;Webpack's team talked about the purpose of the manual &lt;code&gt;sideEffects&lt;/code&gt; property in their &lt;a href="https://youtu.be/bm7RlNEcQM0?t=1761" rel="noopener noreferrer"&gt;conference&lt;/a&gt; and explained that it comes to solve the issue of big bundle files when using of barrel files.&lt;/p&gt;

&lt;p&gt;So let's try to solve our issues from the previous example with a manual configuration of &lt;code&gt;sideEffects&lt;/code&gt; in &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's clone the previous example &lt;code&gt;3-splitChunks&lt;/code&gt; to &lt;code&gt;4-package-sideEffects&lt;/code&gt; and change the package config file as follows:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/optimization-issues/examples/4-package-sideEffects/package.json" rel="noopener noreferrer"&gt;package.json&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;{
  "name": "example-module",
&lt;span class="gi"&gt;+ "sideEffects": ["*.css"],
&lt;/span&gt;}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now run &lt;code&gt;npx webpack&lt;/code&gt; in the terminal window.&lt;/p&gt;

&lt;p&gt;Let's take a look in the browser and check the rendered page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fmwb3ze1mdngha08w8l6e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fmwb3ze1mdngha08w8l6e.png" alt="4-package-sideEffects-rendered"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We see that the &lt;em&gt;Blue strong component (Direct Import)&lt;/em&gt; text is black when it should be blue. This is a visual issue. Why did this strange behavior occur?&lt;/p&gt;

&lt;p&gt;First, let's look at the dev tools:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fnf2xyt64g4o3s1jr3gv3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fnf2xyt64g4o3s1jr3gv3.png" alt="4-package-sideEffects-strong-css"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see that &lt;code&gt;.Strong&lt;/code&gt; overrides &lt;code&gt;.BlueStrong&lt;/code&gt; because &lt;code&gt;.Strong&lt;/code&gt; is in a higher position. Why did this change? In the previous examples, &lt;code&gt;.BlueStrong&lt;/code&gt; overrode &lt;code&gt;.Strong&lt;/code&gt;. This happened because of the &lt;code&gt;sideEffects&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;So I started to research this issue.&lt;/p&gt;

&lt;p&gt;I found an &lt;a href="https://github.com/webpack/webpack/issues/10413" rel="noopener noreferrer"&gt;issue&lt;/a&gt; where &lt;em&gt;Hypnosphi&lt;/em&gt; complained that there were differences between development and production when he configured &lt;code&gt;sideEffects: false&lt;/code&gt;, so he noticed that the order of CSS was not the order of the imports but the usage order. In another &lt;a href="https://github.com/webpack/webpack/issues/7094#issuecomment-383466978" rel="noopener noreferrer"&gt;issue&lt;/a&gt;, there is an answer from &lt;em&gt;sokra&lt;/em&gt; (a Webpack team member) who wrote:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Technically using sideEffects you say order doesn't matter&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Another answer from &lt;a href="https://github.com/webpack/webpack/issues/7094#issuecomment-945663737" rel="noopener noreferrer"&gt;sokra&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If the order of some modules matter they are not side-effect-free.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So let's go back to our case.&lt;/p&gt;

&lt;p&gt;We evaluate the &lt;code&gt;BlueStrong.js&lt;/code&gt; module that first imports the &lt;code&gt;Strong&lt;/code&gt; component and then &lt;code&gt;BlueStrong.css&lt;/code&gt;. But because we flagged modules with sideEffects manually, Webpack will first evaluate import module statements flagged with side effects and then evaluate used modules flagged without side effects in the order of their use. So the import of &lt;code&gt;BlueStrong.css&lt;/code&gt; will be evaluated first and then we use the &lt;code&gt;Strong.js&lt;/code&gt; that will be evaluated with &lt;code&gt;Strong.css&lt;/code&gt; inside of it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's analyze bundle files:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Javascript bundle files&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Bundle file&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Bundled modules&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Actual functions&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Expected functions&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;main.js&lt;/td&gt;
&lt;td&gt;App.js, BlueStrong.js, Strong.js&lt;/td&gt;
&lt;td&gt;BlueStrong, Strong&lt;/td&gt;
&lt;td&gt;BlueStrong, Strong&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GreenSection.js&lt;/td&gt;
&lt;td&gt;GreenButton.js, GreenSection.js,&lt;br&gt;GreenText.js&lt;/td&gt;
&lt;td&gt;GreenButton, GreenSection, GreenText&lt;/td&gt;
&lt;td&gt;GreenText, GreenButton, GreenSection,&lt;br&gt;getTenNumber&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RedSection.js&lt;/td&gt;
&lt;td&gt;RedButton.js, RedSection.js,&lt;br&gt;RedText.js&lt;/td&gt;
&lt;td&gt;RedButton, RedSection, RedText&lt;/td&gt;
&lt;td&gt;RedText, RedButton, RedSection,&lt;br&gt;getThousandNumber&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GreenSection.RedSection.js&lt;/td&gt;
&lt;td&gt;Button.js, Text.js,&lt;br&gt;numberFunctions.js&lt;/td&gt;
&lt;td&gt;Button, Text, getTenNumber,&lt;br&gt;getThousandNumber&lt;/td&gt;
&lt;td&gt;Text, Button&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;CSS bundle files&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Bundle file&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Actual classes&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Expected classes&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;main.css&lt;/td&gt;
&lt;td&gt;BlueStrong, Strong&lt;/td&gt;
&lt;td&gt;BlueStrong, Strong&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GreenSection.css&lt;/td&gt;
&lt;td&gt;GreenText, GreenButton&lt;/td&gt;
&lt;td&gt;GreenText, GreenButton&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RedSection.css&lt;/td&gt;
&lt;td&gt;RedText, RedButton&lt;/td&gt;
&lt;td&gt;RedText, RedButton&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GreenSection.RedSection.css&lt;/td&gt;
&lt;td&gt;Text, Button&lt;/td&gt;
&lt;td&gt;Text, Button&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In the CSS table above, we can see for the first time that CSS files have the expected class selectors. So for now, we know for sure that the size of the CSS files is as small as possible.&lt;/p&gt;

&lt;p&gt;Let's check if our previous example issues are solved:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;GreenText&lt;/code&gt; and &lt;code&gt;RedText&lt;/code&gt; are in their correct bundle files &lt;code&gt;GreenSection.js&lt;/code&gt; and &lt;code&gt;RedSection.js&lt;/code&gt;, respectively. &lt;code&gt;sideEffects&lt;/code&gt; solved the issue of imported modules from barrel files.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.BlueText&lt;/code&gt;, which previously existed in the common bundle CSS file &lt;code&gt;GreenSection.RedSection.css&lt;/code&gt; even though it was unused, is now eliminated. &lt;code&gt;.RedText&lt;/code&gt; and &lt;code&gt;.GreenText&lt;/code&gt; are in &lt;code&gt;RedSection.css&lt;/code&gt; and &lt;code&gt;GreenSection.css&lt;/code&gt;, respectively. &lt;code&gt;sideEffects&lt;/code&gt; solved the issue caused by the barrel file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getTenNumber&lt;/code&gt; and &lt;code&gt;getThousandNumber&lt;/code&gt; still exist in the &lt;code&gt;GreenSection.RedSection.js&lt;/code&gt; bundle file instead of &lt;code&gt;getTenNumber&lt;/code&gt; being only inside &lt;code&gt;GreenSection.js&lt;/code&gt; and &lt;code&gt;getThousandNumber&lt;/code&gt; being only inside &lt;code&gt;RedSection.js&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's summarize the current open issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;getTenNumber&lt;/code&gt; and &lt;code&gt;getThousandNumber&lt;/code&gt; still exist in the &lt;code&gt;GreenSection.RedSection.js&lt;/code&gt; bundle file, instead of having only &lt;code&gt;getTenNumber&lt;/code&gt; in &lt;code&gt;GreenSection.js&lt;/code&gt; and only &lt;code&gt;getThousandNumber&lt;/code&gt; in &lt;code&gt;RedSection.js&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.Strong&lt;/code&gt; overrides &lt;code&gt;.BlueStrong&lt;/code&gt; when it should be the opposite. This is a result of the &lt;code&gt;sideEffects: ["*.css"]&lt;/code&gt; configuration that changing the order of imports based on usage of a module rather than by the order of import statements (except for CSS imports). This causes a visual issue.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I have considered several solutions for the second issue:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Convert CSS files to &lt;a href="https://github.com/css-modules/css-modules" rel="noopener noreferrer"&gt;CSS Modules&lt;/a&gt; and change the &lt;code&gt;sideEffects: ["*.css"]&lt;/code&gt; configuration to &lt;code&gt;sideEffects: false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Create a plugin that moves all CSS import statements to the end of the module if &lt;code&gt;sideEffects: ["*.css"]&lt;/code&gt; is defined in &lt;code&gt;package.json&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;Change import statements from indirect imports through a barrel file to direct imports.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All of these solutions should work, but the first two solutions with configuration of &lt;code&gt;sideEffects&lt;/code&gt; in &lt;code&gt;package.json&lt;/code&gt; will change the import order to be determined by usage. The third solution, on the other hand, follows the order of import statements as ES Modules behavior. Since I want to follow my principle of having the bundle file resemble ES Modules behavior, the third solution is the better choice.&lt;/p&gt;

&lt;p&gt;We still want to use barrel files because they make our code more readable and improve our developer experience. In the next chapter, we will try to develop an automatic transformation for our code that changes indirect imports through a barrel file to direct imports.&lt;/p&gt;

&lt;h3&gt;
  
  
  babel-plugin-transform-barrels
&lt;/h3&gt;

&lt;p&gt;I know that Babel can transform code during the build process of Webpack. So I found some plugins (&lt;a href="https://github.com/mui/material-ui/blob/871c2f35009977d29f9ce735075eaefe0f5fc824/docs/src/pages/guides/minimizing-bundle-size.md#option-2" rel="noopener noreferrer"&gt;#1&lt;/a&gt;, &lt;a href="https://github.com/LiamMartens/babel-plugin-no-index-imports" rel="noopener noreferrer"&gt;#2&lt;/a&gt;, &lt;a href="https://github.com/SectorLabs/babel-plugin-transform-named-imports" rel="noopener noreferrer"&gt;#3&lt;/a&gt;) that will transform the import statements from indirect import (through barrel file) to direct import, but all of them require specific configuration for each package. So I decided to develop a Babel plugin that will transform code with imports from barrel files into code with direct imports without needing configuration.&lt;/p&gt;

&lt;p&gt;Kent C. Dodds talked about the problem of unnecessary CSS class selectors in this &lt;a href="https://www.youtube.com/watch?v=Q_F-c0LEp4I" rel="noopener noreferrer"&gt;video&lt;/a&gt; and about his &lt;a href="https://www.youtube.com/watch?v=EkhD1OMHkYI" rel="noopener noreferrer"&gt;solution&lt;/a&gt;. It is based on a plugin that requires specific configuration, something that I don't want.&lt;/p&gt;

&lt;p&gt;During the bundling process, my babel plugin transforms the line of code as follows:&lt;/p&gt;

&lt;p&gt;From an indirect import (barrel file):&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RedText&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;../../Texts&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;To a direct import:&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RedText&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../Texts/RedText/RedText&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;My babel plugin prevents the inclusion of unused reexported modules from barrel files in the bundle file. This leads to a reduction in bundle size, thereby improving overall performance.&lt;/p&gt;

&lt;p&gt;Now, let's install the plugin:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install --save-dev babel-plugin-transform-barrels&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now we need to add the plugin to the webpack config file which has a rule with a loader of &lt;code&gt;babel-loader&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/optimization-issues/examples/5-babel-plugin/webpack.config.js" rel="noopener noreferrer"&gt;webpack.config.js&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;      {
        test: /\.(js|mjs|jsx|ts|tsx)$/,
        exclude: /node_modules/,
        loader: require.resolve("babel-loader"),
        options: {
          presets: [["@babel/preset-react"]],
&lt;span class="gi"&gt;+         plugins: [["transform-barrels", { webpackConfigFilename: __filename, ...(typeof module.exports === "function" &amp;amp;&amp;amp; { args: arguments })}]],
&lt;/span&gt;        },
      },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now run &lt;code&gt;npx webpack&lt;/code&gt; in the terminal window.&lt;/p&gt;

&lt;p&gt;Let's take a look in the browser and check the rendered page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fnzgvgo5ncmwz45kmf371.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fnzgvgo5ncmwz45kmf371.png" alt="5-babel-plugin-rendered"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We see that the "Blue strong component (Direct Import)" has the blue color as expected.&lt;/p&gt;

&lt;p&gt;Let's look at the dev tools:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fzeh80xkyzuins4beslfh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fzeh80xkyzuins4beslfh.png" alt="5-babel-plugin-strong-css"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So even though the CSS table in this example is the same as in the previous example, the rendered page is different because now class selectors are loaded in the order of their import statements, as expected, rather than in the order of their usage.&lt;/p&gt;

&lt;p&gt;We can see that &lt;code&gt;.BlueStrong&lt;/code&gt; overrides &lt;code&gt;.Strong&lt;/code&gt;, so this issue is solved.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's analyze bundle files:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Javascript bundle files&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Bundle file&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Bundled modules&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Actual functions&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Expected functions&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;main.js&lt;/td&gt;
&lt;td&gt;App.js, BlueStrong.js, Strong.js&lt;/td&gt;
&lt;td&gt;BlueStrong, Strong&lt;/td&gt;
&lt;td&gt;BlueStrong, Strong&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GreenSection.js&lt;/td&gt;
&lt;td&gt;GreenButton.js, GreenSection.js,&lt;br&gt;GreenText.js&lt;/td&gt;
&lt;td&gt;GreenButton, GreenSection, GreenText&lt;/td&gt;
&lt;td&gt;GreenText, GreenButton, GreenSection,&lt;br&gt;getTenNumber&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RedSection.js&lt;/td&gt;
&lt;td&gt;RedButton.js, RedSection.js,&lt;br&gt;RedText.js&lt;/td&gt;
&lt;td&gt;RedButton, RedSection, RedText&lt;/td&gt;
&lt;td&gt;RedText, RedButton, RedSection,&lt;br&gt;getThousandNumber&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GreenSection.RedSection.js&lt;/td&gt;
&lt;td&gt;Button.js, Text.js,&lt;br&gt;numberFunctions.js&lt;/td&gt;
&lt;td&gt;Button, Text, getTenNumber,&lt;br&gt;getThousandNumber&lt;/td&gt;
&lt;td&gt;Text, Button&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;CSS bundle files&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Bundle file&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Actual classes&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Expected classes&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;main.css&lt;/td&gt;
&lt;td&gt;BlueStrong, Strong&lt;/td&gt;
&lt;td&gt;BlueStrong, Strong&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GreenSection.css&lt;/td&gt;
&lt;td&gt;GreenText, GreenButton&lt;/td&gt;
&lt;td&gt;GreenText, GreenButton&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RedSection.css&lt;/td&gt;
&lt;td&gt;RedText, RedButton&lt;/td&gt;
&lt;td&gt;RedText, RedButton&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GreenSection.RedSection.css&lt;/td&gt;
&lt;td&gt;Text, Button&lt;/td&gt;
&lt;td&gt;Text, Button&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As we can see in the Javascript and CSS tables above, there is no difference compared to the previous example &lt;code&gt;4-package-sideEffects&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's summarize the current open issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;getTenNumber&lt;/code&gt; and &lt;code&gt;getThousandNumber&lt;/code&gt; still exist in the &lt;code&gt;GreenSection.RedSection.js&lt;/code&gt; bundle file instead of &lt;code&gt;getTenNumber&lt;/code&gt; being only included in &lt;code&gt;GreenSection.js&lt;/code&gt; and &lt;code&gt;getThousandNumber&lt;/code&gt; being only included in &lt;code&gt;RedSection.js&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;code&gt;numberFunctions.js&lt;/code&gt; module has 3 function exports. If we split the module into 3 separate modules, each with one function export, it should resolve the issue.&lt;/p&gt;

&lt;h3&gt;
  
  
  Function per module
&lt;/h3&gt;

&lt;p&gt;Before I try my optional solution, I searched for open issues on Webpack's Github repository and found the same &lt;a href="https://github.com/webpack/webpack/issues/16672" rel="noopener noreferrer"&gt;issue&lt;/a&gt; we faced, but there is no solution provided by the Webpack team.&lt;/p&gt;

&lt;p&gt;I checked a popular package with tree shaking support called &lt;a href="https://github.com/lodash/lodash" rel="noopener noreferrer"&gt;Lodash&lt;/a&gt;. Lodash has a separate module per function. This allows the package to fully support tree shaking.&lt;/p&gt;

&lt;p&gt;We will try this approach and see if it resolves our issue from the previous example.&lt;/p&gt;

&lt;p&gt;Let's clone the previous example &lt;code&gt;5-babel-plugin&lt;/code&gt; to &lt;code&gt;6-function-per-module&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now let's split the exports &lt;code&gt;getTenNumber&lt;/code&gt;, &lt;code&gt;getHundredNumber&lt;/code&gt;, and &lt;code&gt;getThousandNumber&lt;/code&gt; from &lt;code&gt;src\tools\numberFunctions\numberFunctions.js&lt;/code&gt; into 3 modules: &lt;code&gt;getTenNumber.js&lt;/code&gt;, &lt;code&gt;getHundredNumber.js&lt;/code&gt;, and &lt;code&gt;getThousandNumber.js&lt;/code&gt;, respectively. And create a barrel file for the &lt;code&gt;src\tools\numberFunctions&lt;/code&gt; directory. Now change the import statements of these functions in the &lt;code&gt;GreenSection.js&lt;/code&gt; and &lt;code&gt;RedSection.js&lt;/code&gt; modules.&lt;/p&gt;

&lt;p&gt;Now run &lt;code&gt;npx webpack&lt;/code&gt; in the terminal window.&lt;/p&gt;

&lt;p&gt;Let's take a look in the browser and check the rendered page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fh4wwg6a07rkhmqxrgoni.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fh4wwg6a07rkhmqxrgoni.png" alt="6-function-per-module-rendered"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everything looks great in our rendered page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's analyze bundle files:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Javascript bundle files&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Bundle file&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Bundled modules&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Actual functions&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Expected functions&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;main.js&lt;/td&gt;
&lt;td&gt;App.js, BlueStrong.js, Strong.js&lt;/td&gt;
&lt;td&gt;BlueStrong, Strong&lt;/td&gt;
&lt;td&gt;BlueStrong, Strong&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GreenSection.js&lt;/td&gt;
&lt;td&gt;GreenButton.js, GreenSection.js,&lt;br&gt;GreenText.js, getTenNumber.js&lt;/td&gt;
&lt;td&gt;GreenText, GreenButton, GreenSection,&lt;br&gt;getTenNumber&lt;/td&gt;
&lt;td&gt;GreenText, GreenButton, GreenSection,&lt;br&gt;getTenNumber&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RedSection.js&lt;/td&gt;
&lt;td&gt;RedButton.js, RedSection.js,&lt;br&gt;RedText.js, getThousandNumber.js&lt;/td&gt;
&lt;td&gt;RedText, RedButton, RedSection,&lt;br&gt;getThousandNumber&lt;/td&gt;
&lt;td&gt;RedText, RedButton, RedSection,&lt;br&gt;getThousandNumber&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GreenSection.RedSection.js&lt;/td&gt;
&lt;td&gt;Button.js, Text.js&lt;/td&gt;
&lt;td&gt;Text, Button&lt;/td&gt;
&lt;td&gt;Text, Button&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;CSS bundle files&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Bundle file&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Actual classes&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Expected classes&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;main.css&lt;/td&gt;
&lt;td&gt;BlueStrong, Strong&lt;/td&gt;
&lt;td&gt;BlueStrong, Strong&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GreenSection.css&lt;/td&gt;
&lt;td&gt;GreenText, GreenButton&lt;/td&gt;
&lt;td&gt;GreenText, GreenButton&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RedSection.css&lt;/td&gt;
&lt;td&gt;RedText, RedButton&lt;/td&gt;
&lt;td&gt;RedText, RedButton&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GreenSection.RedSection.css&lt;/td&gt;
&lt;td&gt;Text, Button&lt;/td&gt;
&lt;td&gt;Text, Button&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Now &lt;code&gt;getTenNumber&lt;/code&gt; and &lt;code&gt;getThousandNumber&lt;/code&gt; no longer included in the &lt;code&gt;GreenSection.RedSection.js&lt;/code&gt; bundle file. Instead, &lt;code&gt;getTenNumber&lt;/code&gt; is included only in &lt;code&gt;GreenSection.js&lt;/code&gt; and &lt;code&gt;getThousandNumber&lt;/code&gt; is included only in &lt;code&gt;RedSection.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We have successfully overcome all of our performance and visual issues. Now our project is optimized. We managed to minimize the size of the project by reducing the amount of CSS and Javascript code. The project only loads what it needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this article, we encountered inefficient bundle files and visual issues in the browser when using barrel files with dynamic import that caused our bundle files to split into different chunks with unused Javascript code. We conducted a step-by-step examination to determine the best way to solve these issues.&lt;/p&gt;

&lt;p&gt;We found 2 particular reasons for the issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using barrel files in our code.&lt;/li&gt;
&lt;li&gt;Using a module with more than one export.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The issues occurred because &lt;code&gt;usedExports&lt;/code&gt; and &lt;code&gt;sideEffects&lt;/code&gt; optimizations performed at the entirely code. So for example, in the &lt;code&gt;numberFunctions.js&lt;/code&gt; module, &lt;code&gt;usedExports&lt;/code&gt; first checks if its exports are used and sees that the &lt;code&gt;getTenNumber&lt;/code&gt; function export is used by &lt;code&gt;GreenSection&lt;/code&gt; and the &lt;code&gt;getThousandNumber&lt;/code&gt; function export is used by &lt;code&gt;RedSection&lt;/code&gt; and the &lt;code&gt;getHundredNumber&lt;/code&gt; function is not used anywhere so it marks only &lt;code&gt;getHundredNumber&lt;/code&gt; as an &lt;code&gt;unused harmony export&lt;/code&gt;. Only after this evaluation of code, Webpack inject the code of &lt;code&gt;numberFunctions.js&lt;/code&gt; module with the optimizations that were made into &lt;code&gt;GreenSection.js&lt;/code&gt; and &lt;code&gt;RedSection.js&lt;/code&gt; bundle files as we saw in the &lt;code&gt;2-lazy-loading&lt;/code&gt; example.&lt;/p&gt;

&lt;p&gt;The way we solved each issue:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using a Babel plugin &lt;a href="https://github.com/FogelAI/babel-plugin-transform-barrels" rel="noopener noreferrer"&gt;&lt;code&gt;babel-plugin-transform-barrels&lt;/code&gt;&lt;/a&gt; that transforms indirect imports (barrel files) into direct imports during the bundle process.&lt;/li&gt;
&lt;li&gt;Splitting modules with more than one function into several modules with one function each.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I hope that in the future, the Webpack team will address and resolve the issues I have demonstrated in this article without any special plugin or configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Additional Resources:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://renatopozzi.me/articles/your-nextjs-bundle-will-thank-you" rel="noopener noreferrer"&gt;Your Next.js Bundle Will Thank You&lt;/a&gt; - It's about barrel files and &lt;code&gt;sideEffects&lt;/code&gt; solution.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://medium.com/@klauskpm/do-a-barrel-export-aa5b79b76b05" rel="noopener noreferrer"&gt;Do a barrel export&lt;/a&gt; - A brief overview of tools for barrel files.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>javascript</category>
      <category>webpack</category>
      <category>frontend</category>
      <category>barrelfiles</category>
    </item>
    <item>
      <title>Tree shaking in Webpack</title>
      <dc:creator>Fogel</dc:creator>
      <pubDate>Mon, 17 Jul 2023 13:15:13 +0000</pubDate>
      <link>https://dev.to/fogel/tree-shaking-in-webpack-5apj</link>
      <guid>https://dev.to/fogel/tree-shaking-in-webpack-5apj</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Javascript file size can have a significant impact on browser performance. Unused code increases the size of our bundle file and as a result causes performance issues.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Delivering less JavaScript can mean less time in network transmission, less spent decompressing code and less time parsing and compiling this JavaScript - Addy Osmani&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One effective way to reduce Javascript file size is through tree shaking.&lt;/p&gt;

&lt;p&gt;Tree shaking is a term commonly used in the context of Javascript module bundlers. It refers to the process of removing unused code from the final bundle.&lt;/p&gt;

&lt;p&gt;It is a powerful feature that can help you optimize the size of your Javascript bundle files. Despite its usefulness, many developers are still unfamiliar with how it works and how to use it effectively. After researching the topic and encountering some common issues, I decided to write a comprehensive guide to tree shaking in Webpack.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore how tree shaking works in Webpack and how you can use it to optimize your code. Through examples and visualizations, we'll explain the process of tree shaking step by step and help you optimize your code for better performance.&lt;/p&gt;

&lt;h1&gt;
  
  
  TL;DR
&lt;/h1&gt;

&lt;p&gt;When building a production bundle in Webpack, the tree shaking process occurs automatically. The optimization properties of usedExports and sideEffects are enabled by default, leading to automatic optimization of the bundle files. &lt;/p&gt;

&lt;p&gt;The main purpose of manually configuring sideEffects is to eliminate unused reexported modules within &lt;a href="https://dev.to/fogel/potential-issues-with-barrel-files-in-webpack-4bf2#what-are-barrel-files-indexjs"&gt;barrel files&lt;/a&gt;, resulting in a significant reduction in bundle size, improving performance and loading times.&lt;/p&gt;

&lt;h1&gt;
  
  
  Webpack
&lt;/h1&gt;

&lt;p&gt;Webpack's main role is to bundle all module files into one or several files and minimize their size to save time and reduce server requests. Typically, we provide one entry point (the main Javascript file) to the Webpack config and then bundle files are created.&lt;/p&gt;

&lt;p&gt;When executing regular Javascript (non-bundled), ES Modules evaluate every imported module file even if the imported specifier of the module is not used because the module can have side effects.&lt;/p&gt;

&lt;p&gt;According to &lt;a href="http://www.ecma-international.org/ecma-262/6.0/#table-37" rel="noopener noreferrer"&gt;ECMA spec&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Do nothing if this module has already been evaluated. Otherwise, transitively &lt;strong&gt;evaluate all module dependences of this module and then evaluate this module&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To resemble the behavior of ES Modules, Webpack includes every imported module's code (a dependency) in the bundle file without any elimination of code (except for optimization features).&lt;/p&gt;

&lt;h2&gt;
  
  
  Bundle Javascript project (development mode)
&lt;/h2&gt;

&lt;p&gt;Let's create an example of regular Webpack bundle files without optimization.&lt;/p&gt;

&lt;p&gt;In this example, we'll demonstrate how webpack bundles different files types (JS/CSS) into one file type &lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/tree-shaking/examples/1-without-optimization/dist/main.js" rel="noopener noreferrer"&gt;main.js&lt;/a&gt; and &lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/tree-shaking/examples/1-without-optimization/dist/main.css" rel="noopener noreferrer"&gt;main.css&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We'll use development mode because it does not have any optimizations configured by default.&lt;/p&gt;

&lt;p&gt;To see the differences between different mode configurations (production/development/other) you can refer to the &lt;a href="https://github.com/webpack/webpack/blob/main/lib/config/defaults.js" rel="noopener noreferrer"&gt;defaults.js&lt;/a&gt; file.&lt;/p&gt;

&lt;p&gt;Let's take a look at the Webpack configuration:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/tree-shaking/examples/1-without-optimization/webpack.config.js" rel="noopener noreferrer"&gt;webpack.config.js&lt;/a&gt;&lt;/em&gt;&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;//...&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="c1"&gt;//...&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before we run the webpack command, let's take a look at our code:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/tree-shaking/examples/1-Without-optimization/src/App.js" rel="noopener noreferrer"&gt;App.js&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GreenText&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;./components/Texts/GreenText/GreenText&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;RedText&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;./components/Texts/RedText/RedText&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;getHundredNumber&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;./tools/numberFunctions/numberFunctions&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;getUnusedModuleText&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;./tools/unusedModule/unusedModule&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./tools/sideEffectsModule/sideEffectsModule&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hundredNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getHundredNumber&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;GreenText&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Number in green: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;hundredNumber&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;GreenText&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RedText&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Text in red&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;RedText&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the code above, we can see that we have &lt;code&gt;GreenText&lt;/code&gt; and &lt;code&gt;RedText&lt;/code&gt; components, the &lt;code&gt;getHundredNumber&lt;/code&gt; function and the &lt;code&gt;sideEffectsModule&lt;/code&gt; module in &lt;code&gt;App.js&lt;/code&gt;. We also import an unused function &lt;code&gt;getUnusedModuleText&lt;/code&gt;. These components, functions and module use different modules through direct import:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The component &lt;code&gt;GreenText&lt;/code&gt; is from the module &lt;code&gt;"./components/Texts/GreenText/GreenText&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The component &lt;code&gt;RedText&lt;/code&gt; is from the module &lt;code&gt;"./components/Texts/RedText/RedText"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The function &lt;code&gt;getHundredNumber&lt;/code&gt; is from the module &lt;code&gt;"./tools/numberFunctions/numberFunctions"&lt;/code&gt;, which contains another two functions (&lt;code&gt;getTenNumber&lt;/code&gt;, &lt;code&gt;getThousandNumber&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;the unused function &lt;code&gt;getUnusedModuleText&lt;/code&gt; is from the module &lt;code&gt;"./tools/unusedModule/unusedModule"&lt;/code&gt;, which contains another function (&lt;code&gt;getUnusedModuleButton&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;A side effect import module that is imported from &lt;code&gt;"./tools/sideEffectsModule/sideEffectsModule"&lt;/code&gt;, which contains global code with side effects.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the bundle process we expect that it will produce two files (JS and CSS files).&lt;/p&gt;

&lt;p&gt;Let's run &lt;code&gt;npx webpack&lt;/code&gt; in the terminal window.&lt;/p&gt;

&lt;p&gt;The build process created two files as expected: &lt;code&gt;main.js&lt;/code&gt; and &lt;code&gt;main.css&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's demonstrate it in a dependency tree:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fk6rrpd13d83xbf1zm0rp.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fk6rrpd13d83xbf1zm0rp.gif" alt="without optimization" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/tree-shaking/examples/1-without-optimization/dist/main.js" rel="noopener noreferrer"&gt;main.js&lt;/a&gt; file, we can see that all functions and global code from all imported modules are included in the file. Even functions that weren't imported as a specifier in the import statement are included in the bundle file. As we mentioned earlier, Webpack resembles the behavior of ES Modules by importing the entire code of modules including unused code (dead code).&lt;/p&gt;

&lt;p&gt;Even the following unused functions are included:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The unused function &lt;code&gt;getUnusedModuleButton&lt;/code&gt; from the unused module &lt;code&gt;./tools/unusedModule/unusedModule&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The unused functions &lt;code&gt;getTenNumber&lt;/code&gt; and &lt;code&gt;getThousandNumber&lt;/code&gt; from the used module &lt;code&gt;./tools/numberFunctions/numberFunctions&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The &lt;code&gt;BlueText&lt;/code&gt; and &lt;code&gt;BlackText&lt;/code&gt; are not included because they haven't been imported anywhere.&lt;/p&gt;

&lt;p&gt;When importing from a re-exported module, for example, a barrel file, Webpack will evaluate all re-exported modules as having side effects even if some of the re-exported modules aren't imported or used. The reason for this is written in the official Webpack &lt;a href="https://github.com/webpack/webpack/tree/main/examples/side-effects" rel="noopener noreferrer"&gt;example of side effects&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;According to the EcmaScript spec, all child modules must be evaluated because they could contain side effects.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sean from the Webpack team also explained this on &lt;a href="https://stackoverflow.com/a/49203452" rel="noopener noreferrer"&gt;Stack Overflow&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;According to the ECMA Module Spec, whenever a module re-exports all exports, (regardless if used or unused) they need to be evaluated and executed in case one of those exports created a side-effect with another.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The used and unused functions are marked in the &lt;code&gt;main.js&lt;/code&gt; bundle file by the comment &lt;code&gt;"harmony export"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;These unused functions (also known as dead code) increase the size of our bundle file and cause performance issues.&lt;/p&gt;

&lt;p&gt;To improve performance, we prefer to carefully delete unused code and make our bundle file as small as possible.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/tree-shaking/examples/1-without-optimization/dist/main.css" rel="noopener noreferrer"&gt;main.css&lt;/a&gt; file, we can see both class selectors of &lt;code&gt;.GreenText&lt;/code&gt; and &lt;code&gt;.RedText&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The term for dead code elimination is called &lt;strong&gt;Tree shaking&lt;/strong&gt; and we will discuss it in the next chapter.&lt;/p&gt;

&lt;h1&gt;
  
  
  Tree Shaking
&lt;/h1&gt;

&lt;p&gt;During the build process, Webpack creates a dependency tree structure. In the tree, each dependency (module) is represented by a branch and each function is represented by a leaf. There are green branches (which represent modules with used functions or with side effects), light green leaves (which represent imported used functions), brown leaves (which represent unused functions from imported module, also known as "dead code") and dark brown branches (which represent imported unused modules with no side effects). When we shake the tree, the brown leaves should fall off while the green leaves remain. In our case, this means that after tree shaking only imported used functions or modules with used functions or side effects should remain.&lt;/p&gt;

&lt;p&gt;As we saw in the last example, used and unused functions were marked the same with the comment &lt;code&gt;"harmony export"&lt;/code&gt; that specifies the green leaves.&lt;/p&gt;

&lt;p&gt;How can it be that unused functions were marked as green leaves? Because we were in development mode, which has no optimization enabled.&lt;/p&gt;

&lt;p&gt;So how can we mark the unused functions as brown leaves and unused modules without side effects as dark brown branches? For this, we should use the optimization configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimization
&lt;/h2&gt;

&lt;h3&gt;
  
  
  usedExports
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;usedExports&lt;/code&gt; property is responsible for marking the unused functions with brown leaves.&lt;/p&gt;

&lt;p&gt;Let's clone the previous example &lt;code&gt;1-without-optimization&lt;/code&gt; to &lt;code&gt;2-optimization-usedExports&lt;/code&gt; and change the Webpack config file as follows:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/tree-shaking/examples/2-optimization-usedExports/webpack.config.js" rel="noopener noreferrer"&gt;webpack.config.js&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;//...
&lt;span class="p"&gt;module.exports = {
&lt;/span&gt;  mode: "development",
&lt;span class="gi"&gt;+ optimization: {
+   usedExports: true,
+ },
&lt;/span&gt;//...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now run &lt;code&gt;npx webpack&lt;/code&gt; in the terminal window.&lt;/p&gt;

&lt;p&gt;Let's demonstrate it in a dependency tree:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fbj9egatio9qgbgaqmea4.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fbj9egatio9qgbgaqmea4.gif" alt="optimization usedExports" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Take a look at the bundle file:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/tree-shaking/examples/2-usedExports-enabled/dist/main.js" rel="noopener noreferrer"&gt;main.js&lt;/a&gt;&lt;/em&gt;&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;//...&lt;/span&gt;
&lt;span class="cm"&gt;/* unused harmony exports getTenNumber, getThousandNumber */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getTenNumber&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getHundredNumber&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getThousandNumber&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="cm"&gt;/* unused harmony exports getUnusedModuleText, getUnusedModuleButton */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUnusedModuleText&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;imported but unused module&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUnusedModuleButton&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;imported but unused module&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;p&gt;In the &lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/tree-shaking/examples/2-usedExports-enabled/dist/main.js" rel="noopener noreferrer"&gt;main.js&lt;/a&gt; file we can see that Webpack with the &lt;code&gt;usedExports: true&lt;/code&gt; property marked the unused functions (dead code) with the comment &lt;code&gt;/* unused harmony export functionName */&lt;/code&gt;. This comment points to the unused function as a brown leaf in the tree.&lt;/p&gt;

&lt;p&gt;But the entire unused function declarations are still in the file. How can we get rid of it? How can we shake the tree and cause brown leaves to fall down (eliminate dead code) to the ground? We will shake the tree later using either the configuration of &lt;code&gt;minimize: true&lt;/code&gt; or &lt;code&gt;mode: production&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/tree-shaking/examples/2-usedExports-enabled/dist/main.css" rel="noopener noreferrer"&gt;main.css&lt;/a&gt; file, we can see that it's the same as in the first example &lt;code&gt;1-without-optimization&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  sideEffects
&lt;/h3&gt;

&lt;p&gt;First, let's explain what side effects are.&lt;/p&gt;

&lt;p&gt;There are two types of code: pure code and code with side effects:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pure code&lt;/strong&gt;: It uses only variables from its scope and doesn't use global variables like the &lt;code&gt;window&lt;/code&gt; object or data that comes from the outside sources such as HTTP requests, file system, DOM, etc.
For example, a pure function always returns the same output for the same input and doesn't use global variables. In short, pure code is a code without side effects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code with side effects&lt;/strong&gt;: It uses global variables or data from outside its scope. For example, a function that can return different output for the same input or a function that changes global variables like the &lt;code&gt;window&lt;/code&gt; object or uses data from HTTP calls, file system, DOM, etc. In short, It is the opposite of pure code.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In Webpack, &lt;code&gt;sideEffects&lt;/code&gt; configuration enables us to exclude entire module (and his dependencies) whose direct exports are not used and doesn't have side effects from the bundle file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Point to remember to this section: In Webpack, the &lt;code&gt;sideEffects&lt;/code&gt; configuration only affects imported modules whose direct exports are not used. Modules with used exports will always be included. An example of imported modules whose direct exports are not used are barrel files that re-export functions.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are two configurations for &lt;code&gt;sideEffects&lt;/code&gt; that are designed to work together if they configured:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;sideEffects&lt;/code&gt; property in the &lt;code&gt;optimization&lt;/code&gt; object in &lt;code&gt;webpack.config.js&lt;/code&gt; - Enable the use for manual configuration of modules with or without side effects and/or automatic analysis of modules for side effects.&lt;/li&gt;
&lt;li&gt;The manual &lt;code&gt;sideEffects&lt;/code&gt; property inside either &lt;code&gt;package.json&lt;/code&gt; file or the &lt;code&gt;module.rules&lt;/code&gt; array in the &lt;code&gt;webpack.config.js&lt;/code&gt; file - Manually configure the list of modules that have or don't have side effects. In this case modules whose direct exports are not used flagged manually as having no side effects, then these modules and their dependencies will be safely excluded from the bundle file without even being evaluated.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;sideEffects optimization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;According to &lt;a href="https://github.com/webpack/webpack/blob/eac5d8cacb8a33914d7abf74ee76b51bb087217e/schemas/WebpackOptions.json" rel="noopener noreferrer"&gt;WebpackOptions.json&lt;/a&gt;, the optimization &lt;code&gt;sideEffects&lt;/code&gt; property can have the following values:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;true&lt;/code&gt; - Include or exclude modules depending on their manual configuration in the &lt;code&gt;package.json&lt;/code&gt; or &lt;code&gt;webpack.config.js&lt;/code&gt; file. Modules that haven't been flagged with or without side effects in the &lt;code&gt;webpack.config.js&lt;/code&gt; file and whose exports are not used will be analyzed, if there are no side effects, they will be excluded.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;"flag"&lt;/code&gt; - Only include or exclude modules depending on their manual configuration in the &lt;code&gt;package.json&lt;/code&gt; or &lt;code&gt;webpack.config.js&lt;/code&gt; file. Modules that haven't been flagged with or without side effects in the &lt;code&gt;webpack.config.js&lt;/code&gt; file will be included as usual, just like we learned about ES modules.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;false&lt;/code&gt; - It will not evaluate modules for side effects even if set in the &lt;code&gt;package.json&lt;/code&gt; or &lt;code&gt;webpack.config.js&lt;/code&gt; file. All imported modules will be included as we learned about ES modules.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the modules with side effects are flagged in the &lt;code&gt;package.json&lt;/code&gt; file, the remaining files will be flagged as having no side effects. So if modules are configured through the &lt;code&gt;package.json&lt;/code&gt; file, there will be no difference between the values &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;"flag"&lt;/code&gt;. The result of them will be the same because all modules are flagged with or without side effects and there is no module that isn't flagged. Then the &lt;code&gt;true&lt;/code&gt; value will not have modules to analyze because all modules have been flagged with or without side effects, so &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;"flag"&lt;/code&gt; will have the same behavior.&lt;br&gt;
Production mode uses the optimization &lt;code&gt;sideEffects&lt;/code&gt; value of &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Before we dive into the manual way of configuring sideEffects, let's make an example about the optimization &lt;code&gt;sideEffects&lt;/code&gt; property without manually defining which modules have or don't have side effects:&lt;/p&gt;

&lt;p&gt;Clone the previous example &lt;code&gt;2-optimization-usedExports&lt;/code&gt; to &lt;code&gt;3-optimization-sideEffects&lt;/code&gt; and change the webpack config file as follows:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/tree-shaking/examples/3-optimization-sideEffects/webpack.config.js" rel="noopener noreferrer"&gt;webpack.config.js&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;//...
&lt;span class="p"&gt;module.exports = {
&lt;/span&gt;  mode: "development",
 optimization: {
   usedExports: true,
&lt;span class="gi"&gt;+  sideEffects: true,
&lt;/span&gt; },
//...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now run &lt;code&gt;npx webpack&lt;/code&gt; in the terminal window.&lt;/p&gt;

&lt;p&gt;Let's demonstrate it in a dependency tree:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fuxi56i2u92iufrcalk00.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fuxi56i2u92iufrcalk00.gif" alt="optimization sideEffects" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Take a look at the bundle file:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/tree-shaking/examples/3-optimization-sideEffects/dist/main.js" rel="noopener noreferrer"&gt;main.js&lt;/a&gt;&lt;/em&gt;&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;//...&lt;/span&gt;
&lt;span class="cm"&gt;/* unused harmony exports getTenNumber, getThousandNumber */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getTenNumber&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getHundredNumber&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getThousandNumber&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/tree-shaking/examples/3-optimization-sideEffects/dist/main.js" rel="noopener noreferrer"&gt;main.js&lt;/a&gt; file, we can see that Webpack with the &lt;code&gt;sideEffects: true&lt;/code&gt; property eliminates the unused module of &lt;code&gt;unusedModule&lt;/code&gt; (dead code) compared to the previous example &lt;code&gt;2-optimization-usedExports&lt;/code&gt; which just marked &lt;code&gt;unusedModule&lt;/code&gt; with &lt;code&gt;/* unused harmony export getUnusedModuleText, getUnusedModuleButton */&lt;/code&gt;. When we use in &lt;code&gt;mode: production&lt;/code&gt;, which under the hood uses &lt;code&gt;minimize: true&lt;/code&gt;, for both the second and third examples, both bundle files will be the same because the unused &lt;code&gt;unusedModule&lt;/code&gt; will be eliminated during the minimizing process.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/tree-shaking/examples/3-optimization-sideEffects/dist/main.css" rel="noopener noreferrer"&gt;main.css&lt;/a&gt; file, we can see that it's the same as in the first example &lt;code&gt;1-without-optimization&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;sideEffects - Manually define&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, if we set the optimization &lt;code&gt;sideEffects&lt;/code&gt; property to &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;"flag"&lt;/code&gt;, we can help Webpack manually define which modules have side effects and which don't.&lt;/p&gt;

&lt;p&gt;Sean from the Webpack team explains on &lt;a href="https://stackoverflow.com/questions/49160752/what-does-webpack-4-expect-from-a-package-with-sideeffects-false" rel="noopener noreferrer"&gt;Stack Overflow&lt;/a&gt; that we use the &lt;code&gt;sideEffects&lt;/code&gt; configuration as a way to save on both compile time and build size because it excludes modules in advance that are flagged as having no side effects and whose direct exports are not used.&lt;/p&gt;

&lt;p&gt;According to Webpack &lt;a href="https://webpack.js.org/guides/tree-shaking/#clarifying-tree-shaking-and-sideeffects" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;sideEffects&lt;/code&gt; is much more effective since it allows to skip whole modules/files and the complete subtree.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;usedExports&lt;/code&gt; relies on Terser to detect side effects in statements. It is a difficult task in JavaScript and not as effective as straightforward &lt;code&gt;sideEffects&lt;/code&gt; flag.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Webpack's team talked about another purpose of the manual &lt;code&gt;sideEffects&lt;/code&gt; property in their &lt;a href="https://youtu.be/bm7RlNEcQM0?t=1761" rel="noopener noreferrer"&gt;conference&lt;/a&gt; and explained that it comes to solve the issue of big bundle files when using of barrel files.&lt;/p&gt;

&lt;p&gt;There are 2 ways to manually define which modules have side effects and which don't:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Package config file (&lt;code&gt;package.json&lt;/code&gt;):&lt;/p&gt;

&lt;p&gt;All package modules have no side effects:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"example-module"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sideEffects"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Alternatively, an array of modules that have side effects (the remaining modules will be considered and flagged as having no side effects if they don't have used direct exports):&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"example-module"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sideEffects"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"*.css"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*.scss"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Webpack config file (&lt;code&gt;webpack.config.js&lt;/code&gt;):&lt;/p&gt;

&lt;p&gt;Use regular expressions to define all Javascript and Typescript files in the project as having no side effects and CSS files as having side effects:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;rules&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;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.(&lt;/span&gt;&lt;span class="sr"&gt;js|mjs|jsx|ts|tsx&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;sideEffects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;s&lt;/span&gt;&lt;span class="se"&gt;?&lt;/span&gt;&lt;span class="sr"&gt;css$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;sideEffects&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We know that CSS files are considered to have side effects, so we flag them as such. However, this is not mandatory and we can remove the rule for CSS files above. The result will be the same, it's just for protection. if someone later configures the &lt;code&gt;package.json&lt;/code&gt; file with &lt;code&gt;sideEffects: false&lt;/code&gt;, the rule in &lt;code&gt;webpack.config.js&lt;/code&gt; for CSS will override the configuration in &lt;code&gt;package.json&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Webpack wrote a "Tip" about CSS files as described on &lt;a href="https://webpack.js.org/guides/tree-shaking/#mark-the-file-as-side-effect-free" rel="noopener noreferrer"&gt;Webpack website&lt;/a&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; Note that any imported file is subject to tree shaking. This means if you use something like css-loader in your project and import a CSS file, it needs to be added to the side effect list so it will not be unintentionally dropped in production mode.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Side effect import - &lt;code&gt;import "filename.js"&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#import_a_module_for_its_side_effects_only" rel="noopener noreferrer"&gt;Side effect import&lt;/a&gt; also called "Empty import", It will need to be included if there are side effects inside it. This can include, for example, global code and CSS files.&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;filename.js&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;filename.css&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;In our examples, we use a module with side effects called &lt;code&gt;sideEffectsModule&lt;/code&gt;. Note that this module has no exports but have side effects cause it affects &lt;code&gt;window&lt;/code&gt; object. So this kind of module can easily be excluded from the bundle file if it is configured incorrectly and not included in the array of the &lt;code&gt;sideEffects&lt;/code&gt; property in the &lt;code&gt;package.json&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;So let's make a manual configuration of &lt;code&gt;sideEffects&lt;/code&gt; in the &lt;code&gt;package.json&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Let's clone the previous example &lt;code&gt;3-optimization-sideEffects&lt;/code&gt; to &lt;code&gt;4-package-sideEffects&lt;/code&gt; and change the package config file as follows:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/tree-shaking/examples/4-package-sideEffects/package.json" rel="noopener noreferrer"&gt;package.json&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;{
  "name": "example-module",
&lt;span class="gi"&gt;+ "sideEffects": ["*.css"],
&lt;/span&gt;}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;webpack.config.js&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;module: {
&lt;/span&gt;  rules: [
    {
      test: /\.(js|mjs|jsx|ts|tsx)$/,
&lt;span class="gi"&gt;+     sideEffects: false
&lt;/span&gt;    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our example we use only the &lt;code&gt;package.json&lt;/code&gt; option, but both options have the same result.&lt;/p&gt;

&lt;p&gt;Now run &lt;code&gt;npx webpack&lt;/code&gt; in the terminal window.&lt;/p&gt;

&lt;p&gt;Let's demonstrate it in a dependency tree:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F5k75psx2nbfx02hd9afa.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F5k75psx2nbfx02hd9afa.gif" alt="package sideEffects" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/tree-shaking/examples/4-package-sideEffects/dist/main.js" rel="noopener noreferrer"&gt;main.js&lt;/a&gt; file, we can see that it is similar to the previous example (3-optimization-sideEffects) except that the content of &lt;code&gt;sideEffectsModule&lt;/code&gt; is not included. This occurred because &lt;code&gt;sideEffectsModule&lt;/code&gt; doesn't have any exports and was flagged as having no side effects. As a result, Webpack doesn't evaluate it for side effects and simply skips over the &lt;code&gt;sideEffectsModule&lt;/code&gt; module.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/tree-shaking/examples/4-package-sideEffects/dist/main.css" rel="noopener noreferrer"&gt;main.css&lt;/a&gt; file, we can see that it's the same as in the first example (1-without-optimization).&lt;/p&gt;

&lt;p&gt;So what are the differences between the third and fourth examples except the missing global code of &lt;code&gt;sideEffectsModule&lt;/code&gt; module? It's about compile time, as we talked earlier about Sean from the Webpack team. In the fourth example, Webpack skips over modules with unused exports that have been flagged as having no side effects without attempting to evalute them for side effects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;sideEffects - Manually define fixed&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's make the same example but this time we will correctly configure the &lt;code&gt;package.json&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/tree-shaking/examples/5-package-sideEffects-fixed/package.json" rel="noopener noreferrer"&gt;package.json&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;{
  "name": "example-module",
&lt;span class="gd"&gt;- "sideEffects": ["*.css"],
&lt;/span&gt;&lt;span class="gi"&gt;+ "sideEffects": ["*.css", "sideEffectsModule.js"],
&lt;/span&gt;}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now run &lt;code&gt;npx webpack&lt;/code&gt; in the terminal window.&lt;/p&gt;

&lt;p&gt;Let's demonstrate it in a dependency tree:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F8f6ljixuy2wm11aycspv.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F8f6ljixuy2wm11aycspv.gif" alt="package sideEffects fixed" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/tree-shaking/examples/5-package-sideEffects-fixed/dist/main.js" rel="noopener noreferrer"&gt;main.js&lt;/a&gt; file, we can see that now it fixed and &lt;code&gt;sideEffectsModule&lt;/code&gt; module content is included in the bundle file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note - Manually configuring sideEffects issue&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I found an &lt;a href="https://github.com/webpack/webpack/issues/10413" rel="noopener noreferrer"&gt;issue&lt;/a&gt; where &lt;strong&gt;Hypnosphi&lt;/strong&gt; complained that there were differences between development and production when he configured &lt;code&gt;sideEffects: false&lt;/code&gt;. He noticed that the order of CSS was not the order of the imports but the usage order. In another &lt;a href="https://github.com/webpack/webpack/issues/7094#issuecomment-383466978" rel="noopener noreferrer"&gt;issue&lt;/a&gt; there is an answer from sokra (a Webpack team member) who wrote:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Technically using sideEffects you say order doesn't matter&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Another answer of &lt;a href="https://github.com/webpack/webpack/issues/7094#issuecomment-945663737" rel="noopener noreferrer"&gt;sokra&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If the order of some modules matter they are not side-effect-free.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I will expand on this in the article &lt;a href="https://dev.to/fogel/potential-issues-with-barrel-files-in-webpack-4bf2"&gt;&lt;em&gt;Potential issues with barrel files in Webpack&lt;/em&gt;&lt;/a&gt; talking about issues with optimization configuration and how to solve them.&lt;/p&gt;

&lt;p&gt;If I only import the modules that I use, why should I use the &lt;code&gt;sideEffects&lt;/code&gt; property? It's useful for modules that only re-exports functions from other modules. For example, barrel files that are used inside modules that are dynamically imported. I will expand on this in my next article.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Summarize the &lt;code&gt;sideEffects&lt;/code&gt; configuration in a diagram:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fztbkn49136ou3s0qk1l6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fztbkn49136ou3s0qk1l6.png" alt="sideEffects diagram" width="720" height="960"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Production mode
&lt;/h3&gt;

&lt;p&gt;The last thing that remains to check is the production bundle.&lt;/p&gt;

&lt;p&gt;Production mode has different optimization values compared to development mode. We can see in the &lt;a href="https://github.com/webpack/webpack/blob/main/lib/config/defaults.js" rel="noopener noreferrer"&gt;default.js&lt;/a&gt; file that &lt;code&gt;minimize&lt;/code&gt; is set to true.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;minimize&lt;/code&gt; property is used as the final tree shaking step. It eliminates unused exports (brown leaves) that were marked by &lt;code&gt;usedExports&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's clone the third example &lt;code&gt;3-optimization-sideEffects&lt;/code&gt; to &lt;code&gt;6 - production&lt;/code&gt; and change the webpack config file as follows:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/tree-shaking/examples/6-production/webpack.config.js" rel="noopener noreferrer"&gt;webpack.config.js&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;  //...
  module.exports = {
&lt;span class="gi"&gt;+   mode: "production",
&lt;/span&gt;&lt;span class="gd"&gt;-   mode: "development",
-   optimization: {
-     usedExports: true,
-     sideEffects: true,
-   },
&lt;/span&gt;//...
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now run &lt;code&gt;npx webpack&lt;/code&gt; in the terminal window.&lt;/p&gt;

&lt;p&gt;Let's demonstrate it in a dependency tree:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fjaefz4179disx9fpa3gp.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fjaefz4179disx9fpa3gp.gif" alt="production" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/tree-shaking/examples/6-production/dist/main.js" rel="noopener noreferrer"&gt;main.js&lt;/a&gt; file, we can see that it's significantly smaller file. It only includes what's needed and mangles the variable and function names.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://github.com/FogelAI/webpack-optimization-articles/tree/main/tree-shaking/examples/6-production/dist/main.css" rel="noopener noreferrer"&gt;main.css&lt;/a&gt; file, we can see that it has changed here because it eliminated comments in the file compared to previous examples.&lt;/p&gt;

&lt;p&gt;After optimizing and minifying our bundle file, let's take a look at the results.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F70wkg0qabvetjfarucw0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F70wkg0qabvetjfarucw0.png" alt="6-production-bundling-summary" width="545" height="102"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As shown in the screenshot, the size of the JS files has decreased significantly - from 1.36kb to 626 bytes, a reduction of 54%. This is a substantial decrease in size.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tree shaking summary steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Eliminating imported modules whose direct exports are not used and don't have side effects with &lt;code&gt;sideEffects&lt;/code&gt; configuration.&lt;/li&gt;
&lt;li&gt;Mark the brown leaves (comment: &lt;code&gt;/* unused harmony export functionName */&lt;/code&gt;) with the &lt;code&gt;usedExports: true&lt;/code&gt; property.&lt;/li&gt;
&lt;li&gt;Shake the tree (eliminate dead code) with the &lt;code&gt;minimize: true&lt;/code&gt; or &lt;code&gt;mode: production&lt;/code&gt; property.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Dynamic imports
&lt;/h2&gt;

&lt;p&gt;This article will not cover the topic of tree shaking &lt;em&gt;dynamic imports&lt;/em&gt;. For an in-depth explanation of this subject, please refer to the awesome article &lt;a href="https://blog.hotstar.com/how-to-dynamically-import-esmodules-and-tree-shake-them-too-aa24ee4885f5" rel="noopener noreferrer"&gt;&lt;em&gt;Dynamically Import ESModules and Tree Shake them too!&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;In this article, we explored the concept of tree shaking in Webpack to optimize your bundle file. We explained how tree shaking can be used to remove unused functions and modules (dead code) from the final bundle and which optimization properties involved in that through examples and visualizations. The main purpose of this article was to ease the tree shaking subject and I hope that I succeeded in that.&lt;/p&gt;

&lt;p&gt;I recommend reading my next article on &lt;a href="https://dev.to/fogel/potential-issues-with-barrel-files-in-webpack-4bf2"&gt;&lt;em&gt;Potential issues with barrel files in Webpack&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Additional Resources:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://web.dev/reduce-javascript-payloads-with-tree-shaking/" rel="noopener noreferrer"&gt;Reduce JavaScript payloads with tree shaking&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://webpack.js.org/guides/tree-shaking/" rel="noopener noreferrer"&gt;Tree Shaking in official Webpack website&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://javascript.plainenglish.io/deep-dive-into-tree-shaking-ba2e648b8dcb" rel="noopener noreferrer"&gt;Deep Dive Into Tree-Shaking&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cube.dev/blog/how-to-build-tree-shakeable-javascript-libraries" rel="noopener noreferrer"&gt;How to build tree-shakeable JavaScript libraries&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://web.dev/optimizing-content-efficiency-javascript-startup-optimization/" rel="noopener noreferrer"&gt;JavaScript Start-up Optimization&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webpack</category>
      <category>frontend</category>
      <category>treeshaking</category>
    </item>
  </channel>
</rss>
