<?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: Wewake</title>
    <description>The latest articles on DEV Community by Wewake (@wewake-dev).</description>
    <link>https://dev.to/wewake-dev</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%2F1426726%2F1500bcaf-d3d5-4a2b-8038-7a8f54ae0764.jpeg</url>
      <title>DEV Community: Wewake</title>
      <link>https://dev.to/wewake-dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wewake-dev"/>
    <language>en</language>
    <item>
      <title>When JNI Meets 'Write Once, Run Anywhere': Navigating Java's Multi-Architecture Reality</title>
      <dc:creator>Wewake</dc:creator>
      <pubDate>Fri, 26 Dec 2025 14:59:57 +0000</pubDate>
      <link>https://dev.to/wewake-dev/when-jni-meets-write-once-run-anywhere-navigating-javas-multi-architecture-reality-23oi</link>
      <guid>https://dev.to/wewake-dev/when-jni-meets-write-once-run-anywhere-navigating-javas-multi-architecture-reality-23oi</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;
The "Write Once, Run Anywhere" Philosophy

&lt;ul&gt;
&lt;li&gt;The Problem It Solved&lt;/li&gt;
&lt;li&gt;Java's Brilliant Solution&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

The Exception: When Architecture Matters

&lt;ul&gt;
&lt;li&gt;Enter JNI: The Bridge to Native Code&lt;/li&gt;
&lt;li&gt;The Problem: Native Libraries Are Platform and Architecture-Specific&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

How Libraries Solve the Multi-Arch Problem

&lt;ul&gt;
&lt;li&gt;The "Bundle Everything" Pattern&lt;/li&gt;
&lt;li&gt;The "Platform/Architecture-Specific JAR" Pattern&lt;/li&gt;
&lt;li&gt;When to Use Each Pattern&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Conclusion

&lt;ul&gt;
&lt;li&gt;Further Reading&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

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

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;One of Java's most celebrated promises is &lt;strong&gt;"Write Once, Run Anywhere" (WORA)&lt;/strong&gt;. The idea is simple and powerful: write your code once, compile it, and run it on any platform—Windows, Linux, macOS, x86, ARM—without modification. This promise has made Java the language of choice for enterprise applications, Android development, and countless other use cases.&lt;/p&gt;

&lt;p&gt;For pure Java code, this promise holds beautifully. But there's a caveat.&lt;/p&gt;

&lt;p&gt;When you venture into the world of &lt;strong&gt;JNI (Java Native Interface)&lt;/strong&gt;, which is the bridge between Java and native code written in C, C++, or Rust—the cross-platform simplicity disappears. Suddenly, we need to worry about platform-specific binaries, and get treated with the cryptic &lt;code&gt;UnsatisfiedLinkError&lt;/code&gt; error messages.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How Java is normally platform-independent&lt;/li&gt;
&lt;li&gt;When and why that independence breaks down with JNI&lt;/li&gt;
&lt;li&gt;How modern libraries cleverly solve the multi-architecture challenge&lt;/li&gt;
&lt;li&gt;Peak under the hood of a production multi-architecture library&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The "Write Once, Run Anywhere" Philosophy
&lt;/h2&gt;

&lt;p&gt;Java's WORA promise isn't just marketing—it's a fundamental architectural decision that revolutionized software development in the mid-1990s.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem It Solved
&lt;/h3&gt;

&lt;p&gt;Before Java, cross-platform software required painful compromises:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Separate codebases&lt;/strong&gt; for each platform (Windows, Mac, Unix)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Abstraction layers&lt;/strong&gt; like POSIX, but still compile separately for each platform&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interpreted languages&lt;/strong&gt; like Perl or Python, which were slower and had limited ecosystem&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Java's Brilliant Solution
&lt;/h3&gt;

&lt;p&gt;Java introduced an intermediate layer: &lt;strong&gt;bytecode&lt;/strong&gt;. Instead of compiling directly to machine code, Java compiles to a universal, platform-neutral instruction set that can run on any machine with a JVM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Source Code (.java)  →  Bytecode (.class)  →  JVM (x86/ARM/etc)  →  Machine Code
   [Developer]           [Compiler]            [Runtime]              [CPU]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you compile Java code with &lt;code&gt;javac&lt;/code&gt;, it creates &lt;code&gt;.class&lt;/code&gt; files containing bytecode—universal instructions that aren't specific to x86, ARM, or any particular CPU architecture. These bytecode instructions (like &lt;code&gt;aload_0&lt;/code&gt;, &lt;code&gt;getstatic&lt;/code&gt;, &lt;code&gt;invokevirtual&lt;/code&gt;) are understood by the JVM, not directly by the hardware.&lt;/p&gt;

&lt;p&gt;The magic happens at runtime: each platform has its own JVM implementation (compiled for x86-linux, aarch64-darwin, etc.) that reads this universal bytecode and translates it to native machine code via Just-In-Time (JIT) compilation. The same &lt;code&gt;.jar&lt;/code&gt; (think of it as a zipped folder of .class files) file can run on Linux x86_64, macOS ARM64, or Windows x86_64 without any modification.&lt;/p&gt;

&lt;p&gt;This architecture provides  &lt;strong&gt;True portability&lt;/strong&gt;, since the same &lt;code&gt;.jar&lt;/code&gt; file runs everywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Exception: When Architecture Matters
&lt;/h2&gt;

&lt;p&gt;Now comes the interesting part: &lt;strong&gt;when does this beautiful abstraction break down?&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Enter JNI: The Bridge to Native Code
&lt;/h3&gt;

&lt;p&gt;JNI (Java Native Interface) allows Java code to call functions written in C, C++, Rust, or other languages that compile to native machine code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why would we want to do this?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Critical operations like cryptography are often faster in native code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hardware Access&lt;/strong&gt;: Low-level hardware operations that Java can't do&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Legacy Integration&lt;/strong&gt;: Calling existing C/C++ libraries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System APIs&lt;/strong&gt;: Accessing OS-specific features not exposed in Java&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;I feel it's important to mention that using JNI is not always beneficial. JNI calls incur an overhead. So, if JNI is invoked frequently, for low-work operations, it's not going to help reduce latency. We should only use it if the Java native operation is much slower. &lt;br&gt;
{:.prompt-info}&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The Problem: Native Libraries Are Platform and Architecture-Specific
&lt;/h3&gt;

&lt;p&gt;When you compile native code, you must compile it for each target platform (Windows, MacOS, Linux, etc) and target architecture (x86-64, ARM64, armv7, etc). &lt;/p&gt;

&lt;p&gt;We can run this simple test to explore this ourselves:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;% mvn dependency:get &lt;span class="nt"&gt;-Dartifact&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;org.xerial:sqlite-jdbc:3.44.1.0 &lt;span class="c"&gt;# Download sqlite jdbc jar from maven&lt;/span&gt;
% jar xf ~/.m2/repository/org/xerial/sqlite-jdbc/3.44.1.0/sqlite-jdbc-3.44.1.0.jar &lt;span class="c"&gt;# Extract its contents&lt;/span&gt;

% &lt;span class="c"&gt;# Checkout its target platform &amp;amp; architecture&lt;/span&gt;
% file native/Mac/x86_64/libsqlitejdbc.dylib
native/Mac/x86_64/libsqlitejdbc.dylib: Mach-O 64-bit dynamically linked shared library x86_64

% file native/Mac/aarch64/libsqlitejdbc.dylib
native/Mac/aarch64/libsqlitejdbc.dylib: Mach-O 64-bit dynamically linked shared library arm64

