阿里云主机折上折
  • 微信号
Current Site:Index > Webpack's code splitting mechanism

Webpack's code splitting mechanism

Author:Chuan Chen 阅读数:56901人阅读 分类: 构建工具

Webpack's Code Splitting Mechanism

Webpack's code splitting allows code to be divided into multiple bundles, enabling on-demand or parallel loading. This mechanism effectively reduces initial load times and improves application performance. Code splitting is primarily achieved through three methods: entry points, preventing duplication, and dynamic imports.

Entry Point Splitting

The most basic form of code splitting is achieved by configuring multiple entry points. By setting multiple entry properties in webpack.config.js, Webpack generates separate bundles for each entry.

// webpack.config.js
module.exports = {
  entry: {
    app: './src/app.js',
    admin: './src/admin.js'
  },
  output: {
    filename: '[name].bundle.js',
    path: __dirname + '/dist'
  }
};

This approach is straightforward but has two issues: 1) If entry chunks share duplicate modules, they will be bundled redundantly; 2) It lacks flexibility and cannot dynamically split code.

SplitChunksPlugin Optimization

Starting with Webpack 4, the built-in SplitChunksPlugin is used to extract shared dependencies and third-party libraries. This plugin automatically identifies duplicate modules and optimizes them.

// webpack.config.js
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      minSize: 30000,
      maxSize: 0,
      minChunks: 1,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      automaticNameDelimiter: '~',
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    }
  }
};

Configuration parameters explained:

  • chunks: 'all' optimizes all chunks.
  • minSize sets the minimum size for generated chunks.
  • cacheGroups defines how modules are split.
  • priority determines which cache group a module should be placed in.

Dynamic Imports

Dynamic imports are the most common method for code splitting, achieved using the ES proposal's import() syntax or Webpack-specific require.ensure.

// Using import()
button.addEventListener('click', () => {
  import('./math.js').then(math => {
    console.log(math.add(16, 26));
  });
});

// Using require.ensure
button.addEventListener('click', () => {
  require.ensure([], require => {
    const math = require('./math.js');
    console.log(math.add(16, 26));
  });
});

Webpack splits dynamically imported modules into separate chunks, loading them on-demand at runtime. This approach is particularly suitable for route-level code splitting.

Magic Comments

Magic comments allow customization of dynamically imported chunk names and other behaviors.

import(
  /* webpackChunkName: "math" */
  /* webpackPrefetch: true */
  './math.js'
).then(math => {
  console.log(math.add(16, 26));
});

Common magic comments:

  • webpackChunkName: Specifies the chunk name.
  • webpackPrefetch: Prefetches resources.
  • webpackPreload: Preloads resources.
  • webpackMode: Specifies the loading mode.

Preloading and Prefetching

Webpack 4.6+ supports preloading and prefetching resources to further optimize loading performance.

import(/* webpackPrefetch: true */ 'LoginModal');

Differences:

  • Prefetch: Loads during idle time with low priority.
  • Preload: Loads in parallel with the parent chunk with high priority.

Third-Party Library Splitting

Splitting third-party libraries into separate bundles is a common optimization technique, configured using cacheGroups:

// webpack.config.js
module.exports = {
  optimization: {
    splitChunks: {
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
          name: 'vendor',
          chunks: 'all'
        }
      }
    }
  }
};

Persistent Caching

Configure filename for long-term caching:

output: {
  filename: '[name].[contenthash].js',
  chunkFilename: '[name].[contenthash].js'
}

contenthash generates a hash based on file content, ensuring filenames change only when content changes.

Lazy Loading React Components

Combine React.lazy for component-level code splitting:

const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <OtherComponent />
      </Suspense>
    </div>
  );
}

Route-Level Code Splitting

Implement route-level splitting in React Router:

const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));

function App() {
  return (
    <Router>
      <Suspense fallback={<div>Loading...</div>}>
        <Switch>
          <Route exact path="/" component={Home}/>
          <Route path="/about" component={About}/>
        </Switch>
      </Suspense>
    </Router>
  );
}

Webpack Bundle Analysis

Use webpack-bundle-analyzer to analyze bundle results:

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
  plugins: [
    new BundleAnalyzerPlugin()
  ]
};

This tool generates a visual report to help identify optimization opportunities.

Common Issues and Solutions

  1. Code Splitting Not Working

    • Verify dynamic import syntax is used.
    • Ensure SplitChunksPlugin is configured correctly.
    • Confirm optimization.splitChunks.chunks is not set to 'initial'.
  2. Duplicate Dependencies

    • Adjust cacheGroups priorities.
    • Check for multiple versions of the same package.
    • Use resolve.alias to unify versions.
  3. Loading Order Issues

    • Use webpackInclude/webpackExclude to limit import scope.
    • Adjust preloading/prefetching strategies.
    • Consider using webpackMode parameter in import().

Advanced Optimization Techniques

  1. Layered Bundling: Separate node_modules, business code, and third-party libraries into distinct bundles.
  2. On-Demand Polyfills: Use @babel/preset-env with useBuiltIns: 'usage'.
  3. Shared Modules: Use shared cache groups in multi-page applications.
  4. CSS Code Splitting: Achieve CSS splitting with mini-css-extract-plugin.
// Layered bundling example
cacheGroups: {
  corejs: {
    test: /[\\/]node_modules[\\/]core-js[\\/]/,
    name: 'core-js',
    chunks: 'all'
  },
  lodash: {
    test: /[\\/]node_modules[\\/]lodash[\\/]/,
    name: 'lodash',
    chunks: 'all'
  }
}

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.