<?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>Forem: Mathias Bernardeau</title>
    <description>The latest articles on Forem by Mathias Bernardeau (@mbernardeau).</description>
    <link>https://forem.com/mbernardeau</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F348883%2F390b37d5-2bae-408a-89a1-933405b09b31.jpeg</url>
      <title>Forem: Mathias Bernardeau</title>
      <link>https://forem.com/mbernardeau</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mbernardeau"/>
    <language>en</language>
    <item>
      <title>6 tips to optimize bundle size</title>
      <dc:creator>Mathias Bernardeau</dc:creator>
      <pubDate>Wed, 13 May 2020 14:56:51 +0000</pubDate>
      <link>https://forem.com/mbernardeau/6-tips-to-optimize-bundle-size-50n9</link>
      <guid>https://forem.com/mbernardeau/6-tips-to-optimize-bundle-size-50n9</guid>
      <description>&lt;p&gt;Disclaimer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article includes optimizations that are only valid for an app bundled with webpack, or only for a React app. Some optimizations also assume you have control over the webpack configuration of your app.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Measure and visualize bundle size
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Valid for: any app bundled with Webpack&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The tool &lt;a href="https://www.npmjs.com/package/webpack-bundle-analyzer" rel="noopener noreferrer"&gt;webpack-bundle-analyzer&lt;/a&gt; can produce an easily understandable view of the composition of a JS bundle.&lt;/p&gt;

&lt;p&gt;The easiest way to use it is to generate a stats file with webpack and to launch the tool with &lt;code&gt;npx&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;webpack &lt;span class="nt"&gt;--profile&lt;/span&gt; &lt;span class="nt"&gt;--json&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; stats.json
&lt;span class="c"&gt;# Assuming generated bundled files are in the dist folder&lt;/span&gt;
npx webpack-bundle-analyzer stats.json dist/  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fi%2F7v64iizv17wrf2qy18q9.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%2Fi%2F7v64iizv17wrf2qy18q9.png" alt="Example of a webpack-bundle-analyzer tab"&gt;&lt;/a&gt;&lt;/p&gt;
webpack-bundle-analyzer launches a tab in your browser which look like this



&lt;p&gt;To understand what the different sizes mean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Stat size&lt;/code&gt; is the size of the input, after webpack bundling but before optimizations like minification&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Parsed size&lt;/code&gt; is the size of the file on disk (after minification). It is the effective size of the JavaScript code parsed by the client browser&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gzip size&lt;/code&gt; is the size of the file after gzip (most likely the effective content size transmitted over the network)&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  1. Avoid libraries global imports
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Valid for: any bundled app or lib&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Cost: Low&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Impact: High&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With some large libraries, it is possible to import only the parts we use instead of the entire library. If done right, this can save a lot of unused bundle size.&lt;/p&gt;

&lt;p&gt;Examples of splittable libs: lodash, date-fns, react-bootstrap...&lt;/p&gt;

&lt;p&gt;The downside of this is that only one global import in the app or in dependencies that transitively depend on these libs is necessary to make the bundler include the whole dependency.&lt;/p&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%2Fi%2Fzhdf4bodb3xql6vpzpsx.png" alt="Using webpack-bundle-analyzer a global import of lodash will look like this"&gt;Using webpack-bundle-analyzer, a global import of lodash will look like this



&lt;p&gt;In this capture you can see that necessary functions are bundled up to 3 times (once in lodash.js, once in lodash.min.js, and once in one-by-one imports). This is the worse case scenario.&lt;/p&gt;

&lt;p&gt;There are two ways to enforce one-by-one imports. Note that both of these methods don't apply to dependencies, only to your own code.&lt;/p&gt;
&lt;h2&gt;
  
  
  Via a babel plugin
&lt;/h2&gt;

&lt;p&gt;The plugin &lt;a href="https://www.npmjs.com/package/babel-plugin-transform-imports" rel="noopener noreferrer"&gt;babel-plugin-transform-imports&lt;/a&gt; has the ability to replace global destructured imports by one-by-one imports.&lt;/p&gt;

&lt;p&gt;Configured like this:&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;.babelrc&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"plugins"&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="s2"&gt;"transform-imports"&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;"lodash"&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;"transform"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lodash/${member}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"preventFullImport"&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="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;



&lt;p&gt;It will have the following effect:&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;map&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;some&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;lodash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="c1"&gt;// will be replaced by&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;map&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;lodash/map&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;some&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;lodash/some&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the option &lt;code&gt;preventFullImport&lt;/code&gt; will tell the plugin to throw an error if it encounters an import which would include the entire library.&lt;/p&gt;

&lt;h2&gt;
  
  
  Via an ESLint rule
&lt;/h2&gt;

&lt;p&gt;The downside of the first method is that two methods of imports of the same function are valid, meaning it becomes harder to enforce a single import style in a single project.&lt;/p&gt;

