Code Splitting

7. Code Splitting

Code splitting is a technique used to improve the performance of your application by splitting your code into smaller chunks. This allows the browser to load only the necessary parts of your application when they are needed, reducing the initial load time and improving the overall user experience. Turbopack provides built-in support for code splitting, making it easy to implement this optimization.

What is Code Splitting?

Code splitting involves breaking down your application’s code into smaller, manageable chunks. This can be done in several ways:

  1. Entry Points: Splitting code based on multiple entry points.
  2. Dynamic Imports: Splitting code using dynamic import() statements.
  3. Vendor Splitting: Separating third-party libraries from your main application code.

Implementing Code Splitting with Turbopack

  1. Multiple Entry Points: Define multiple entry points to create separate bundles.

    javascript
    	const path = require('path');
    	
    	module.exports = {
    	  entry: {
    	    main: './src/index.js',
    	    admin: './src/admin.js'
    	  },
    	  output: {
    	    path: path.resolve(__dirname, 'dist'),
    	    filename: '[name].bundle.js'
    	  }
    	};

    This configuration will create main.bundle.js and admin.bundle.js, each containing the code specific to their respective entry points.

  2. Dynamic Imports: Use dynamic import() statements to load modules only when they are needed.

    javascript
    	// src/index.js
    	document.getElementById('loadButton').addEventListener('click', () => {
    	  import('./module').then((module) => {
    	    module.load();
    	  });
    	});
    	
    	// src/module.js
    	export function load() {
    	  console.log('Module loaded dynamically!');
    	}

    When the button is clicked, the module.js file will be loaded dynamically, creating a separate chunk for it.

  3. Vendor Splitting: Separate third-party libraries from your main application code to reduce the size of your main bundle.

    javascript
    	const path = require('path');
    	const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    	const HtmlWebpackPlugin = require('html-webpack-plugin');
    	
    	module.exports = {
    	  entry: {
    	    main: './src/index.js',
    	    vendor: ['lodash']
    	  },
    	  output: {
    	    path: path.resolve(__dirname, 'dist'),
    	    filename: '[name].[contenthash].js'
    	  },
    	  optimization: {
    	    splitChunks: {
    	      cacheGroups: {
    	        vendor: {
    	          test: /[\\/]node_modules[\\/]/,
    	          name: 'vendors',
    	          chunks: 'all'
    	        }
    	      }
    	    }
    	  },
    	  plugins: [
    	    new CleanWebpackPlugin(),
    	    new HtmlWebpackPlugin({
    	      template: './src/index.html'
    	    })
    	  ]
    	};

    In this configuration, lodash is separated into a vendors bundle, reducing the size of the main bundle.

Example: Comprehensive Code Splitting

Let’s create a comprehensive example that includes multiple entry points, dynamic imports, and vendor splitting.

javascript
	const path = require('path');
	const { CleanWebpackPlugin } = require('clean-webpack-plugin');
	const HtmlWebpackPlugin = require('html-webpack-plugin');
	
	module.exports = {
	  entry: {
	    app: './src/app.js',
	    admin: './src/admin.js',
	    vendor: ['lodash']
	  },
	  output: {
	    path: path.resolve(__dirname, 'dist'),
	    filename: '[name].[contenthash].js'
	  },
	  module: {
	    rules: [
	      {
	        test: /\.js$/,
	        exclude: /node_modules/,
	        use: 'babel-loader'
	      }
	    ]
	  },
	  optimization: {
	    splitChunks: {
	      cacheGroups: {
	        vendor: {
	          test: /[\\/]node_modules[\\/]/,
	          name: 'vendors',
	          chunks: 'all'
	        }
	      }
	    }
	  },
	  plugins: [
	    new CleanWebpackPlugin(),
	    new HtmlWebpackPlugin({
	      template: './src/index.html'
	    })
	  ]
	};
	
	// src/app.js
	import _ from 'lodash';
	
	document.getElementById('loadButton').addEventListener('click', () => {
	  import('./module').then((module) => {
	    module.load();
	  });
	});
	
	console.log(_.join(['Hello', 'from', 'app'], ' '));
	
	// src/admin.js
	console.log('Hello from admin');
	
	// src/module.js
	export function load() {
	  console.log('Module loaded dynamically!');
	}
  • Entry Points:

    • app.js and admin.js as entry points for different parts of the application.
    • vendor entry point for third-party libraries like lodash.
  • Dynamic Imports:

    • Dynamically import module.js when the button is clicked.
  • Vendor Splitting:

    • Separate lodash into a vendors bundle.

This example demonstrates how to leverage multiple entry points, dynamic imports, and vendor splitting to optimize your application’s performance.