Next.js - Optimize Package Bundlings



In this chapter, we will learn what is package bundling, how to analyze and optimize package bundling in Next.js, and how to use different techniques to optimize package bundling.

What is Package Bundling?

Package bundling is the process of combining multiple JavaScript files and their dependencies into a single file. Next.js automatically analyses the application dependency graph and split code into manageable chunks, and then create separate bundles for client-side and server-side code. In general, Next.js will split your code it to,

  • Client-side bundles for browser execution
  • Server-side bundles for SSR/SSG
  • Route-based chunks for automatic code splitting
  • Shared chunks for commonly used code

Analyzing Package Bundles in Next.js

Before optimizing the package bundling, it is important to understand how Next.js handles package bundling. Next.js provides a built-in tool to analyze the package bundling of your application. It generates a visual report of the size of each package and their dependencies. You can use the information to remove large dependencies, split, or lazy-load your code.

Install and Setup Analysis Tools

To analyze the package bundling, you need to install the analysis tools. Run the following command in your terminal.

npm i @next/bundle-analyzer

After installing the analysis tools, edit the next.config.js file and add the following code:

// File - /next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {}
 
const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
})
 
module.exports = withBundleAnalyzer(nextConfig)

Generate HTML report

After setting up the analysis tools, you can generate an HTML report by running the following command:

$env:ANALYZE="true"; npm run build

Output

Next.js will generate a detailed HTML report of the package bundling. The report shows the size of each package and their dependencies. See the image below for an example.

Next.js Analyze Package Bundling

Optimizing Package Bundles

The section below explain different methods to optimize package bundling in Next.js applications.

Removing Unwanted Packages

Sometimes, you may not need all the packages in a module for your application. You can remove unwanted packages out of bundling using the 'serverExternalPackages' option in your next.config.js. The following code shows how to remove the 'react' package from bundling.

// File - /next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  serverExternalPackages: ['react'],
}

module.exports = nextConfig

Using Dynamic Imports

To further optimize package bundling, you can use dynamic imports to load components on-demand. This can significantly reduce the initial bundle size and improve the performance of your application. Here's an example of how to use dynamic imports:

const DynamicComponent = dynamic(
  () => import('./components/HeavyComponent'),
  {
    loading: () => 

Loading component...

} );

Configuring Optimized Package Imports

Sometimes certain packages, such as icon libraries, may contain hundreds of modules for exporting, which can cause performance issues in development and production. We can optimize the importing of these packages by adding the 'optimizePackageImports' option to our 'next.config.js' file. By this setting this option, Next.js will only load the modules we actually use, while still giving you the convenience of writing import statements with many named exports.

/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    optimizePackageImports: ['icon-library'],
  },
}
 
module.exports = nextConfig

Tree Shaking Enhancement

Tree shaking is automatic optimization technique used by Next.js to eliminate unused dead code from application. It is a powerful way to enhance performance of application. To properly leverage tree shaking, follow the below measures.

  • Use ES Modules (ESM): ESM is a new standard for JavaScript modules that provides better tree shaking capabilities. Next.js prefers ES modules for enhanced tree shaking.
    // Good: ESM
    import { specificFunction } from 'library';
    specificFunction();
    
    // Avoid: CommonJS
    const library = require('library');
    library.specificFunction(); 
    
  • Optimize Third-Party Libraries: Sometimes, Next.js cannot treeshake all the third-party libraries. So you have to avoid importing entire libraries when you only need specific parts.
    // Good: Import specific functions
    import { debounce } from 'lodash-es';
    
    // Avoid: Importing the entire library
    import _ from 'lodash';
    
Advertisements