&lt;p&gt;Fortunately it is possible to configure the &lt;a href="https://eslint.org/docs/rules/no-restricted-imports" rel="noopener noreferrer"&gt;no-restricted-imports&lt;/a&gt; rule to throw an error if a global import is encountered.&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;.eslintrc&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"no-restricted-imports"&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;"error"&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;"paths"&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;"lodash"&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;



&lt;p&gt;It will produce an error for the following 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;map&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;lodash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But not for a specific module import like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;map&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;lodash/map&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can of course combine these two methods to enforce a specific style.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Use code-splitting
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Valid for: Web apps bundled with webpack&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Cost: Low&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Impact: Variable&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Using dynamic imports and Suspense, it is possible to split application code in async chunks that can be loaded on-demand. This allows to reduce the size of the bundle downloaded initially. It does not reduce overall bundle size (it even slightly increases it).&lt;/p&gt;

&lt;p&gt;Configuration:&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="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;webpack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;span class="nx"&gt;optimization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;splitChunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// include all types of chunks&lt;/span&gt;
    &lt;span class="na"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;all&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default a “vendors” chunk is created, separating application code from dependencies. This can have a positive impact when updating the application. If only the application code changes (assuming resources are correctly cached), the client can save the cost of downloading vendors files. This behaviour can be disabled by setting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;optimization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;splitChunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// include all types of chunks&lt;/span&gt;
    &lt;span class="na"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;cacheGroups&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;vendors&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="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;Be careful not to be overzealous with code splitting as this can slow down some user actions as we have to download, parse and execute more code. Depending on the structure of the application, it possible that adding a chunk implies downloading several files (with HTTP 1, &lt;a href="https://stackoverflow.com/a/14768266/3890766" rel="noopener noreferrer"&gt;there is a limit on parallel connections to the same domain&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The recommended way is to create a chunk per route&lt;/strong&gt;. This is &lt;strong&gt;not&lt;/strong&gt; an absolute rule.&lt;/p&gt;

&lt;p&gt;How to export a lazy loaded component:&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="c1"&gt;// myComponent.lazy.jsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Suspense&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;LoadingIndicator&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;..&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// Create a lazy component using React.lazy&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponentLazy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
 &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* webpackChunkName: "my-component" */&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./myComponent&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;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Suspense&lt;/span&gt; &lt;span class="na"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;=&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;Loading&lt;/span&gt; &lt;span class="na"&gt;Indicator&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&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;MyComponentLazy&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&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;Suspense&lt;/span&gt;&lt;span class="p"&gt;&amp;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;MyComponent&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we use the dynamic import syntax to tell Webpack to bundle a separate chunk for MyComponent (and all its dependencies). &lt;/p&gt;

&lt;p&gt;Setting the &lt;code&gt;webpackChunkName&lt;/code&gt; is optional, this allows to control the name of the generated file (with the &lt;a href="https://webpack.js.org/configuration/output/#outputchunkfilename" rel="noopener noreferrer"&gt;corresponding webpack configuration&lt;/a&gt;). If two lazily imported components have the same name, they will be concatenated in a single chunk.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;React.lazy&lt;/code&gt; is used to allow the lazily imported component to be rendered like a regular component. &lt;code&gt;Suspense&lt;/code&gt; allows to provide a fallback (component that will be rendered while the import is not resolved).&lt;br&gt;
Note that &lt;code&gt;Suspense&lt;/code&gt; can be further up the component tree, depending on what the users should see during load.&lt;/p&gt;

&lt;p&gt;See &lt;a href="https://en.reactjs.org/docs/code-splitting.html" rel="noopener noreferrer"&gt;React documentation&lt;/a&gt; for a more complete explanation of &lt;code&gt;lazy&lt;/code&gt; and &lt;code&gt;Suspense&lt;/code&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  3. Do not include source maps
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Valid for: Web apps and libs bundled with Webpack&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Cost: Low&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Impact: Variable&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Source maps are a link between source code and generated bundled files. While it can be really useful to use browser debuggers, it shouldn't be included in the production bundle.&lt;/p&gt;

&lt;p&gt;For JS source-map, the option &lt;a href="https://webpack.js.org/configuration/devtool/#root" rel="noopener noreferrer"&gt;devtool&lt;/a&gt; controls how source-maps are generated.&lt;br&gt;
For development, &lt;code&gt;'eval-source-map'&lt;/code&gt; is a good choice (we see the original source and rebuilds are fast).&lt;br&gt;
For production, setting &lt;code&gt;false&lt;/code&gt; will completely disable source-map generation. As it can be useful to debug generated bundled app, the best way to keep them in production is to set &lt;code&gt;devtool: 'source-map'&lt;/code&gt;. It will generate a separate file (downloaded only if browser devtools are open) linked by a comment added in the original bundle that looks like this: &lt;code&gt;//# sourceMappingURL=app.daa9676c2167d965d0ae.js.map&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For CSS, Less or Sass source-maps, the configuration depends on the loader used. Using &lt;a href="https://github.com/webpack-contrib/css-loader" rel="noopener noreferrer"&gt;css-loader&lt;/a&gt;, &lt;a href="https://github.com/webpack-contrib/sass-loader" rel="noopener noreferrer"&gt;sass-loader&lt;/a&gt; and &lt;a href="https://github.com/webpack-contrib/less-loader" rel="noopener noreferrer"&gt;less-loader&lt;/a&gt;, I would recommend setting &lt;code&gt;options: { sourceMap: true }&lt;/code&gt; in development inside loader configuration, and &lt;code&gt;options: { sourceMap: false }&lt;/code&gt; in production (as this is the default, you can safely omit the property in production).&lt;/p&gt;
&lt;h1&gt;
  
  
  4. Remove replaceable libs
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Valid for: any bundled app or lib&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Cost: Variable&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Impact: Variable&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It can be very tempting to add a library which does meet the user requirement but also do much more. Possible reasons include not knowing future needs of users or simply to deliver faster.&lt;/p&gt;

