关于webpack打包的一些困惑

webpack进行打包的时候遇到的一些?困惑:

webpack打包提供了:

  • 通过commonChunksPlugin插件可以将多个entry chunk中复用的module抽离为公共的chunk;

  • 通过require.ensure这个api去自定义code spiltting的分割点,webpack完成分隔chunk的功能。

现在想到了这样一个问题:
lib文件夹下是基础js库,例如loadsh等等,在components文件夹下是组件库,例如dialog等等。

现在一共有9个页面,9个页面都使用到了lib中的基础库,在从第4个页面开始才用到了components组件库。

因为webpack是分析不同js文件的相互依赖,然后进行打包的。因此在我使用了commonChunksPlugin后,会将lib中的基础js库和components中的组件库全部打包到一个文件中。

现在我想达到的效果就是,将lib中的基础js库打包到common chunk当中,入口页面一加载的时候就加载这个common chunk, 然后将components中的组件库另外单独打包到一个components文件当中,当加载到第4个页面时,才会加载这个components文件,而不是像之前的初始页面一加载的时候就会将components也加载进来。

所以这种需求的话webpack应该如何配置呢?还是就没法做到,是否是因为webpack的打包机制所决定的。

阅读 5.5k
3 个回答

有两种方式:

1. 多个 Common Chunk (lib 一个、component 一个)
module.exports = {
  entry: {
    lib: ['./lib/a.js', './lib/b.js'],
    component: ['./component/a.js', './component/b.js'],
    'page/home': './page/home.js',
    'page/list': './page/list.js'
  },
  output: {
    path: join(__dirname, 'dist'),
    filename: '[name].js'
  },
  module: {
    loaders: [{
      test: /\.js[x]?$/,
      exclude: /node_modules/,
      loader: 'babel-loader'
    }]
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      names: ['component', 'lib'],
      minChunks: Infinity
    })
  ]
};

相应的页面:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Home page</title>
</head>
<body>
  <script src="/lib.js"></script>
  <script src="/component.js"></script>
  <script src="/page/home/index.js"></script>
</body>
</html>
2. lib 为 Common,component 动态加载
module.exports = {
  entry: {
    lib: ['./lib/a.js', './lib/b.js'],
    'page/home': './page/home.js',
    'page/list': './page/list.js'
  },
  output: {
    path: join(__dirname, 'dist'),
    filename: '[name].js'
  },
  module: {
    loaders: [{
      test: /\.js[x]?$/,
      exclude: /node_modules/,
      loader: 'babel-loader'
    }]
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'lib',
      minChunks: Infinity
    })
  ]
};

异步加载:

// home.js
import libA from '../../lib/a';

import('../../component/b').then(module => {
  module.default();
  libA();
});

相应的页面

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Home page</title>
</head>
<body>
  <script src="/lib.js"></script>
  <script src="/page/home/index.js"></script>
</body>
</html>
附录(详细的 Demo 源码)
  • libcomponents 配置成2个 entry point

  • componentsrequire.ensure 动态加载

无论哪种方式都需要修改源码,打包策略和代码组织息息相关

额,今天突然转念一想,如果在从第4个页面开始都需要的组件,在路由当中通过使用require.ensure()即可完成对components的分包:

    页面4:
        require.ensure([], function() {
            require('module/route4/controller');
        }, 'components');
        
    页面5:
        require.ensure([], function() {
            require('modules/route5/controller');
        }, 'components');

webpack分析依赖的时候,会自动将route4route5中共用的components单独抽离出来到components文件当中(require.ensure接收的第三个参数需要一致),加载route4时异步加载这个文件。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题