% file native/Windows/x86_64/sqlitejdbc.dll
native/Windows/x86_64/sqlitejdbc.dll: PE32+ executable &lt;span class="o"&gt;(&lt;/span&gt;DLL&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;console&lt;span class="o"&gt;)&lt;/span&gt; x86-64 &lt;span class="o"&gt;(&lt;/span&gt;stripped to external PDB&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;for &lt;/span&gt;MS Windows

% file native/Windows/x86/sqlitejdbc.dll
native/Windows/x86/sqlitejdbc.dll: PE32 executable &lt;span class="o"&gt;(&lt;/span&gt;DLL&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;console&lt;span class="o"&gt;)&lt;/span&gt; Intel 80386 &lt;span class="o"&gt;(&lt;/span&gt;stripped to external PDB&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;for &lt;/span&gt;MS Windows

% file native/Windows/armv7/sqlitejdbc.dll
native/Windows/armv7/sqlitejdbc.dll: PE32 executable &lt;span class="o"&gt;(&lt;/span&gt;DLL&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;GUI&lt;span class="o"&gt;)&lt;/span&gt; ARMv7 Thumb, &lt;span class="k"&gt;for &lt;/span&gt;MS Windows

% file native/Windows/aarch64/sqlitejdbc.dll
native/Windows/aarch64/sqlitejdbc.dll: PE32+ executable &lt;span class="o"&gt;(&lt;/span&gt;DLL&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;GUI&lt;span class="o"&gt;)&lt;/span&gt; Aarch64, &lt;span class="k"&gt;for &lt;/span&gt;MS Windows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The x86 &lt;code&gt;.so&lt;/code&gt; file won't work on ARM, and vice versa. The Linux &lt;code&gt;.so&lt;/code&gt; won't work on Windows. When you try it, you will get the famous &lt;code&gt;java.lang.UnsatisfiedLinkError&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The "Write Once, Run Anywhere" promise is broken, in a way.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Libraries Solve the Multi-Arch Problem
&lt;/h2&gt;

&lt;p&gt;Modern Java libraries that use JNI have developed clever patterns to maintain cross-platform compatibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Bundle Everything" Pattern
&lt;/h3&gt;

&lt;p&gt;The most common solution: &lt;strong&gt;include all native libraries for all platforms in a single JAR&lt;/strong&gt;. We saw this in the last section with &lt;code&gt;sqlite-jdbc&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;At runtime, the Java code detects the platform and extracts the appropriate native library:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Detect OS and architecture&lt;/strong&gt; from system properties&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extract the correct native library&lt;/strong&gt; from the JAR to a temporary location&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load the library&lt;/strong&gt; using &lt;code&gt;System.load()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean up&lt;/strong&gt; temporary files on JVM exit&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The JAR file is larger (containing multiple native libraries), but the developer experience is seamless.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Platform/Architecture-Specific JAR" Pattern
&lt;/h3&gt;

&lt;p&gt;An alternative approach: &lt;strong&gt;publish separate JARs for each platform&lt;/strong&gt;, and let the build tool select the right one at build time.&lt;/p&gt;

&lt;p&gt;Instead of one fat JAR containing all native libraries, libraries publish multiple artifacts:&lt;/p&gt;

&lt;p&gt;For instance, checkout &lt;code&gt;netty-tcnative&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;% curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://repo1.maven.org/maven2/io/netty/netty-tcnative/2.0.74.Final/ | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'netty-tcnative-[^"]*\.jar'&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;
netty-tcnative-2.0.74.Final-javadoc.jar
netty-tcnative-2.0.74.Final-linux-x86_64-fedora.jar
netty-tcnative-2.0.74.Final-linux-x86_64.jar
netty-tcnative-2.0.74.Final-osx-aarch_64.jar
netty-tcnative-2.0.74.Final-osx-x86_64.jar
netty-tcnative-2.0.74.Final-sources.jar
netty-tcnative-2.0.74.Final.jar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;One slight hiccup:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If we specify the platform manually in our &lt;code&gt;pom.xml&lt;/code&gt;, it becomes platform-specific:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- BAD: Hard-coded platform --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;io.netty&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;netty-tcnative&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;2.0.74.Final&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;classifier&amp;gt;&lt;/span&gt;linux-x86_64&lt;span class="nt"&gt;&amp;lt;/classifier&amp;gt;&lt;/span&gt;  &lt;span class="c"&gt;&amp;lt;!-- Won't work on macOS! --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our &lt;code&gt;pom.xml&lt;/code&gt; now only works on Linux x86_64. Developers on macOS can't build, and we can't deploy to ARM servers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution: Maven's os-maven-plugin&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/trustin/os-maven-plugin" rel="noopener noreferrer"&gt;os-maven-plugin&lt;/a&gt; automatically detects your build platform and selects the correct JAR:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Add the plugin --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;build&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;extensions&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;extension&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;kr.motd.maven&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;os-maven-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.7.1&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/extension&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/extensions&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/build&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Use auto-detected classifier --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;io.netty&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;netty-tcnative&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;2.0.74.Final&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;classifier&amp;gt;&lt;/span&gt;${os.detected.classifier}&lt;span class="nt"&gt;&amp;lt;/classifier&amp;gt;&lt;/span&gt;  &lt;span class="c"&gt;&amp;lt;!-- Auto-detected! --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The plugin sets &lt;code&gt;${os.detected.classifier}&lt;/code&gt; based on your build environment. This way, the same &lt;code&gt;pom.xml&lt;/code&gt; works on every developer's machine and in every CI/CD environment!&lt;/p&gt;

&lt;h3&gt;
  
  
  When to Use Each Pattern
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Use "Bundle Everything" when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Distributing desktop applications to unknown end-users&lt;/li&gt;
&lt;li&gt;We want a single universal artifact that works everywhere&lt;/li&gt;
&lt;li&gt;We deploy the same JAR to multiple different architectures&lt;/li&gt;
&lt;li&gt;Simplicity is more important than JAR size&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use "Platform-Specific JARs" when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building server applications deployed to known platforms&lt;/li&gt;
&lt;li&gt;Using containerization (each container image is already platform-specific)&lt;/li&gt;
&lt;li&gt;JAR size matters (e.g., AWS Lambda cold start times)&lt;/li&gt;
&lt;li&gt;We have a consistent CI/CD pipeline per architecture&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Java's "Write Once, Run Anywhere" promise isn't a myth, it just comes with a practical asterisk when we venture into the native code territory. But with the patterns we've explored, modern Java libraries have found elegant ways to maintain cross-platform compatibility even when using architecture-specific native code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Further Reading
&lt;/h3&gt;

&lt;p&gt;The Java ecosystem continues to evolve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://openjdk.org/projects/panama/" rel="noopener noreferrer"&gt;Project Panama&lt;/a&gt;&lt;/strong&gt; (Foreign Function &amp;amp; Memory API): Aims to replace JNI with a safer, simpler API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.graalvm.org/latest/reference-manual/native-image/" rel="noopener noreferrer"&gt;GraalVM Native Image&lt;/a&gt;&lt;/strong&gt;: Compiles Java to native binaries, changing the paradigm entirely&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved JIT compilation&lt;/strong&gt;: Narrowing the performance gap between Java and native code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Despite these advances, understanding JNI and multi-architecture challenges remains crucial for Java developers working with high-performance applications, legacy integrations, or specialized hardware.&lt;/p&gt;

&lt;p&gt;If you liked this article, you might like my other article on &lt;a href="https://wewake.dev/posts/simplifying-libraries-part-1/" rel="noopener noreferrer"&gt;Simplifying the complicated world of Libraries &lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.oracle.com/en/java/javase/17/docs/specs/jni/index.html" rel="noopener noreferrer"&gt;Java Native Interface Specification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/netty/netty-tcnative" rel="noopener noreferrer"&gt;Netty TCNative GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/trustin/os-maven-plugin" rel="noopener noreferrer"&gt;os-maven-plugin GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://maven.apache.org/pom.html#dependencies" rel="noopener noreferrer"&gt;Maven Classifier Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://openjdk.org/projects/panama/" rel="noopener noreferrer"&gt;Project Panama: Foreign Function &amp;amp; Memory API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/xerial/sqlite-jdbc" rel="noopener noreferrer"&gt;SQLite JDBC Driver&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.android.com/training/articles/perf-jni" rel="noopener noreferrer"&gt;JNI Best Practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.oracle.com/javase/specs/jvms/se17/html/index.html" rel="noopener noreferrer"&gt;Understanding Java Bytecode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wewake.dev/posts/simplifying-libraries-part-1/" rel="noopener noreferrer"&gt;Simplifying the complicated world of Libraries &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article was originally published on my blog at &lt;a href="https://wewake.dev/posts/when-jni-meets-write-once-run-anywhere-in-multi-arch-world/" rel="noopener noreferrer"&gt;https://wewake.dev/posts/when-jni-meets-write-once-run-anywhere-in-multi-arch-world/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Find more of my content on my blog, where I share my software development experiences and learnings: &lt;a href="https://wewake.dev" rel="noopener noreferrer"&gt;https://wewake.dev&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>jni</category>
      <category>architecture</category>
      <category>performance</category>
    </item>
    <item>
      <title>Why Your Python Logs Vanish in Docker (and How PYTHONUNBUFFERED=1 Saves the Day)</title>
      <dc:creator>Wewake</dc:creator>
      <pubDate>Fri, 26 Dec 2025 14:55:04 +0000</pubDate>
      <link>https://dev.to/wewake-dev/why-your-python-logs-vanish-in-docker-and-how-pythonunbuffered1-saves-the-day-65i</link>
      <guid>https://dev.to/wewake-dev/why-your-python-logs-vanish-in-docker-and-how-pythonunbuffered1-saves-the-day-65i</guid>
      <description>&lt;ul&gt;
&lt;li&gt;The Mystery: Why are my logs disappearing ?&lt;/li&gt;
&lt;li&gt;
What is Output Buffering?

&lt;ul&gt;
&lt;li&gt;Why Buffering Exists ?&lt;/li&gt;
&lt;li&gt;The Three Types of Buffering&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Why Docker Makes This Worse&lt;/li&gt;

&lt;li&gt;The Solution: PYTHONUNBUFFERED=1&lt;/li&gt;

&lt;li&gt;

Alternative Solutions

&lt;ul&gt;
&lt;li&gt;Use python unbuffered commandline option&lt;/li&gt;
&lt;li&gt;Flush Manually&lt;/li&gt;
&lt;li&gt;Use stderr in Python's logging module&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

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

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

&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Mystery: Why are my logs disappearing ?
&lt;/h2&gt;

&lt;p&gt;This has unfortunately happened almost every time I have come back to using python in my little side projects, or experiments.&lt;/p&gt;

&lt;p&gt;I create a neat little Python app. It runs perfectly, printing helpful logs at every step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app.py
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Starting application...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Connecting to database...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Processing request...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;All done!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I run it locally:&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="nv"&gt;$ &lt;/span&gt;python app.py
Starting application...
Connecting to database...
Processing request...
All &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All good! I containerize it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.12-slim&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; app.py .&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["python", "app.py"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Build and run it in Docker:&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="nv"&gt;$ &lt;/span&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; myapp &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;docker run myapp
&lt;span class="nv"&gt;$ &lt;/span&gt;docker logs &amp;lt;container-id&amp;gt;
&lt;span class="c"&gt;# &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the logs are nowhere to be seen. Where did it go ? If running k8, I check &lt;code&gt;kubectl logs&lt;/code&gt; , same thing. No logs.&lt;/p&gt;

&lt;p&gt;The logs, like a magician's trick, have vanished into thin air. What sorcery is this?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spoiler&lt;/strong&gt;: It's Python's output buffering, and it's been frustrating developers since Docker became popular.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Output Buffering?
&lt;/h2&gt;

&lt;p&gt;Output buffering is when your program doesn't immediately write output to its destination (like your terminal or Docker logs). Instead, it collects output in a temporary buffer (a chunk of memory) and writes it all at once.&lt;/p&gt;

&lt;p&gt;Think of it like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Without buffering&lt;/strong&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;Your code] &lt;span class="nt"&gt;---&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Hello"&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Terminal]
            &lt;span class="nt"&gt;---&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"World"&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Terminal]
            &lt;span class="nt"&gt;---&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"!!!"&lt;/span&gt;    &lt;span class="nt"&gt;---&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Terminal]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;With buffering&lt;/strong&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;Your code] &lt;span class="nt"&gt;---&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Hello"&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
            &lt;span class="nt"&gt;---&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"World"&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;--&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Buffer]---&amp;gt; &lt;span class="o"&gt;[&lt;/span&gt;Terminal] &lt;span class="o"&gt;(&lt;/span&gt;when full or flushed&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="nt"&gt;---&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"!!!"&lt;/span&gt;   &lt;span class="nt"&gt;--&lt;/span&gt;/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why Buffering Exists ?
&lt;/h3&gt;

&lt;p&gt;Buffering is a performance optimization. Writing to output (terminal, files, network) is &lt;strong&gt;slow&lt;/strong&gt; compared to memory operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Three Types of Buffering
&lt;/h3&gt;

&lt;p&gt;Python (and most languages) uses three buffering modes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Unbuffered&lt;/strong&gt;: Write immediately (no buffer)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Used for: stderr by default&lt;/li&gt;
&lt;li&gt;Behavior: Every &lt;code&gt;print()&lt;/code&gt; appears instantly&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line-buffered&lt;/strong&gt;: Write after each newline (&lt;code&gt;\n&lt;/code&gt;)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Used for: stdout &lt;strong&gt;when connected to a terminal&lt;/strong&gt; (TTY)&lt;/li&gt;
&lt;li&gt;Behavior: Output appears after each line&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Block-buffered&lt;/strong&gt;: Write when buffer is full (default: 8KB)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Used for: stdout &lt;strong&gt;when NOT connected to a terminal&lt;/strong&gt; (pipes, files, Docker)&lt;/li&gt;
&lt;li&gt;Behavior: Output appears in chunks, or when program exits&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Python detects if stdout is connected to a terminal. If yes, it line-buffers. If no (like in Docker), it block-buffers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Want to see the actual buffer size?&lt;/strong&gt; You can check it yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Default buffer size: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DEFAULT_BUFFER_SIZE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; bytes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Output: Default buffer size: 8192 bytes
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;io.DEFAULT_BUFFER_SIZE&lt;/code&gt; constant (defined in &lt;a href="https://docs.python.org/3/library/io.html#io.DEFAULT_BUFFER_SIZE" rel="noopener noreferrer"&gt;Python's io module&lt;/a&gt;) is what Python uses for block-buffering. It's typically 8192 bytes (8KB), though it can vary based on the system's block size.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Docker Makes This Worse
&lt;/h2&gt;

&lt;p&gt;When you run Python in a Docker container:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;stdout is NOT a TTY&lt;/strong&gt; (it's a pipe to Docker's logging driver)&lt;/li&gt;
&lt;li&gt;Python switches to &lt;strong&gt;block-buffering&lt;/strong&gt; (8KB buffer by default)&lt;/li&gt;
&lt;li&gt;The logs sit in memory until:

&lt;ul&gt;
&lt;li&gt;The buffer fills up, OR&lt;/li&gt;
&lt;li&gt;The program exits, OR&lt;/li&gt;
&lt;li&gt;You explicitly flush&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It's a classic case of "works on my machine" syndrome—because your machine &lt;em&gt;is&lt;/em&gt; a TTY!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: PYTHONUNBUFFERED=1
&lt;/h2&gt;

&lt;p&gt;Set the &lt;code&gt;PYTHONUNBUFFERED&lt;/code&gt; environment variable to any non-empty value. This forces Python to use unbuffered mode for stdout and stderr.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In Dockerfile&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.12-slim&lt;/span&gt;

&lt;span class="c"&gt;# Add this line!&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; PYTHONUNBUFFERED=1&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; app.py .&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["python", "app.py"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In docker-compose.yml&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;PYTHONUNBUFFERED=1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In Kubernetes deployment&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python-app&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;myapp:latest&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PYTHONUNBUFFERED&lt;/span&gt;
          &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;At runtime&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;PYTHONUNBUFFERED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 myapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our logs will appear instantly:&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="nv"&gt;$ &lt;/span&gt;docker logs myapp
Starting application...
Connecting to database...
Processing request...
All &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Fun fact&lt;/strong&gt;: The value doesn't matter. &lt;code&gt;PYTHONUNBUFFERED=1&lt;/code&gt;, &lt;code&gt;PYTHONUNBUFFERED=true&lt;/code&gt;, even &lt;code&gt;PYTHONUNBUFFERED=banana&lt;/code&gt; all work. Python just checks if the variable is set and non-empty.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Alternative Solutions
&lt;/h2&gt;

&lt;p&gt;While &lt;code&gt;PYTHONUNBUFFERED=1&lt;/code&gt; is the easiest fix, here are other approaches:&lt;/p&gt;

&lt;h3&gt;
  
  
  Use python unbuffered commandline option
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;-u&lt;/code&gt; flag forces unbuffered mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.12-slim&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; app.py .&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["python", "-u", "app.py"]  # Note the -u flag&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is equivalent to &lt;code&gt;PYTHONUNBUFFERED=1&lt;/code&gt;, just more explicit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;: No environment variable needed&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Cons&lt;/strong&gt;: Have to remember to add &lt;code&gt;-u&lt;/code&gt; everywhere you run Python&lt;/p&gt;
&lt;h3&gt;
  
  
  Flush Manually
&lt;/h3&gt;

&lt;p&gt;Call &lt;code&gt;flush()&lt;/code&gt; explicitly when you want output to appear:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Critical log message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Appears immediately
&lt;/span&gt;
&lt;span class="c1"&gt;# Or flush everything:
&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;: Fine-grained control over when to flush&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Cons&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy to forget&lt;/li&gt;
&lt;li&gt;Clutters your code&lt;/li&gt;
&lt;li&gt;Doesn't help with third-party libraries that use &lt;code&gt;print()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Use stderr in Python's logging module
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;stderr&lt;/code&gt; is unbuffered by default.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;

&lt;span class="c1"&gt;# Configure logging to stderr (which is unbuffered by default)
&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;%(asctime)s - %(levelname)s - %(message)s&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;  &lt;span class="c1"&gt;# stderr is unbuffered!
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Application starting&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Connected to database&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Something went wrong!&lt;/span&gt;&lt;span class="sh"&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;strong&gt;Why this works&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;stderr&lt;/code&gt; is &lt;strong&gt;unbuffered by default&lt;/strong&gt; (even in Docker)&lt;/li&gt;
&lt;li&gt;Structured logging is better for production anyway&lt;/li&gt;
&lt;li&gt;You get timestamps, log levels, and better formatting&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;The &lt;code&gt;PYTHONUNBUFFERED=1&lt;/code&gt; environment variable is a tiny fix that solves a huge headache. It forces Python to stop buffering output, so your logs appear immediately in Docker and Kubernetes.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/io.html#io.DEFAULT_BUFFER_SIZE" rel="noopener noreferrer"&gt;Python io Module Documentation (DEFAULT_BUFFER_SIZE)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/using/cmdline.html#cmdoption-u" rel="noopener noreferrer"&gt;Python Documentation: &lt;code&gt;-u&lt;/code&gt; flag&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/io.html#text-i-o" rel="noopener noreferrer"&gt;Python io Module: Text I/O Buffering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/howto/logging.html" rel="noopener noreferrer"&gt;Python Logging HOWTO&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/sys.html#sys.stdout" rel="noopener noreferrer"&gt;Python sys.stdout Buffering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linusakesson.net/programming/tty/" rel="noopener noreferrer"&gt;The TTY Demystified&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article was originally published on my blog at &lt;a href="https://wewake.dev/posts/why-your-python-logs-vanish-in-docker-pythonunbuffered-explained/" rel="noopener noreferrer"&gt;https://wewake.dev/posts/why-your-python-logs-vanish-in-docker-pythonunbuffered-explained/&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;Find more of my content on my blog, where I share my software development experiences and learnings: &lt;a href="https://wewake.dev" rel="noopener noreferrer"&gt;https://wewake.dev&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>docker</category>
      <category>containers</category>
      <category>pythonunbuffered</category>
    </item>
    <item>
      <title>Impress Recruiters and Upskill using these 10 Unconventional Software Engineering Projects</title>
      <dc:creator>Wewake</dc:creator>
      <pubDate>Sun, 05 May 2024 21:36:22 +0000</pubDate>
      <link>https://dev.to/wewake-dev/impress-recruiters-and-upskill-using-these-10-unconventional-software-engineering-projects-4mpo</link>
      <guid>https://dev.to/wewake-dev/impress-recruiters-and-upskill-using-these-10-unconventional-software-engineering-projects-4mpo</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;It's a tough market out there, and the ability to stand out is very important. Most (if not all) resumes for software engineering roles contain several projects. But most of them are generic clones that all recruiters (and even interviewers) have seen hundreds of times. Such projects may well help you to fill up that resume, but they don't really add much of a value.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to come up with a project idea
&lt;/h2&gt;

&lt;p&gt;This may seem like a daunting task, but it is also incredibly rewarding. Some of my tips:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Identify your interests and strengths&lt;/strong&gt;: Start by identifying your interests and strengths in software engineering. What technical or programming language do you like? What skills are you good at?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Research Current Products and Technologies Research&lt;/strong&gt;: Keep up to date with current products and technologies in software technology. Look for emerging technologies like AI, blockchain, or AR/VR, that have the potential to disrupt industries or solve complex problems. Choosing such technology can set your project apart and reflect your forward-thinking approach.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Think unique solutions to common problems&lt;/strong&gt;: Think outside the box and come up with unique solutions to common problems. Consider how you can use technology to automate tasks, improve productivity, or enhance the user experience in new and innovative ways.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seek feedback and validation&lt;/strong&gt;: Once you have a few ideas in mind, ask for feedback from classmates, mentors, or industry professionals. Their feedback can help you refine your idea and choose the most promising one for your project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be open to iterative development&lt;/strong&gt;: Be open to iteration and refinement, and be willing to adapt if necessary. The final project may look different from your initial idea, but as long as it aligns with your goals and showcases your skills, it can be a successful and impactful project&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  List of Ideas
&lt;/h2&gt;

&lt;p&gt;The following curated list contains more uncommon projects, that take a bit more time and effort to create. Naturally, if you have such projects in your resume, the chances of getting selected for the interviews is much higher. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Resume Website&lt;/strong&gt;: Create a dynamic website that showcases your skills, experience, and services using HTML, CSS, and JavaScript. Include interactive features like animations and infographics to keep visitors engaged.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Virtual Reality (VR) Portfolio&lt;/strong&gt;: Create a VR experience that showcases your projects and accomplishments. Use frameworks like A-Frame or Unity to create an immersive environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI-Powered Personal Chatbot&lt;/strong&gt;: Build a chatbot that can answer common questions about your industry, skills and experiences. Use natural language processing (NLP) and machine learning to improve its responsiveness over time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gesture-driven web applications&lt;/strong&gt;: Create web applications that can be operated via gestures. Use libraries like TensorFlow.js or OpenCV.js for gesture recognition.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Augmented Reality (AR) Visualization Tools&lt;/strong&gt;: Visualize an AR application that visualizes complex data or concepts. Use AR.js or Unity AR Foundation to create interactive AR experiences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blockchain-based credential verification system&lt;/strong&gt;: Develop a system that uses blockchain technology to verify credentials and certificates. Use smart contracts to manage the verification process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time code collaboration platform&lt;/strong&gt;: Create a platform that allows multiple developers to collaborate on code in real time. Use WebSockets for real-time communication with code editors like Monaco Editor or CodeMirror.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Voice-Controlled Task Manager&lt;/strong&gt;: Create a task management application that can be operated using voice commands. Use a speech recognition API such as Web Speech API or Google Cloud Speech-to-Text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated Code Review Tool&lt;/strong&gt;: Create a tool that automatically reviews code to look for common problems and suggest improvements. Use static code analysis tools such as ESLint or SonarQube.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Artificial Intelligence Art Generator&lt;/strong&gt;: Develop an AI-powered tool that generates unique pieces of art based on user inputs such as colors, styles, and themes. This project demonstrates your ability to create innovative and artistic applications of AI.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;While it's important to have come up with, and worked on unconventional projects to showcase and set you apart, it's equally important to be able to replicate the design, reason and defend the design and technology choices &amp;amp; trade offs, during interviews. When explained and defended well, it leaves a positive impression on the interviewer, and highly increases the chances of selection.&lt;/p&gt;




&lt;p&gt;If you like this, I write and publish technical content on &lt;a href="https://wewake.dev" rel="noopener noreferrer"&gt;my personal blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>interview</category>
      <category>resume</category>
      <category>coding</category>
    </item>
    <item>
      <title>Practical and Beginner friendly guide for speeding up your web-apps</title>
      <dc:creator>Wewake</dc:creator>
      <pubDate>Wed, 01 May 2024 15:07:34 +0000</pubDate>
      <link>https://dev.to/wewake-dev/practical-and-beginner-friendly-guide-for-speeding-up-your-web-apps-using-webpack-ho0</link>
      <guid>https://dev.to/wewake-dev/practical-and-beginner-friendly-guide-for-speeding-up-your-web-apps-using-webpack-ho0</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Setup&lt;/li&gt;
&lt;li&gt;Starting State&lt;/li&gt;
&lt;li&gt;Tree Shaking&lt;/li&gt;
&lt;li&gt;Minification&lt;/li&gt;
&lt;li&gt;Use only what is needed&lt;/li&gt;
&lt;li&gt;Code Splitting &lt;/li&gt;
&lt;li&gt;Lazy loading&lt;/li&gt;
&lt;li&gt;Production mode&lt;/li&gt;
&lt;li&gt;Compression&lt;/li&gt;
&lt;li&gt;Other options&lt;/li&gt;
&lt;li&gt;Bundle analyzer&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;li&gt;References&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In modern web development, all webpage assets like &lt;code&gt;html&lt;/code&gt;, &lt;code&gt;css&lt;/code&gt;, &lt;code&gt;js&lt;/code&gt;, etc are bundled together into a smaller set of assets. This helps in reducing network calls from the client/user agent, and gives a much smaller file to download. This in turn gives a fast and efficient user experience, which is what we all want. &lt;/p&gt;

&lt;p&gt;There are various tools available that manage the size of bundled assets. We are going to use the example of a popular and widely used bundler named &lt;a href="https://webpack.js.org/" rel="noopener noreferrer"&gt;Webpack&lt;/a&gt;, and practically look at many of the optimization techniques it offers.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;Let's start with a basic node + react setup. It's okay if you don't have expertise in this. Ensure you have &lt;code&gt;node&lt;/code&gt; and &lt;code&gt;npm&lt;/code&gt;  and &lt;code&gt;npx&lt;/code&gt; installed.&lt;/p&gt;

&lt;p&gt;We are using &lt;code&gt;webpack5&lt;/code&gt;, but the concepts are more or less transferable across versions with minor modifications.&lt;/p&gt;

&lt;p&gt;My &lt;code&gt;node&lt;/code&gt; and &lt;code&gt;npm&lt;/code&gt; version details:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;webpack-optimization-demo % node &lt;span class="nt"&gt;--version&lt;/span&gt;
v20.11.1
webpack-optimization-demo % npm &lt;span class="nt"&gt;--version&lt;/span&gt;
10.2.4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;You can get the initial code from &lt;a href="https://github.com/viv1/blog-code-examples/tree/main/webpack-optimization-demo" rel="noopener noreferrer"&gt;repo&lt;/a&gt;. Follow these steps:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;git clone git@github.com:viv1/blog-code-examples.git&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git checkout dab817ec0a502adff4c82070c58ee36bb79e7bc0&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cd blog-code-examples/webpack-optimization-demo&lt;/code&gt; , then run &lt;code&gt;npm install .&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;You can go directly to section Starting State.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you would like to do it from scratch, follow along:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let's initiate a node project:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;webpack-optimization-demo
&lt;span class="nb"&gt;cd &lt;/span&gt;webpack-optimization-demo
npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Install libraries and dependencies:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; webpack webpack-cli webpack-dev-server style-loader css-loader babel-loader @babel/core @babel/preset-env @babel/preset-react html-webpack-plugin
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save&lt;/span&gt; prop-types process lodash react react-dom webpack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create the following files in this directory structure:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a simple single page app with 2 components. &lt;br&gt;
&lt;code&gt;App.js&lt;/code&gt; is cretaed using &lt;code&gt;Component1&lt;/code&gt; and a &lt;code&gt;Component2&lt;/code&gt;. &lt;code&gt;Component1&lt;/code&gt;  and &lt;code&gt;Component2&lt;/code&gt; are simple text displays. &lt;code&gt;Component1&lt;/code&gt; is shown by default with a button.&lt;br&gt;
When button is clicked, it displays &lt;code&gt;Component2&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;unUsedComponent&lt;/code&gt; is not really used anywhere.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;- src
    - components
        - Component1.js
        - Component2.js
        - unUsedComponent.js
    - App.js
    - index.html
    - index.js
- webpack.config.js
- package.json
- package.lock.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Component1.js&lt;/strong&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&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="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&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;prop-types&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;_&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="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Component1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;C&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;o&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;m&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;p&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;o&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;e&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;t&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;Component1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;propTypes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;number&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;Component1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Component2.js&lt;/strong&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&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="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Component2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&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;Component2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;unUsedComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Using-unUsedComponent&lt;/span&gt;&lt;span class="dl"&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;unUsedComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;unUsedComponent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;index.html&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Webpack Optimization&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;App.js&lt;/strong&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="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;useState&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="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Component1&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/Component1&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;Component2&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/Component2&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;unUsedComponent&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/UnUsedComponent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;showComponent2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setShowComponent2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setShowComponent2&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Component1&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Load&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;showComponent2&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Suspense&lt;/span&gt; &lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Loading&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;}&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Component2&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/React.Suspense&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="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;strong&gt;index.js&lt;/strong&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&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="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&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-dom&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;App&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;./App&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&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;&lt;strong&gt;webpack.config.js&lt;/strong&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;path&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="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;HtmlWebpackPlugin&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="s1"&gt;html-webpack-plugin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;webpack&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="s1"&gt;webpack&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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="s1"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;main&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;import&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/index.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;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;js|jsx&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;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="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;babel-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;presets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/preset-env&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/preset-react&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;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;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HtmlWebpackPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/index.html&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;// fix "process is not defined" error:&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;webpack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ProvidePlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;process&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;process/browser&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;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting State
&lt;/h2&gt;

&lt;p&gt;Let's first build the assets and see if our starting set is all good.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;npx webpack&lt;/code&gt; to build the assets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;webpack-optimization-demo % npx webpack
asset main.js 1.8 MiB [compared for emit] (name: main)
asset index.html 201 bytes [compared for emit]
runtime modules 1.25 KiB 6 modules
modules by path ./node_modules/ 1.78 MiB
  modules by path ./node_modules/prop-types/ 28.6 KiB 6 modules
  modules by path ./node_modules/react/ 92.5 KiB 3 modules
  modules by path ./node_modules/react-dom/ 1.11 MiB 3 modules
  modules by path ./node_modules/scheduler/ 21.4 KiB 3 modules
  modules by path ./node_modules/react-is/ 9.5 KiB 3 modules
  + 3 modules
modules by path ./src/ 3.27 KiB
  modules by path ./src/components/*.js 710 bytes
    ./src/components/Component1.js 342 bytes [built] [code generated]
    + 2 modules
  modules by path ./src/*.js 2.58 KiB
    ./src/index.js 181 bytes [built] [code generated]
    ./src/App.js 2.4 KiB [built] [code generated]
webpack 5.91.0 compiled successfully in 743 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the bundle size as &lt;code&gt;1.8MiB&lt;/code&gt; (Your bundle sizes might be slightly different)&lt;/p&gt;

&lt;p&gt;Let's also see how our page looks:&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;npx http-server -p 8000&lt;/code&gt;. Now, open your web browser, and open developer tools. Go to Network tab.&lt;/p&gt;

&lt;p&gt;Now load &lt;code&gt;http://localhost:8000/dist&lt;/code&gt; on your web browser. Your page should look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3x1ea1neuh9ikkka6z8y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3x1ea1neuh9ikkka6z8y.png" alt="Expected Original UI" width="180" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your network tab:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbdggbvtlf011pnnm7nqa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbdggbvtlf011pnnm7nqa.png" alt="Expected Network Tab" width="779" height="49"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we click on button for &lt;code&gt;Loading Component 2&lt;/code&gt;, we see that no new network call was made even though &lt;code&gt;Component 2&lt;/code&gt; was loaded. &lt;/p&gt;

&lt;p&gt;Now that our starting point is all good, we are going to look into how we can optimize this code.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;At any point, feel free to complete delete the &lt;code&gt;dist&lt;/code&gt; folder since it gets generated automatically when &lt;code&gt;npx webpack&lt;/code&gt; is run.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Tree Shaking
&lt;/h2&gt;

&lt;p&gt;Let's start with [Tree Shaking]{&lt;a href="https://webpack.js.org/guides/tree-shaking/" rel="noopener noreferrer"&gt;https://webpack.js.org/guides/tree-shaking/&lt;/a&gt;}.&lt;br&gt;
It's a method to remove any unused modules.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;unUsedComponent&lt;/code&gt; is not really used in the display. However, it is still present in the code:&lt;/p&gt;

&lt;p&gt;If we go to dist/main.js. Search for &lt;code&gt;Using-unUsedComponent&lt;/code&gt;, we see that it is present.&lt;/p&gt;

&lt;p&gt;Let's start fixing this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add this in webpack.config.js under &lt;code&gt;modules.exports&lt;/code&gt; and then run &lt;code&gt;npx webpack&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;optimization: {
    usedExports: true,
  },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;webpack-optimization-demo2 % npx webpack
asset main.js 1.79 MiB [emitted] (name: main)
asset index.html 201 bytes [compared for emit]
runtime modules 1010 bytes 5 modules
modules by path ./node_modules/ 1.78 MiB
  modules by path ./node_modules/prop-types/ 28.6 KiB 6 modules
  modules by path ./node_modules/react/ 92.5 KiB 3 modules
  modules by path ./node_modules/react-dom/ 1.11 MiB 3 modules
  modules by path ./node_modules/scheduler/ 21.4 KiB 3 modules
  modules by path ./node_modules/react-is/ 9.5 KiB 3 modules
  + 3 modules
modules by path ./src/ 3.27 KiB
  modules by path ./src/components/*.js 710 bytes
    ./src/components/Component1.js 342 bytes [built] [code generated]
    + 2 modules
  modules by path ./src/*.js 2.58 KiB
    ./src/index.js 181 bytes [built] [code generated]
    ./src/App.js 2.4 KiB [built] [code generated]
webpack 5.91.0 compiled successfully in 735 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Not much change in file size. However, if we go to dist/main.js. Search for &lt;code&gt;unUsedComponent&lt;/code&gt;, we see it is &lt;strong&gt;NOT&lt;/strong&gt; present.&lt;/p&gt;

&lt;p&gt;Just like that, we have removed an unused component we created.  &lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Minification
&lt;/h2&gt;

&lt;p&gt;Next, we will do some minification. Minification is a process to reduce the total size of file contents by removing characters and parts which are deemed useless for machines. &lt;br&gt;
FOr example, spaces in codes are simply a way for them to be readable by humans. However, from machine point of view,  these are harmless. Minification helps remove these additional spaces among other things. Let's use an external plugin to help minify further.&lt;/p&gt;

&lt;p&gt;We will install a minimizer plugin::&lt;br&gt;
&lt;code&gt;npm install --save-dev terser-webpack-plugin&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now, add this in webpack.config.js under &lt;code&gt;modules.exports&lt;/code&gt; and then run &lt;code&gt;npx webpack&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
  // ... other config
  optimization: {
    // ...
    minimize: true,
    minimizer: [new TerserPlugin()],
  },
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;webpack-optimization-demo % npx webpack
asset main.js 520 KiB &lt;span class="o"&gt;[&lt;/span&gt;emitted] &lt;span class="o"&gt;[&lt;/span&gt;minimized] &lt;span class="o"&gt;(&lt;/span&gt;name: main&lt;span class="o"&gt;)&lt;/span&gt; 1 related asset
asset index.html 201 bytes &lt;span class="o"&gt;[&lt;/span&gt;compared &lt;span class="k"&gt;for &lt;/span&gt;emit]
runtime modules 1010 bytes 5 modules
modules by path ./node_modules/ 1.78 MiB
  modules by path ./node_modules/prop-types/ 28.6 KiB 6 modules
  modules by path ./node_modules/react/ 92.5 KiB 3 modules
  modules by path ./node_modules/react-dom/ 1.11 MiB 3 modules
  modules by path ./node_modules/scheduler/ 21.4 KiB 3 modules
  modules by path ./node_modules/react-is/ 9.5 KiB 3 modules
  + 3 modules
modules by path ./src/ 3.27 KiB
  modules by path ./src/components/&lt;span class="k"&gt;*&lt;/span&gt;.js 710 bytes
    ./src/components/Component1.js 342 bytes &lt;span class="o"&gt;[&lt;/span&gt;built] &lt;span class="o"&gt;[&lt;/span&gt;code generated]
    + 2 modules
  modules by path ./src/&lt;span class="k"&gt;*&lt;/span&gt;.js 2.58 KiB
    ./src/index.js 181 bytes &lt;span class="o"&gt;[&lt;/span&gt;built] &lt;span class="o"&gt;[&lt;/span&gt;code generated]
    ./src/App.js 2.4 KiB &lt;span class="o"&gt;[&lt;/span&gt;built] &lt;span class="o"&gt;[&lt;/span&gt;code generated]
webpack 5.91.0 compiled successfully &lt;span class="k"&gt;in &lt;/span&gt;3011 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the reduction in file size. From &lt;code&gt;1.79MiB&lt;/code&gt; to &lt;code&gt;520KiB&lt;/code&gt;. Around &lt;strong&gt;&lt;code&gt;70% savings&lt;/code&gt;&lt;/strong&gt; in size.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Use only what is needed
&lt;/h2&gt;

&lt;p&gt;Notice that in &lt;code&gt;Component1.js&lt;/code&gt;, we only use join but we are instead importing the whole &lt;code&gt;lodash&lt;/code&gt; library.&lt;br&gt;
&lt;code&gt;lodash&lt;/code&gt; has split each function in their own library file, so we can just download &lt;code&gt;lodash/join&lt;/code&gt; instead of the whole things.&lt;/p&gt;

&lt;p&gt;Make the following code change in &lt;code&gt;Component1.js&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Component1.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ...
import join from 'lodash/join';
// ...
let x = join(['C', 'o', 'm', 'p', 'o', 'n', 'e', 'n', 't', ' 1'], '');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then run &lt;code&gt;npx webpack&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;webpack-optimization-demo % npx webpack
asset main.js 451 KiB [emitted] [minimized] (name: main) 1 related asset
asset index.html 201 bytes [compared for emit]
runtime modules 786 bytes 4 modules
modules by path ./node_modules/ 1.27 MiB
  modules by path ./node_modules/prop-types/ 28.6 KiB 6 modules
  modules by path ./node_modules/react/ 92.5 KiB 3 modules
  modules by path ./node_modules/react-dom/ 1.11 MiB 3 modules
  modules by path ./node_modules/scheduler/ 21.4 KiB 3 modules
  modules by path ./node_modules/react-is/ 9.5 KiB 3 modules
  + 3 modules
modules by path ./src/ 3.34 KiB
  modules by path ./src/components/*.js 779 bytes
    ./src/components/Component1.js 411 bytes [built] [code generated]
    + 2 modules
  modules by path ./src/*.js 2.58 KiB
    ./src/index.js 181 bytes [built] [code generated]
    ./src/App.js 2.4 KiB [built] [code generated]
webpack 5.91.0 compiled successfully in 2543 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the further reduction is asset size.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Splitting
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://webpack.js.org/guides/code-splitting/" rel="noopener noreferrer"&gt;Code Splitting&lt;/a&gt; is a way to split the bundled asset into multiple bundled assets, which can be loaded on demand, or in parallel. &lt;br&gt;
We will see how to code split here, and take advantage of it in this and the next section.&lt;/p&gt;

&lt;p&gt;Do demonstrate this better, let's create a new page which only loads &lt;code&gt;Component1&lt;/code&gt;. Remember that &lt;code&gt;Component1&lt;/code&gt; uses &lt;code&gt;lodash/join&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create 'NewApp.js' inside &lt;code&gt;src&lt;/code&gt;, which only loads &lt;code&gt;Component1&lt;/code&gt;:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;NewApp.js&lt;/strong&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&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="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Component1&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/Component1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AppNew&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Component1&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create 'newindex.js' inside &lt;code&gt;src&lt;/code&gt;:
&lt;strong&gt;newindex.js&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="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="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&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-dom&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;AppNew&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;./AppNew&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AppNew&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&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;Let's now update &lt;code&gt;webpack.config.js&lt;/code&gt; to the following:&lt;br&gt;
&lt;strong&gt;webpack.config.js&lt;/strong&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;path&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="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;HtmlWebpackPlugin&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="s1"&gt;html-webpack-plugin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TerserPlugin&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="s1"&gt;terser-webpack-plugin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;webpack&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="s1"&gt;webpack&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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="s1"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;main&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;import&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/index.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;dependOn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shared&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;newindex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;import&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/newindex.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;dependOn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shared&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;shared&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lodash/join&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[name].js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;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;js|jsx&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;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="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;babel-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;presets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/preset-env&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/preset-react&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;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;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HtmlWebpackPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shared&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HtmlWebpackPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;newindex/index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;newindex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shared&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;// fix "process is not defined" error:&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;webpack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ProvidePlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;process&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;process/browser&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;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;minimize&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;minimizer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TerserPlugin&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
    &lt;span class="na"&gt;splitChunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&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;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we are doing the following things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Modified &lt;code&gt;entry&lt;/code&gt; to have 2 new values, &lt;code&gt;main&lt;/code&gt; &amp;amp; &lt;code&gt;newindex&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lodash/join&lt;/code&gt; is used in both pages, so we have taken out &lt;code&gt;lodash/join&lt;/code&gt; into a new common &lt;code&gt;shared&lt;/code&gt; asset &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;output&lt;/code&gt; specifies how would we name our new assets.&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;HtmlWebpackPlugin&lt;/code&gt; to be able to load &lt;code&gt;newindex&lt;/code&gt; page&lt;/li&gt;
&lt;li&gt;Added &lt;a href="https://webpack.js.org/guides/code-splitting/#splitchunksplugin" rel="noopener noreferrer"&gt;&lt;code&gt;splitChunks&lt;/code&gt;&lt;/a&gt; in &lt;code&gt;optimization&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's run &lt;code&gt;npx webpack&lt;/code&gt; again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;webpack-optimization-demo % npx webpack
assets by path &lt;span class="k"&gt;*&lt;/span&gt;.js 453 KiB
  asset 3.js 449 KiB &lt;span class="o"&gt;[&lt;/span&gt;compared &lt;span class="k"&gt;for &lt;/span&gt;emit] &lt;span class="o"&gt;[&lt;/span&gt;minimized] &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id &lt;/span&gt;hint: vendors&lt;span class="o"&gt;)&lt;/span&gt; 1 related asset
  asset main.js 2.14 KiB &lt;span class="o"&gt;[&lt;/span&gt;compared &lt;span class="k"&gt;for &lt;/span&gt;emit] &lt;span class="o"&gt;[&lt;/span&gt;minimized] &lt;span class="o"&gt;(&lt;/span&gt;name: main&lt;span class="o"&gt;)&lt;/span&gt;
  asset shared.js 1.25 KiB &lt;span class="o"&gt;[&lt;/span&gt;compared &lt;span class="k"&gt;for &lt;/span&gt;emit] &lt;span class="o"&gt;[&lt;/span&gt;minimized] &lt;span class="o"&gt;(&lt;/span&gt;name: shared&lt;span class="o"&gt;)&lt;/span&gt;
  asset newindex.js 736 bytes &lt;span class="o"&gt;[&lt;/span&gt;compared &lt;span class="k"&gt;for &lt;/span&gt;emit] &lt;span class="o"&gt;[&lt;/span&gt;minimized] &lt;span class="o"&gt;(&lt;/span&gt;name: newindex&lt;span class="o"&gt;)&lt;/span&gt;
asset newindex/index.html 287 bytes &lt;span class="o"&gt;[&lt;/span&gt;compared &lt;span class="k"&gt;for &lt;/span&gt;emit]
asset index.html 274 bytes &lt;span class="o"&gt;[&lt;/span&gt;compared &lt;span class="k"&gt;for &lt;/span&gt;emit]
Entrypoint main 451 KiB &lt;span class="o"&gt;=&lt;/span&gt; 3.js 449 KiB main.js 2.14 KiB
Entrypoint newindex 449 KiB &lt;span class="o"&gt;=&lt;/span&gt; 3.js 449 KiB newindex.js 736 bytes
Entrypoint shared 1.25 KiB &lt;span class="o"&gt;=&lt;/span&gt; shared.js
runtime modules 3.18 KiB 6 modules
modules by path ./node_modules/ 1.27 MiB
  modules by path ./node_modules/prop-types/ 28.6 KiB 6 modules
  modules by path ./node_modules/react/ 92.5 KiB 3 modules
  modules by path ./node_modules/react-dom/ 1.11 MiB 3 modules
  modules by path ./node_modules/scheduler/ 21.4 KiB 3 modules
  modules by path ./node_modules/react-is/ 9.5 KiB 3 modules
  + 3 modules
modules by path ./src/ 3.76 KiB
  modules by path ./src/&lt;span class="k"&gt;*&lt;/span&gt;.js 3 KiB
    ./src/newindex.js 190 bytes &lt;span class="o"&gt;[&lt;/span&gt;built] &lt;span class="o"&gt;[&lt;/span&gt;code generated]
    + 3 modules
  modules by path ./src/components/&lt;span class="k"&gt;*&lt;/span&gt;.js 779 bytes
    ./src/components/Component1.js 411 bytes &lt;span class="o"&gt;[&lt;/span&gt;built] &lt;span class="o"&gt;[&lt;/span&gt;code generated]
    + 2 modules
webpack 5.91.0 compiled successfully &lt;span class="k"&gt;in &lt;/span&gt;2620 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how multiple different asset files are getting created, including one for &lt;code&gt;shared.js&lt;/code&gt; which only contains &lt;code&gt;lodash/join&lt;/code&gt;. We can find these files inside the &lt;code&gt;dist/&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;At this point, let's run the server again and see how it all looks: &lt;code&gt;npx http-server -p 8000&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;If we open &lt;a href="https://localhost:8000/dist" rel="noopener noreferrer"&gt;&lt;code&gt;https://localhost:8000/dist&lt;/code&gt;&lt;/a&gt;, we see that &lt;code&gt;newindex.js&lt;/code&gt; is not loaded:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs001la1s9en0y4szgir0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs001la1s9en0y4szgir0.png" alt="Expected Code Split Page1 Network Tab" width="692" height="69"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we open &lt;a href="https://localhost:8000/dist/newindex" rel="noopener noreferrer"&gt;&lt;code&gt;https://localhost:8000/dist/newindex&lt;/code&gt;&lt;/a&gt;, we see that &lt;code&gt;main.js&lt;/code&gt; is not loaded:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F67kx7hnqr573c1e5mp60.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F67kx7hnqr573c1e5mp60.png" alt="Expected Code Split Page2 Network Tab" width="612" height="67"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Lazy loading
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://webpack.js.org/guides/lazy-loading/" rel="noopener noreferrer"&gt;Lazy loading&lt;/a&gt; simply means that loading of an asset should happen only on demand.&lt;/p&gt;

&lt;p&gt;In our case, we have seen that &lt;code&gt;Component2&lt;/code&gt; gets shown to user only when the button has clicked. However, it is loaded upfront. We are goin to load this only on demand.&lt;/p&gt;

&lt;p&gt;Update &lt;code&gt;App.js&lt;/code&gt; with following 2 changes:&lt;br&gt;
&lt;strong&gt;App.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState, lazy } from 'react';
// ...
const Component2 = lazy(() =&amp;gt; import('./components/Component2'));
// ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;npx webpack&lt;/code&gt;, we see a new asset (&lt;code&gt;4.js&lt;/code&gt; in my case, it might be named differently for you) is created in the &lt;code&gt;dist&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-optimization-demo % npx webpack
assets by path &lt;span class="k"&gt;*&lt;/span&gt;.js 455 KiB
  asset 3.js 449 KiB &lt;span class="o"&gt;[&lt;/span&gt;compared &lt;span class="k"&gt;for &lt;/span&gt;emit] &lt;span class="o"&gt;[&lt;/span&gt;minimized] &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id &lt;/span&gt;hint: vendors&lt;span class="o"&gt;)&lt;/span&gt; 1 related asset
  asset shared.js 3.2 KiB &lt;span class="o"&gt;[&lt;/span&gt;compared &lt;span class="k"&gt;for &lt;/span&gt;emit] &lt;span class="o"&gt;[&lt;/span&gt;minimized] &lt;span class="o"&gt;(&lt;/span&gt;name: shared&lt;span class="o"&gt;)&lt;/span&gt;
  asset main.js 2.06 KiB &lt;span class="o"&gt;[&lt;/span&gt;compared &lt;span class="k"&gt;for &lt;/span&gt;emit] &lt;span class="o"&gt;[&lt;/span&gt;minimized] &lt;span class="o"&gt;(&lt;/span&gt;name: main&lt;span class="o"&gt;)&lt;/span&gt;
  asset newindex.js 736 bytes &lt;span class="o"&gt;[&lt;/span&gt;compared &lt;span class="k"&gt;for &lt;/span&gt;emit] &lt;span class="o"&gt;[&lt;/span&gt;minimized] &lt;span class="o"&gt;(&lt;/span&gt;name: newindex&lt;span class="o"&gt;)&lt;/span&gt;
  asset 4.js 254 bytes &lt;span class="o"&gt;[&lt;/span&gt;compared &lt;span class="k"&gt;for &lt;/span&gt;emit] &lt;span class="o"&gt;[&lt;/span&gt;minimized]
asset newindex/index.html 287 bytes &lt;span class="o"&gt;[&lt;/span&gt;compared &lt;span class="k"&gt;for &lt;/span&gt;emit]
asset index.html 274 bytes &lt;span class="o"&gt;[&lt;/span&gt;compared &lt;span class="k"&gt;for &lt;/span&gt;emit]
Entrypoint main 451 KiB &lt;span class="o"&gt;=&lt;/span&gt; 3.js 449 KiB main.js 2.06 KiB
Entrypoint newindex 449 KiB &lt;span class="o"&gt;=&lt;/span&gt; 3.js 449 KiB newindex.js 736 bytes
Entrypoint shared 3.2 KiB &lt;span class="o"&gt;=&lt;/span&gt; shared.js
runtime modules 8.12 KiB 12 modules
modules by path ./node_modules/ 1.27 MiB
  modules by path ./node_modules/prop-types/ 28.6 KiB 6 modules
  modules by path ./node_modules/react/ 92.5 KiB 3 modules
  modules by path ./node_modules/react-dom/ 1.11 MiB 3 modules
  modules by path ./node_modules/scheduler/ 21.4 KiB 3 modules
  modules by path ./node_modules/react-is/ 9.5 KiB 3 modules
  + 3 modules
modules by path ./src/ 3.8 KiB
  modules by path ./src/&lt;span class="k"&gt;*&lt;/span&gt;.js 3.04 KiB
    ./src/newindex.js 190 bytes &lt;span class="o"&gt;[&lt;/span&gt;built] &lt;span class="o"&gt;[&lt;/span&gt;code generated]
    + 3 modules
  modules by path ./src/components/&lt;span class="k"&gt;*&lt;/span&gt;.js 779 bytes
    ./src/components/Component1.js 411 bytes &lt;span class="o"&gt;[&lt;/span&gt;built] &lt;span class="o"&gt;[&lt;/span&gt;code generated]
    + 2 modules
webpack 5.91.0 compiled successfully &lt;span class="k"&gt;in &lt;/span&gt;2529 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What is this asset ? Le's open it (Find it in &lt;code&gt;dist/4.js&lt;/code&gt;).&lt;br&gt;
We see that &lt;code&gt;4.js&lt;/code&gt; contains our &lt;code&gt;Component2&lt;/code&gt; code. &lt;/p&gt;

&lt;p&gt;Let;s now run &lt;code&gt;npx http-server -p 8000&lt;/code&gt;, open &lt;code&gt;Developer Tools&lt;/code&gt; and go to &lt;code&gt;Network Tab&lt;/code&gt; and open &lt;code&gt;https://localhost:8000/dist&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We see that &lt;code&gt;4.js&lt;/code&gt; is not yet loaded.&lt;br&gt;
Click on the button &lt;code&gt;Load Component 2&lt;/code&gt; and notice that  &lt;code&gt;4.js&lt;/code&gt; gets loaded now.&lt;/p&gt;

&lt;p&gt;There you have it, Lazy (On-demand) Loading.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Production mode
&lt;/h2&gt;

&lt;p&gt;We can provide different modes in the webpack config. We are currently running with &lt;code&gt;none&lt;/code&gt; mode. We can specify &lt;code&gt;development&lt;/code&gt; and &lt;code&gt;production&lt;/code&gt; mode.&lt;br&gt;
In &lt;code&gt;development&lt;/code&gt; mode, the purpose is ease of development. In &lt;code&gt;production&lt;/code&gt; mode, the purpose is to give small, fast, optimized assets.&lt;/p&gt;

&lt;p&gt;Let's change the mode in:&lt;br&gt;
&lt;strong&gt;webpack.config.js&lt;/strong&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;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;npx webpack&lt;/code&gt; and notice how the asset size is reduced in size by a huge number.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;webpack-optimization-demo % npx webpack
assets by path &lt;span class="k"&gt;*&lt;/span&gt;.js 143 KiB
  asset 248.js 137 KiB &lt;span class="o"&gt;[&lt;/span&gt;emitted] &lt;span class="o"&gt;[&lt;/span&gt;minimized] &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id &lt;/span&gt;hint: vendors&lt;span class="o"&gt;)&lt;/span&gt; 1 related asset
  asset shared.js 3.13 KiB &lt;span class="o"&gt;[&lt;/span&gt;emitted] &lt;span class="o"&gt;[&lt;/span&gt;minimized] &lt;span class="o"&gt;(&lt;/span&gt;name: shared&lt;span class="o"&gt;)&lt;/span&gt;
  asset main.js 1.94 KiB &lt;span class="o"&gt;[&lt;/span&gt;emitted] &lt;span class="o"&gt;[&lt;/span&gt;minimized] &lt;span class="o"&gt;(&lt;/span&gt;name: main&lt;span class="o"&gt;)&lt;/span&gt;
  asset newindex.js 644 bytes &lt;span class="o"&gt;[&lt;/span&gt;emitted] &lt;span class="o"&gt;[&lt;/span&gt;minimized] &lt;span class="o"&gt;(&lt;/span&gt;name: newindex&lt;span class="o"&gt;)&lt;/span&gt;
  asset 860.js 248 bytes &lt;span class="o"&gt;[&lt;/span&gt;emitted] &lt;span class="o"&gt;[&lt;/span&gt;minimized]
asset newindex/index.html 282 bytes &lt;span class="o"&gt;[&lt;/span&gt;emitted]
asset index.html 269 bytes &lt;span class="o"&gt;[&lt;/span&gt;emitted]
Entrypoint main 139 KiB &lt;span class="o"&gt;=&lt;/span&gt; 248.js 137 KiB main.js 1.94 KiB
Entrypoint newindex 137 KiB &lt;span class="o"&gt;=&lt;/span&gt; 248.js 137 KiB newindex.js 644 bytes
Entrypoint shared 3.13 KiB &lt;span class="o"&gt;=&lt;/span&gt; shared.js
runtime modules 8 KiB 11 modules
orphan modules 2.88 KiB &lt;span class="o"&gt;[&lt;/span&gt;orphan] 3 modules
cacheable modules 148 KiB
  modules by path ./node_modules/ 144 KiB
    modules by path ./node_modules/prop-types/ 2.6 KiB 3 modules
    modules by path ./node_modules/react/ 6.95 KiB 2 modules
    modules by path ./node_modules/react-dom/ 130 KiB 2 modules
    modules by path ./node_modules/scheduler/ 4.33 KiB 2 modules
    + 1 module
  modules by path ./src/ 3.61 KiB
    modules by path ./src/&lt;span class="k"&gt;*&lt;/span&gt;.js 3.04 KiB 2 modules
    modules by path ./src/components/&lt;span class="k"&gt;*&lt;/span&gt;.js 579 bytes
      ./src/components/Component1.js 411 bytes &lt;span class="o"&gt;[&lt;/span&gt;built] &lt;span class="o"&gt;[&lt;/span&gt;code generated]
      ./src/components/Component2.js 168 bytes &lt;span class="o"&gt;[&lt;/span&gt;built] &lt;span class="o"&gt;[&lt;/span&gt;code generated]
webpack 5.91.0 compiled successfully &lt;span class="k"&gt;in &lt;/span&gt;1664 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Compression
&lt;/h2&gt;

&lt;p&gt;We can also compress the files further to ensure a smaller asset is transferred over the network.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;npm install compression-webpack-plugin --save-dev&lt;/code&gt;, and then run &lt;code&gt;npx webpack&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-optimization-demo % npx webpack
assets by path &lt;span class="k"&gt;*&lt;/span&gt;.js 143 KiB
  assets by status 5.7 KiB &lt;span class="o"&gt;[&lt;/span&gt;emitted]
    asset shared.js 3.13 KiB &lt;span class="o"&gt;[&lt;/span&gt;emitted] &lt;span class="o"&gt;[&lt;/span&gt;minimized] &lt;span class="o"&gt;(&lt;/span&gt;name: shared&lt;span class="o"&gt;)&lt;/span&gt; 1 related asset
    asset main.js 1.94 KiB &lt;span class="o"&gt;[&lt;/span&gt;emitted] &lt;span class="o"&gt;[&lt;/span&gt;minimized] &lt;span class="o"&gt;(&lt;/span&gt;name: main&lt;span class="o"&gt;)&lt;/span&gt; 1 related asset
    asset newindex.js 644 bytes &lt;span class="o"&gt;[&lt;/span&gt;emitted] &lt;span class="o"&gt;[&lt;/span&gt;minimized] &lt;span class="o"&gt;(&lt;/span&gt;name: newindex&lt;span class="o"&gt;)&lt;/span&gt; 1 related asset
  assets by status 137 KiB &lt;span class="o"&gt;[&lt;/span&gt;compared &lt;span class="k"&gt;for &lt;/span&gt;emit]
    asset 248.js 137 KiB &lt;span class="o"&gt;[&lt;/span&gt;compared &lt;span class="k"&gt;for &lt;/span&gt;emit] &lt;span class="o"&gt;[&lt;/span&gt;minimized] &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id &lt;/span&gt;hint: vendors&lt;span class="o"&gt;)&lt;/span&gt; 2 related assets
    asset 860.js 248 bytes &lt;span class="o"&gt;[&lt;/span&gt;compared &lt;span class="k"&gt;for &lt;/span&gt;emit] &lt;span class="o"&gt;[&lt;/span&gt;minimized] 1 related asset
asset newindex/index.html 282 bytes &lt;span class="o"&gt;[&lt;/span&gt;emitted] 1 related asset
asset index.html 269 bytes &lt;span class="o"&gt;[&lt;/span&gt;emitted] 1 related asset
Entrypoint main 139 KiB &lt;span class="o"&gt;=&lt;/span&gt; 248.js 137 KiB main.js 1.94 KiB
Entrypoint newindex 137 KiB &lt;span class="o"&gt;=&lt;/span&gt; 248.js 137 KiB newindex.js 644 bytes
Entrypoint shared 3.13 KiB &lt;span class="o"&gt;=&lt;/span&gt; shared.js
runtime modules 8 KiB 11 modules
orphan modules 2.88 KiB &lt;span class="o"&gt;[&lt;/span&gt;orphan] 3 modules
cacheable modules 148 KiB
  modules by path ./node_modules/ 144 KiB
    modules by path ./node_modules/prop-types/ 2.6 KiB 3 modules
    modules by path ./node_modules/react/ 6.95 KiB 2 modules
    modules by path ./node_modules/react-dom/ 130 KiB 2 modules
    modules by path ./node_modules/scheduler/ 4.33 KiB 2 modules
    + 1 module
  modules by path ./src/ 3.61 KiB
    modules by path ./src/&lt;span class="k"&gt;*&lt;/span&gt;.js 3.04 KiB 2 modules
    modules by path ./src/components/&lt;span class="k"&gt;*&lt;/span&gt;.js 579 bytes
      ./src/components/Component1.js 411 bytes &lt;span class="o"&gt;[&lt;/span&gt;built] &lt;span class="o"&gt;[&lt;/span&gt;code generated]
      ./src/components/Component2.js 168 bytes &lt;span class="o"&gt;[&lt;/span&gt;built] &lt;span class="o"&gt;[&lt;/span&gt;code generated]
webpack 5.91.0 compiled successfully &lt;span class="k"&gt;in &lt;/span&gt;1656 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is no difference in this small example. But the difference can be more significant in larger projects. (It's also possible the compression done in the production mode is comparable in this case, so does not make any difference here).&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Other options
&lt;/h2&gt;

&lt;p&gt;There are still many other steps we can take like &lt;a href="https://webpack.js.org/configuration/externals/" rel="noopener noreferrer"&gt;External Dependency&lt;/a&gt; where we loaded common large dependencies during run-time from CDN, &lt;a href="https://purgecss.com/plugins/webpack.html" rel="noopener noreferrer"&gt;Purge Unsued CSS&lt;/a&gt;, &lt;a href="https://webpack.js.org/plugins/module-concatenation-plugin/" rel="noopener noreferrer"&gt;Module Concatenation&lt;/a&gt; and many more, depending on our specific needs. I will not go into it for the sake of keeping this article consumeable.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Bundle analyzer
&lt;/h2&gt;

&lt;p&gt;I will however mention one very useful plugin &lt;a href="https://www.npmjs.com/package/webpack-bundle-analyzer" rel="noopener noreferrer"&gt;Webpack Bundle Analyzer&lt;/a&gt;. It graphically helps us visualize which modules are taking how much space and where we should look to optimize. It's also interactive.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; webpack-bundle-analyzer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update the &lt;code&gt;webpack.config.js&lt;/code&gt;:&lt;br&gt;
&lt;strong&gt;webpack.config.js&lt;/strong&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;BundleAnalyzerPlugin&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="s1"&gt;webpack-bundle-analyzer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;BundleAnalyzerPlugin&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="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="na"&gt;plugins&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BundleAnalyzerPlugin&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;Run &lt;code&gt;npx webpack&lt;/code&gt; and then open &lt;code&gt;http://localhost:8888/&lt;/code&gt; and we should see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8idydmw1dvhnawnumwu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8idydmw1dvhnawnumwu.png" alt="Bundle Analyzer Plugin Example Output" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

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

&lt;p&gt;Optimizing the bundle size of any web application is essential for ensuring a seamless and performant user experience. By leveraging the power of webpack and its optimization techniques, we can significantly reduce the amount of data transferred over the network, leading to faster load times and improved overall performance. Continuously monitoring and refining the webpack configuration will help in maintaining a high-performing and responsive application over time.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://webpack.js.org/" rel="noopener noreferrer"&gt;Webpack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://webpack.js.org/guides/tree-shaking/" rel="noopener noreferrer"&gt;Tree Shaking&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://webpack.js.org/guides/code-splitting/" rel="noopener noreferrer"&gt;Code Splitting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://webpack.js.org/configuration/externals/" rel="noopener noreferrer"&gt;External Dependency&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://purgecss.com/plugins/webpack.html" rel="noopener noreferrer"&gt;Purge CSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://webpack.js.org/plugins/module-concatenation-plugin/" rel="noopener noreferrer"&gt;Module Concatenation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/webpack-bundle-analyzer" rel="noopener noreferrer"&gt;Webpack Bundle Analyzer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;blockquote&gt;
&lt;p&gt;This article was originally published in &lt;a href="https://wewake.dev/posts/beginner-friendly-hands-on-guide-to-speed-up-nodejs-apps/" rel="noopener noreferrer"&gt;my personal blog&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>tutorial</category>
      <category>beginners</category>
      <category>javascript</category>
      <category>webpack</category>
    </item>
    <item>
      <title>Practical Experiments for Optimizing Django query with the power of SQL joins</title>
      <dc:creator>Wewake</dc:creator>
      <pubDate>Sat, 27 Apr 2024 03:42:12 +0000</pubDate>
      <link>https://dev.to/wewake-dev/practical-experiments-for-optimizing-django-query-with-the-power-of-sql-joins-215d</link>
      <guid>https://dev.to/wewake-dev/practical-experiments-for-optimizing-django-query-with-the-power-of-sql-joins-215d</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Concepts&lt;/li&gt;
&lt;li&gt;
Practical

&lt;ul&gt;
&lt;li&gt;Project Setup&lt;/li&gt;
&lt;li&gt;Experiment with a small number of records&lt;/li&gt;
&lt;li&gt;Experiment with a larger number of records&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Python&lt;/code&gt; is a remarkable programming language - it's simple, powerful, and abstracts away several complicated internal concepts, which makes it easy to code with. &lt;code&gt;Django&lt;/code&gt; framework extends this simple powerful nature of python to the web.&lt;/p&gt;

&lt;p&gt;However, the very abstraction and simplicity that make &lt;code&gt;Python&lt;/code&gt; and &lt;code&gt;Django&lt;/code&gt; so appealing can sometimes lead developers, especially those without formal computer science training, to overlook (or maybe just forget about) the intricacies of how things work under the hood. &lt;/p&gt;

&lt;p&gt;One concept that I have often seen several developers overlook in their professional lives is the concept of &lt;code&gt;joins&lt;/code&gt; in database queries. This might not be apparent on a small scale, but when handling vast amounts of data, the programs can become unweildy.&lt;/p&gt;

&lt;p&gt;We will walk through how a simple optimization concepts can make a huge difference as the scale increases.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Concepts
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Django's ORM&lt;/code&gt; is tightly coupled with the &lt;code&gt;SQL&lt;/code&gt; (relational) tables. Each Model defined in &lt;code&gt;Django&lt;/code&gt; has a correponding table defined in &lt;code&gt;SQL&lt;/code&gt;. When we query in &lt;code&gt;Django Model&lt;/code&gt;, we are actually querying the corresponnding &lt;code&gt;SQL&lt;/code&gt; table. So, it is obvious that any optimization techniques used in SQL would also be beneficial when querying &lt;code&gt;Django models&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Another important point to note is that making a &lt;code&gt;SQL&lt;/code&gt; call (i.e. a Database call) is expensive. So, we want to minimize the number of calls to the Database.&lt;/p&gt;

&lt;p&gt;We assume you already know what SQL joins are. Informally, &lt;code&gt;SQL joins&lt;/code&gt; allows you to query 2 or more related tables faster. To read more, you can checkout &lt;a href="https://en.wikipedia.org/wiki/Join_(SQL)" rel="noopener noreferrer"&gt;SQL JOIN&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;As we would expect, &lt;code&gt;Django&lt;/code&gt; has corresponding methods to optimize queries:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;select_related&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Performs a &lt;code&gt;SQL JOIN&lt;/code&gt; to fetch related data in the same query.&lt;/li&gt;
&lt;li&gt;Suitable for &lt;strong&gt;&lt;em&gt;one-to-one&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;one-to-many&lt;/em&gt;&lt;/strong&gt; relationships.&lt;/li&gt;
&lt;li&gt;More efficient than separate queries when you know you'll need the related data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;prefetch_related&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uses &lt;em&gt;separate queries&lt;/em&gt; to fetch related data, but &lt;em&gt;batches the queries to minimize database hits&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Suitable for &lt;strong&gt;&lt;em&gt;many-to-many&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;many-to-one&lt;/em&gt;&lt;/strong&gt; relationships.&lt;/li&gt;
&lt;li&gt;More efficient than separate queries when you'll need the related data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In summary, &lt;code&gt;select_related&lt;/code&gt; is optimized for &lt;code&gt;one-to-one&lt;/code&gt; and &lt;code&gt;one-to-many&lt;/code&gt; relationships, while &lt;code&gt;prefetch_related&lt;/code&gt; is optimized for &lt;code&gt;many-to-many&lt;/code&gt; and &lt;code&gt;many-to-one&lt;/code&gt; relationships. # The choice depends on the type of relationship and the likelihood of needing the related data.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical
&lt;/h2&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Project Setup
&lt;/h3&gt;

&lt;p&gt;Let's set up a very simple Django project so that we can run our experiments. &lt;/p&gt;

&lt;p&gt;1.Assuming you have &lt;code&gt;python3&lt;/code&gt; installed, run the following to start &lt;code&gt;virtualenv&lt;/code&gt; and install &lt;code&gt;Django&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;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv
&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate
pip &lt;span class="nb"&gt;install &lt;/span&gt;Django
pip &lt;span class="nb"&gt;install &lt;/span&gt;Faker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;If you don't want to go through the setup, you can clone the&lt;br&gt;
&lt;a href="https://github.com/viv1/blog-code-examples" rel="noopener noreferrer"&gt;repository&lt;/a&gt; and go to the example directory: &lt;code&gt;cd django_join&lt;/code&gt; after the above step. And then continue reading from Experiment 1&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2.Run the following to start a new project named &lt;code&gt;django-join&lt;/code&gt; and create an app/module inside it called &lt;code&gt;myapp&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;django-admin startproject django_join
django-admin startapp myapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3.Now, enable the &lt;code&gt;myapp&lt;/code&gt; by including it under &lt;code&gt;INSTALLED_APPS&lt;/code&gt; in &lt;code&gt;settings.py&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;vim django_join/settings.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;myapp&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# ADD YOUR APP HERE
&lt;/span&gt;
    &lt;span class="c1"&gt;# EXISTING MODELS
&lt;/span&gt;    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.admin&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.auth&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.contenttypes&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.sessions&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.messages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.staticfiles&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="bp"&gt;...&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4.Create New Django models in &lt;code&gt;myapp/models.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.core.validators&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MaxValueValidator&lt;/span&gt;

&lt;span class="c1"&gt;# Create your models here.
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;IntegerField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validators&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;MaxValueValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5.Run migration commands to create the model tables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python manage.py makemigrations myapp
python manage.py migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;6.Let's also create a command to populate our tables with random data. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install &lt;code&gt;Faker&lt;/code&gt; library:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;Faker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create the file in this location (Create subfolders as needed):
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vim myapp/management/commands/populate_data.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Paste the following. This basically generates random data given author count and max number of books for an author.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.core.management.base&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseCommand&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;faker&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Faker&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;myapp.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Book&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseCommand&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;help&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Populates the database with random authors and books&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_arguments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;authors&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;The number of authors to create&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;books&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;The number of books to create per author&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;faker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Faker&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="n"&gt;authors_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;authors&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;max_books_per_author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;books&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;authors_count&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="c1"&gt;# Generate random number of books upto max_count
&lt;/span&gt;            &lt;span class="n"&gt;book_count_for_this_author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;books_per_author&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book_count_for_this_author&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SUCCESS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Successfully added &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;authors_count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; authors and &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;authors_count&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;books_per_author&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; books&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;7.Create another file to run the 1st experiment. This experiment will check the difference in number of queries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vim myapp/management/commands/get_db_query_count.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reset_queries&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;myapp.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Book&lt;/span&gt;

&lt;span class="c1"&gt;# Measuring for select_related
&lt;/span&gt;&lt;span class="nf"&gt;reset_queries&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;books&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select_related&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;author&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;books&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Queries with select_related: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;reset_queries&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;books&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;books&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Queries without select_related: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Measuring for prefetch_related
&lt;/span&gt;&lt;span class="nf"&gt;reset_queries&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;authors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prefetch_related&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;book_set&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;book_set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Queries with prefetch_related: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;reset_queries&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;authors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;book_set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Queries without prefetch_related: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;8.Create another file to run the 2nd experiment. This experiment will measure the time difference while running the commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vim myapp/management/commands/get_time_difference.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.core.management.base&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseCommand&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reset_queries&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Count&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;myapp.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Book&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseCommand&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;help&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Measure average time taken to run commands. It gives average run time of 10 commands.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# With prefetch_related
&lt;/span&gt;        &lt;span class="n"&gt;execution_time1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;get_total_book_count_with_prefetch_related()&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;globals&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Avg time with prefetch_related: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;execution_time1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Without prefetch_related
&lt;/span&gt;        &lt;span class="n"&gt;execution_time2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;get_total_book_count_without_prefetch_related()&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;globals&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Avg time without prefetch_related: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;execution_time2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prefetch_related performance improvement RATIO:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;execution_time2&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;execution_time1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="c1"&gt;# With select_related
&lt;/span&gt;        &lt;span class="n"&gt;execution_time3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;get_total_book_count_with_select_related()&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;globals&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Avg time with select_related: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;execution_time3&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Without select_related
&lt;/span&gt;        &lt;span class="n"&gt;execution_time4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;get_total_book_count_without_select_related()&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;globals&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Avg time without select_related: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;execution_time4&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;select_related performance improvement RATIO:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;execution_time4&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;execution_time3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;



&lt;span class="c1"&gt;# Without prefetch_related
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_total_book_count_without_prefetch_related&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;authors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;book_set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;# print(count)
&lt;/span&gt;
&lt;span class="c1"&gt;# With prefetch_related
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_total_book_count_with_prefetch_related&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;authors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prefetch_related&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;book_set&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;book_set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;# print(count)
&lt;/span&gt;
&lt;span class="c1"&gt;# Without select_related
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_total_book_count_without_select_related&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;books&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;total_age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; 
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;books&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;total_age&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;
    &lt;span class="c1"&gt;# print(total_age // books.count())
&lt;/span&gt;
&lt;span class="c1"&gt;# With select_related
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_total_book_count_with_select_related&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;books&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select_related&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;author&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;total_age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;books&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;total_age&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;
    &lt;span class="c1"&gt;# print(total_age // books.count())
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Experiment with a small number of records
&lt;/h3&gt;

&lt;p&gt;We will first populate a small dataset, and then run the commands to get db query count and time.&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;venv&lt;span class="o"&gt;)&lt;/span&gt; viv1@Viveks-MacBook-Pro django_join % python manage.py populate_data 5 5
Successfully added 5 authors and 18 books

&lt;span class="o"&gt;(&lt;/span&gt;venv&lt;span class="o"&gt;)&lt;/span&gt; viv1@Viveks-MacBook-Pro django_join % python manage.py get_db_query_count
Queries with prefetch_related: 2
Queries without prefetch_related: 6
Additional Queries: 4

Queries with select_related: 1
Queries without select_related: 19
Additional Queries: 18
&lt;span class="o"&gt;(&lt;/span&gt;venv&lt;span class="o"&gt;)&lt;/span&gt; viv1@Viveks-MacBook-Pro django_join % python manage.py get_time_difference
Avg &lt;span class="nb"&gt;time &lt;/span&gt;with prefetch_related: 0.0008449875000000023
Avg &lt;span class="nb"&gt;time &lt;/span&gt;without prefetch_related: 0.0017883291999999996
prefetch_related performance improvement RATIO: 2.1163972248110117

Avg &lt;span class="nb"&gt;time &lt;/span&gt;with select_related: 0.00023677920000000075
Avg &lt;span class="nb"&gt;time &lt;/span&gt;without select_related: 0.0030041750000000004
select_related performance improvement RATIO: 12.68766428807932

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even with the small amount of records, we can see the performance improvement in terms of time and the number of db calls. In fact, what we are observing in the query part is the &lt;strong&gt;&lt;em&gt;&lt;a href="https://stackoverflow.com/questions/97197/what-is-the-n1-selects-problem-in-orm-object-relational-mapping" rel="noopener noreferrer"&gt;famous N+1 query problem&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt; , where there is N number of DB calls for each of the N records. With this optimization, we can reduce it to a single DB call.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Experiment with a larger number of records
&lt;/h3&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;venv&lt;span class="o"&gt;)&lt;/span&gt; viv1@Viveks-MacBook-Pro django_join % python manage.py populate_data 100 10
Successfully added 100 authors and 549 books
&lt;span class="o"&gt;(&lt;/span&gt;venv&lt;span class="o"&gt;)&lt;/span&gt; viv1@Viveks-MacBook-Pro django_join % python manage.py get_db_query_count
Queries with prefetch_related: 2
Queries without prefetch_related: 106
Additional Queries: 104

Queries with select_related: 1
Queries without select_related: 568
Additional Queries: 567
&lt;span class="o"&gt;(&lt;/span&gt;venv&lt;span class="o"&gt;)&lt;/span&gt; viv1@Viveks-MacBook-Pro django_join % python manage.py get_time_difference
Avg &lt;span class="nb"&gt;time &lt;/span&gt;with prefetch_related: 0.0058029208
Avg &lt;span class="nb"&gt;time &lt;/span&gt;without prefetch_related: 0.029672083399999993
prefetch_related performance improvement RATIO: 5.113301460188806

Avg &lt;span class="nb"&gt;time &lt;/span&gt;with select_related: 0.003976683299999994
Avg &lt;span class="nb"&gt;time &lt;/span&gt;without select_related: 0.099798425
select_related performance improvement RATIO: 25.09589461147186
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With just a bit higher number of records, we can see the performance improvement is even higher.&lt;/p&gt;

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

&lt;p&gt;Optimizing database queries is crucial for achieving high performance and scalability in Django applications. Being aware of very simple concepts like joins can make our application faster, more responsive and efficient, especially when dealing with large datasets and complex relationships between models.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.djangoproject.com/en/5.0/ref/models/querysets/#django.db.models.query.QuerySet.prefetch_related" rel="noopener noreferrer"&gt;prefetch_related&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.djangoproject.com/en/5.0/ref/models/querysets/#django.db.models.query.QuerySet.select_related" rel="noopener noreferrer"&gt;select_related&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;This article was originally published on my blog at &lt;a href="https://wewake.dev/posts/practical-experiments-for-django-orm-query-optimizations/" rel="noopener noreferrer"&gt;https://wewake.dev/posts/practical-experiments-for-django-orm-query-optimizations/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Find more of my content of my blog, where I share my software development experiences and learnings: &lt;a href="https://wewake.dev" rel="noopener noreferrer"&gt;https://wewake.dev&lt;/a&gt;&lt;/p&gt;

</description>
      <category>django</category>
      <category>optimization</category>
      <category>performance</category>
      <category>sql</category>
    </item>
    <item>
      <title>Solving Coding Problems using the Inclusion-Exclusion Principle and its variations</title>
      <dc:creator>Wewake</dc:creator>
      <pubDate>Mon, 15 Apr 2024 17:29:10 +0000</pubDate>
      <link>https://dev.to/wewake-dev/solving-coding-problems-using-the-inclusion-exclusion-principle-and-its-variations-27be</link>
      <guid>https://dev.to/wewake-dev/solving-coding-problems-using-the-inclusion-exclusion-principle-and-its-variations-27be</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Problem Statement&lt;/li&gt;
&lt;li&gt;Solving the inverse problem&lt;/li&gt;
&lt;li&gt;Inclusion Exclusion Principle&lt;/li&gt;
&lt;li&gt;
Variations

&lt;ul&gt;
&lt;li&gt;Variation 1: Counting Sequences with Required Elements&lt;/li&gt;
&lt;li&gt;Variation 2: Number of upper-bound integer sums&lt;/li&gt;
&lt;li&gt;Variation 3: Leetcode Problem Ugly Number III&lt;/li&gt;
&lt;li&gt;Other Variations&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

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

&lt;li&gt;References and Further Reading&lt;/li&gt;

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

&lt;/ul&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;Let's start with the problem statement:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Count the number of permutations of digits from 0 to 9 such that the first digit is greater than 1, and the last digit is less than 8.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Solving the inverse problem
&lt;/h2&gt;

&lt;p&gt;We will try to solve for the inverse problem instead. i.e. finding all permutations where the first digit is greater than 1, OR the last digit is less than 8&lt;/p&gt;

&lt;p&gt;If we define &lt;code&gt;X&lt;/code&gt; and &lt;code&gt;Y&lt;/code&gt; as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;X: The set of permutations where the first digit is less than or equal to 1.
Y: The set of permutations where the last digit is greater than or equal to 8.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From &lt;em&gt;venn diagram&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;|X ∪ Y|&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6f5k3dxusm0jfyd5rqqu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6f5k3dxusm0jfyd5rqqu.png" alt="|X ∪ Y|" width="360" height="265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;|X ∩ Y|&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvf0rmb0lqu99hpj0socb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvf0rmb0lqu99hpj0socb.png" alt="|X ∩ Y|" width="360" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;it follows:&lt;/p&gt;

&lt;p&gt;i.e.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|X ∪ Y| : Count of permutations with "first digit is less than or equal to 1" OR "last digit is greater than or equal to 8".

|X ∩ Y|: Count of permutations with "first digit is less than or equal to 1" AND "last digit is greater than or equal to 8".
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|X ∪ Y| : Represents all the bad permutations.
This is the solution to the "inverse" problem.

So,
Our answer = All Permutations of [O, 9]  - All Bad permutations
=&amp;gt; answer = All Permutations of [O, 9] - |X ∪ Y|

Since, `|X ∪ Y| = |X| + |Y| - |X ∩ Y|`

Answer = `Total Permutations of [O, 9] - (|X| + |Y| - |X ∩ Y|)`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;factorial&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;count_permutations_ie&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;total_permutations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;factorial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;bad_first_digit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;factorial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# 2 options (0 or 1) for the first digit
&lt;/span&gt;    &lt;span class="n"&gt;bad_last_digit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;factorial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# 2 options (8 or 9) for the last digit
&lt;/span&gt;    &lt;span class="n"&gt;bad_first_and_last&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;factorial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# 2 options for first, 2 for last
&lt;/span&gt;
    &lt;span class="n"&gt;bad_permutations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bad_first_digit&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;bad_last_digit&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;bad_first_and_last&lt;/span&gt;
    &lt;span class="n"&gt;good_permutations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;total_permutations&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;bad_permutations&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;good_permutations&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Number of permutations (IE): &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;count_permutations_ie&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This can also be solved via dynamic programming. See section Appendix.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Inclusion Exclusion Principle
&lt;/h2&gt;

&lt;p&gt;What we observed above was basically the &lt;code&gt;Inclusion Exclusion Principle&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To find &lt;code&gt;|X ∪ Y|&lt;/code&gt;, we used  &lt;code&gt;|X| + |Y| - |X ∩ Y|&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is a more complete definition:&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Inclusion-Exclusion Principle&lt;/code&gt; is a counting technique that allows us to find the cardinality (size) of the union of multiple sets by considering their individual cardinalities, their intersections, and their complements. The principle states that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|A_1 ∪ A_2 ∪ ... ∪ A_n| = Σ(|A_i|) - Σ(|A_i ∩ A_j|) + Σ(|A_i ∩ A_j ∩ A_k|) - ... + (-1)^(n-1) * |A_1 ∩ A_2 ∩ ... ∩ A_n|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In simpler terms, the principle says that to find the cardinality of the union of sets, we need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add the cardinalities of all the individual sets.&lt;/li&gt;
&lt;li&gt;Subtract the cardinalities of all pairwise intersections of the sets.&lt;/li&gt;
&lt;li&gt;Add the cardinalities of all triple intersections of the sets.&lt;/li&gt;
&lt;li&gt;Subtract the cardinalities of all quadruple intersections of the sets, and so on, alternating the signs.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;This formula might seem intimidating at first, but it becomes more intuitive with examples and practice.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Variations
&lt;/h2&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Variation 1: Counting Sequences with Required Elements
&lt;/h3&gt;

&lt;p&gt;Consider a problem where we need to count the number of sequences of length n consisting of only 0, 1, and 2, such that each number occurs at least once.&lt;/p&gt;

&lt;p&gt;We can represent the set of "bad" sequences (those that don't satisfy the constraint) as the union of three sets:&lt;/p&gt;

&lt;p&gt;A_0: The set of sequences that don't contain 0.&lt;br&gt;
A_1: The set of sequences that don't contain 1.&lt;br&gt;
A_2: The set of sequences that don't contain 2.&lt;br&gt;
Using the Inclusion-Exclusion Principle, we can find the cardinality of the "bad" sequences as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;|A_0 ∪ A_1 ∪ A_2| &lt;span class="o"&gt;=&lt;/span&gt; |A_0| + |A_1| + |A_2| - |A_0 ∩ A_1| - |A_0 ∩ A_2| - |A_1 ∩ A_2| + |A_0 ∩ A_1 ∩ A_2|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can calculate the cardinalities as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;count_sequences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;total_sequences&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
    &lt;span class="n"&gt;bad_sequences&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;good_sequences&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;total_sequences&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;bad_sequences&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;good_sequences&lt;/span&gt;

&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Number of good sequences of length &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;count_sequences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code will output the number of sequences of length n that contain all three elements (0, 1, and 2) at least once.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Variation 2: Number of upper-bound integer sums
&lt;/h3&gt;

&lt;p&gt;For &lt;code&gt;x1 + x2 + x3 + x4 + x5 + x6 = 20&lt;/code&gt;, where &lt;code&gt;0 &amp;lt;= xi &amp;lt;= 8&lt;/code&gt;, find the number of solutions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let's define the set of &lt;code&gt;"good"&lt;/code&gt; solutions as the set of all tuples &lt;code&gt;(x1, x2, x3, x4, x5, x6)&lt;/code&gt; that &lt;strong&gt;satisfy&lt;/strong&gt; the equation &lt;code&gt;x1 + x2 + x3 + x4 + x5 + x6 = 20&lt;/code&gt; and the constraint &lt;code&gt;0 ≤ xi ≤ 8&lt;/code&gt; for &lt;strong&gt;all i&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Also, let's define the set of &lt;code&gt;"bad"&lt;/code&gt; solutions as the set of tuples that &lt;strong&gt;violate&lt;/strong&gt; the constraint &lt;code&gt;0 ≤ xi ≤ 8&lt;/code&gt; for &lt;strong&gt;at least one value of i&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, we can use the &lt;code&gt;Inclusion-Exclusion Principle&lt;/code&gt; to count the number of &lt;code&gt;"bad"&lt;/code&gt; solutions and then subtract it from the total number of solutions to get the count of &lt;code&gt;"good"&lt;/code&gt; solutions.&lt;/p&gt;

&lt;p&gt;Here is the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;functools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;lru_cache&lt;/span&gt;

&lt;span class="nd"&gt;@lru_cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxsize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;count_solutions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_vars&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lower_bound&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;upper_bound&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Count the number of solutions to the equation x1 + x2 + ... + xn = target,
    where lower_bound &amp;lt;= xi &amp;lt;= upper_bound for all i.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;num_vars&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&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;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;lower_bound&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;upper_bound&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="n"&gt;solutions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lower_bound&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;upper_bound&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;remaining_target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
        &lt;span class="n"&gt;solutions&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;count_solutions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;remaining_target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_vars&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lower_bound&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;upper_bound&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;solutions&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;count_solutions_with_inclusion_exclusion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_vars&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lower_bound&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;upper_bound&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;total_solutions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;count_solutions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_vars&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;upper_bound&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;bad_solutions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_vars&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;invalid_values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num_vars&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;bad_solutions&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;count_solutions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_vars&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lower_bound&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;upper_bound&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;invalid_values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;total_solutions&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;bad_solutions&lt;/span&gt;

&lt;span class="c1"&gt;# Example usage
&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
&lt;span class="n"&gt;num_vars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Number of solutions: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;count_solutions_with_inclusion_exclusion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_vars&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&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;/p&gt;

&lt;h3&gt;
  
  
  Variation 3: Leetcode Problem &lt;a href="https://leetcode.com/problems/ugly-number-iii/description/" rel="noopener noreferrer"&gt;Ugly Number III&lt;/a&gt;
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;This is a bit advanced. Here, the &lt;code&gt;Inclusion Exclusion Principle&lt;/code&gt; helps us break down the problem so that we can apply binary search, and find the solution.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An &lt;code&gt;ugly number&lt;/code&gt; is a positive integer that is divisible by &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;, &lt;strong&gt;OR&lt;/strong&gt; &lt;code&gt;c&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Given four integers &lt;code&gt;n&lt;/code&gt;, &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;, and &lt;code&gt;c&lt;/code&gt;, return the &lt;code&gt;nth ugly number&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Basically, we can find count of such ugly numbers from &lt;code&gt;1...N&lt;/code&gt; by doing this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;+ count of numbers from 1..n which are divisible by a
+ count of numbers from 1..n which are divisible by b
+ count of numbers from 1..n which are divisible by c
- count of numbers from 1..n which are divisible by a AND b
- count of numbers from 1..n which are divisible by b AND c
- count of numbers from 1..n which are divisible by a AND c
+ count of numbers from 1..n which are divisible by a,b AND c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's call this &lt;strong&gt;&lt;em&gt;&lt;code&gt;f(K)&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;. Now the task is to find out the &lt;strong&gt;&lt;em&gt;least K such that f(K) &amp;gt;= N.&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
We can do a &lt;strong&gt;&lt;em&gt;binary search&lt;/em&gt;&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;gcd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gcd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lcm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gcd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;uglyCountFrom1toN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lcm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lcm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lcm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lcm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lcm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;nthUglyNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
            &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uglyCountFrom1toN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;# print(lo, hi, mid, count, n)
&lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt;
            &lt;span class="c1"&gt;# print(lo, hi)
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Other Variations
&lt;/h3&gt;

&lt;p&gt;You can find several other variations in this &lt;a href="https://cp-algorithms.com/combinatorics/inclusion-exclusion.html#the-formulation-using-venn-diagrams" rel="noopener noreferrer"&gt;wonderful detailed article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

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

&lt;p&gt;The Inclusion-Exclusion Principle is a powerful combinatorics technique that can be applied to a wide range of counting problems. While the principle's formula might seem daunting at first, its systematic approach can simplify complex counting scenarios by breaking them down into manageable parts.&lt;/p&gt;

&lt;p&gt;By understanding the Inclusion-Exclusion Principle and practicing its application, developers can enhance their problem-solving skills and tackle intricate counting problems more effectively. Whether you're working on algorithms, probability theory, or combinatorics-related challenges, mastering this technique can be a valuable asset in your programming toolbox.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References and Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cp-algorithms.com/combinatorics/inclusion-exclusion.html#the-formulation-using-venn-diagrams" rel="noopener noreferrer"&gt;https://cp-algorithms.com/combinatorics/inclusion-exclusion.html#the-formulation-using-venn-diagrams&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codeforces.com/topic/65035" rel="noopener noreferrer"&gt;https://codeforces.com/topic/65035&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/ugly-number-iii/discuss/387539/cpp-Binary-Search-with-picture-and-Binary-Search-Template" rel="noopener noreferrer"&gt;https://leetcode.com/problems/ugly-number-iii/discuss/387539/cpp-Binary-Search-with-picture-and-Binary-Search-Template&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Appendix
&lt;/h2&gt;

&lt;p&gt;Can this be solved using Dynamic Programming ?&lt;br&gt;
Yes.&lt;br&gt;
Let's define &lt;code&gt;dp[i][j]&lt;/code&gt; that stores the count of permutations of length i where the first digit is j.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;factorial&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;count_permutations_dp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;dp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

    &lt;span class="c1"&gt;# Base case: For permutations of length 1, there's 1 permutation for each digit
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="c1"&gt;# Fill the dp table
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# Include permutations where the first digit is greater than 1
&lt;/span&gt;                &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;factorial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Calculate the desired result
&lt;/span&gt;    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Number of permutations (DP): &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;count_permutations_dp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Time complexity: &lt;code&gt;O(n * 10)&lt;/code&gt;&lt;br&gt;
Space complexity:&lt;code&gt;O(n * 10)&lt;/code&gt;, where n is the number of digits (10 in this case).&lt;/p&gt;




&lt;p&gt;This article was originally published on my blog at &lt;a href="https://wewake.dev/posts/inclusion-exclusion-principle/" rel="noopener noreferrer"&gt;https://wewake.dev/posts/inclusion-exclusion-principle/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Find more of my content of my blog, where I share my software development experiences and learnings: &lt;a href="https://wewake.dev/" rel="noopener noreferrer"&gt;https://wewake.dev&lt;/a&gt;&lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>algorithms</category>
    </item>
  </channel>
</rss>