&lt;p&gt;Adding unneeded complexity can have a huge impact on the bundle size.&lt;/p&gt;

&lt;p&gt;In my project, we found out that we used &lt;a href="https://www.npmjs.com/package/libphonenumber-js" rel="noopener noreferrer"&gt;libphonenumber-js&lt;/a&gt; for only two use cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Format a french phone number&lt;/li&gt;
&lt;li&gt;Validate an input field which only allows french phone numbers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Having to deal only with french phone number greatly reduce the complexity needed for these kind of features. libphonenumber-js is a great library -- just not fitted to our needs.&lt;/p&gt;

&lt;p&gt;Rewriting these feature using only vanilla JS took only a few hours and saved us ~150 KiB of JS bundle size.&lt;/p&gt;

&lt;p&gt;For each dependency, you should wonder:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do we use only a small part of the dependency ?&lt;/li&gt;
&lt;li&gt;Do we have the capacity to rewrite it in a reasonable time ?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the answer to both questions is &lt;em&gt;yes&lt;/em&gt;, it seems that rewriting code which meet the needs of the project (and only them) is a good idea.&lt;/p&gt;
&lt;h1&gt;
  
  
  5. Remove prop-types
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Valid for: React apps&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Cost: low&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Impact: High&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With React, defining prop-types enables validation of props passed to a component. Although it is really useful in development, prop-types are disabled in production (mostly for performance reasons).&lt;/p&gt;

&lt;p&gt;But their definition is still included in the produced bundle.&lt;/p&gt;

&lt;p&gt;The Babel plugin &lt;a href="https://github.com/oliviertassinari/babel-plugin-transform-react-remove-prop-types#readme" rel="noopener noreferrer"&gt;transform-react-remove-prop-types&lt;/a&gt; completely deletes prop-types definitions from the generated bundle. However, prop-types included by dependencies are not removed.&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;.babelrc&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;"production"&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;"plugins"&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;span class="s2"&gt;"transform-react-remove-prop-types"&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;"removeImport"&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="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;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;p&gt;&lt;strong&gt;Warning&lt;/strong&gt;: only activate this plugin in the production environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Target recent browsers
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Valid for: any web app&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Cost: low&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Impact: medium&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To include polyfills, you probably already use &lt;a href="https://github.com/zloirock/core-js" rel="noopener noreferrer"&gt;core-js&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/regenerator-runtime" rel="noopener noreferrer"&gt;regenerator-runtime&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;By default, all polyfills are included and core-js weights approximately 154KiB while regenerator-runtime is only 6.3KiB.&lt;/p&gt;

&lt;p&gt;By targeting only recent browsers, it is possible to reduce the size of included polyfills. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://babeljs.io/docs/en/babel-preset-env" rel="noopener noreferrer"&gt;Babel-preset-env&lt;/a&gt; has the ability to replace global imports of core-js by specific imports dependings on the targeted browsers.&lt;/p&gt;

&lt;p&gt;To configure the preset:&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;.babelrc&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"presets"&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;span class="s2"&gt;"@babel/preset-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;"useBuiltIns"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"entry"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"corejs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3.6"&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="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The version of core-js has to be provided.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;"useBuiltIns": "entry"&lt;/code&gt;, you only have to import these two dependencies once:&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="s1"&gt;regenerator-runtime/runtime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;core-js/stable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These two imports will be replaced by specific imports depending on the targeted browsers.&lt;/p&gt;

&lt;p&gt;To declare targeted browsers, the preset uses the &lt;a href="https://github.com/browserslist/browserslist" rel="noopener noreferrer"&gt;browserslist&lt;/a&gt; syntax.&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="nl"&gt;"browserslist"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"last 2 Chrome versions, last 2 Firefox versions, last 2 safari versions"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Hope this helps !&lt;/p&gt;

&lt;p&gt;Let me know if this is useful to you and how much bandwidth and client memory you saved&lt;/p&gt;

</description>
      <category>webpack</category>
      <category>react</category>
      <category>javascript</category>
      <category>performance</category>
    </item>
  </channel>
</rss>
