Shaking the dependency tree
How a small change can have a big impact
Alejandro González S.
Multimedia Engineer
Context
We’re working in a monorepo with Turbo, where multiple Next.js applications are located in the apps
folder.
We have a shared component library in the packages
folder that is used across all these applications.
Context
The development process was being slowed down due to incorrect imports of Material UI Icons in the component library, impacting performance significantly.
THE PROBLEM
Incorrect Import
Why This Is a Problem?
The trailing slash at the end of the import path forces the entire package to be imported instead of just the necessary icons.
Consequence
Each Next.js app was loading and compiling thousands of unnecessary modules, making the development environment slow and heavy for the machine.
correct Import
Why Does the Trailing Slash Matter?
- The trailing slash tells the module system to load everything in the package.
- Instead of fetching just the
CheckBox,
CheckBoxOutlinedBlack
and InfoOutlined it pulls all icons from Material UI, preventing tree shaking from working correctly.
What Is Tree Shaking?
Tree-shaking is a technique used in modern web development to eliminate unused code (dead code) from the final bundle. It can significantly reduce the size of the bundle, resulting in faster load times and better performance.
Dead code refers to the code that is not executed or used during runtime. For example, if a module exports a function that is never called in the application, then that function is considered dead code.
EXAMPLE
The Impact of Not Applying Tree Shaking
Without Tree Shaking you’re pulling in unnecessary code, which:
- Increases bundle size.
- Slows down compilation.
- Causes longer load times.
bundle size without tree shaking
The Fix: Correct Import and Optimization
-
Optimizing Imports:
- We fixed the incorrect imports to ensure tree shaking works as expected, limiting the imported icons to only the required ones.
-
Additional Optimization in Next.js:
- We configured the
optimizePackageImports
setting in Next.js to handle the packages imported from thepackages
folder efficiently. - This ensures that only the necessary modules are loaded in each app.
- We configured the
Instead of grabbing the whole Lego set, we only select the exact pieces we need—this is like optimizing imports.
bundle size with tree shaking
Comparison
-63.2%
-82%
-85.7%
Raw size generated by Webpack.
Size of the file in the browser memory when it is being executed.
Size of the file when compressed to reduce weight in network transfer.
Time and Cost Benefits
-
Time Savings:
- Faster Builds: Reduced unnecessary modules speed up development and build times.
- Quicker to Market: Shorter build times allow for faster feature delivery.
- Significant Improvement: Reduced from compiling 30,000+ modules per app to just 4,000–5,000 modules.
-
Cost Savings:
- Lower Infrastructure Costs: Smaller bundles reduce CPU and memory usage on build servers.
- Bandwidth Efficiency: Smaller bundles mean faster load times and significant bandwidth savings, especially for users with slower connections.
Conclusions
- Lessons Learned: Small mistakes in how you import modules can lead to major performance issues.
- Tree Shaking Matters: Prevents unnecessary code, improving performance.
-
Time and Cost Savings:
- Faster Builds and Quicker Feature Delivery.
- Lower Infrastructure Costs and Reduced Maintenance.
Thank you
Alejandro González Suárez
Multimedia Engineer
Three Shaking
By Alejandro Gonzalez
Three Shaking
- 66