webpack代码拆分

469 阅读2分钟

三种通用方式

  • 入口点:使用entry配置手动拆分代码。
  • 防止重复:使用Entry依赖项或SplitChunksPlugin对重复数据块进行重复数据删除和拆分。
  • 动态导入:通过模块内的内联函数调用拆分代码。

入口点

拆分代码的最简单,最直观的方法。更手动的,并且有一些陷阱。

1.项目结构

2.index.js

import _ from 'lodash';

function component() {
    const element = document.createElement('div');
    element.innerHTML = _.join(['Hello', 'index.js'], ' ');
    return element;
  }
  
  document.body.appendChild(component());

3.print.js

import _ from 'lodash';

console.log(_.join(['Hello', 'print.js'], ' '));

4.webpack.config.js

 const path = require('path');
 module.exports = {
  entry: {
        index: './src/index.js', // 入口1
        print: './src/print.js', // 入口2
  },
  mode: 'development',
  output: {
    filename: '[name].bundle.js',
     path: path.resolve(__dirname, 'dist'),
   },
 };

5.构建结果

dist下面产生两个包文件

6.陷阱注意

index.js,print.js都包含了lodash,即上述所说,这种方式如果条目块之间有任何重复的模块,则它们将同时包含在两个包文件中。

防止重复打包文件

1.Entry dependencies重复避免

const path = require('path');
 
 module.exports = {
   mode: 'development',
   entry: {
    index: {
      import: './src/index.js',
      dependOn: 'shared',
    },
    print: {
      import: './src/print.js',
      dependOn: 'shared',
    },
    shared: 'lodash',
   },
   output: {
     filename: '[name].bundle.js',
     path: path.resolve(__dirname, 'dist'),
   },
 };
1.1单页面多个入口时

还需配置optimization.runtimeChunk: 'single',在output后配置如下:

  optimization: {
    runtimeChunk: 'single',
  },
1.2打包结果

此时项目结构如下:

2. SplitChunksPlugin

SplitChunksPlugin可以将共同的依赖提取到一个现有的条目块或一个全新的块。

2.1 配置optimization.splitChunks
  const path = require('path');

  module.exports = {
    mode: 'development',
    entry: {
      index: './src/index.js',
      another: './src/print.js',
    },
    output: {
      filename: '[name].bundle.js',
      path: path.resolve(__dirname, 'dist'),
    },
    optimization: {
      splitChunks: {
      chunks: 'all',
      },
    },
  };

我们已经把lodash从index.bundle,print.bundle等主bundle中移除到一个单独的块中.

将CSS从主应用程序中分离出来

mini-css-extract-plugin

动态导入

动态代码分割:import()语法进行动态导入【推荐】;特定于webpack的方法时可使用遗留的require.ensure。

1. import()语法进行动态导入

1.1 配置如下

项目目录

webpack.config.js

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

index.js

  async function getComponent() {
    const element = document.createElement('div');
    const { default: _ } = await import('lodash');
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');
    return element;
  }
  
  getComponent().then((component) => {
    document.body.appendChild(component);
  });
1.2 打包结果