code splittingのchunkのしくみ

疑問

異なるchunkA Bそれぞれで、同じモジュール(例えばlodash)をimportしている場合、ビルド後のA Bのサイズはどうなるのか

Answer

  • require.ensure System.import bundle-loader どれを用いても結果は変わらず。
  • A B 双方「200kb」ほどサイズ増加しており、両方でlodashを別々にloadしていることが伺える。

Code Splitting (公式)

Chunk optimization

If two chunks contain the same modules, they are merged into one. This can cause chunks to have multiple parents.

If a module is available in all parents of a chunk, it’s removed from that chunk.

If a chunk contains all modules of another chunk, this is stored. It fulfills multiple chunks.

とあるが、lodashの場合はうまくいかないということ?

追記(19:09)

→どうやらそういうわけではなく、共通部分があってもentry chunkには決してmergeされない仕様らしい。つまり、複数の孫モジュール間での共通部分は抽出されて別のchunkとしてmergeされるはず…(親=entry chunk)

Webpack will take care of it by merging chunks (it will prefer merging chunk that have duplicate modules). Nothing will be merged into the entry chunk, so as not to impact initial page loading time.

optimization · webpack/docs Wiki · GitHub

試した

下記のように

  • entry chunk --> Home --> lodash
  • entry chunk --> About --> lodash

というchunkわけをしてビルドした結果。(lodashは単一ファイルのchunk)

entry chunk
------
function resolveIndex(nextState, cb) {
  System.import('../components/Home')
    .then(module => cb(null, module.default))
    .catch(handleError);
}

function resolveAbout(nextState, cb) {
  System.import('../components/About')
    .then(module => cb(null, module.default))
    .catch(handleError);
}
components/Home
------
import Home from './Home';
// sync loading is not merged...
// import _ from 'lodash';

// async loading is merged into a new chunk !!
System.import('lodash')

export default Home;
components/About
------
import About from './About';

// sync loading is not merged...
// import _ from 'lodash';

// async loading is merged into a new chunk !!
System.import('lodash')

export default About;

みごと2-c87d85131caeed2b63ea.jsにlodashのコードがmergeされている。

Version: webpack 2.1.0-beta.20
Time: 5341ms
                            Asset       Size  Chunks             Chunk Names
        0-ad0eb1228846aae746d1.js  549 bytes       0  [emitted]
        1-2fcd73cc179c047a58c9.js  449 bytes       1  [emitted]
        2-c87d85131caeed2b63ea.js    69.5 kB       2  [emitted]
     main-d489ed5a12ea8ccac8d5.js     220 kB       3  [emitted]  main
    main-d489ed5a12ea8ccac8d5.css    2.37 kB       3  [emitted]  main
main-d489ed5a12ea8ccac8d5.css.map  106 bytes       3  [emitted]  main

さらに追記:アグレッシブにOptimizeする

DedupePlugin

https://webpack.github.io/docs/list-of-plugins.html#dedupeplugin

AggressiveMergingPlugin

https://webpack.github.io/docs/list-of-plugins.html#aggressivemergingplugin