tooling.report

feature

Splitting modules between dynamic imports

Can modules be split along their exports used by different bundles?

Person in shorts with blue hair walking left

The Test

This test checks to see if exports from a common module can be separated when they are used exclusively by different consuming modules. In this particular variation, an entry module and a lazily-loaded module each use one of the exported objects from a third common module.

index.js

import { foo } from './objects.js';
console.log(foo);
import('./lazy.js');

lazy.js

import { bar } from './objects.js';
console.log(bar);

objects.js

export const foo = { name: 'foo' };
export const bar = { name: 'bar' };

In this example, index.js only uses foo from objects.js, whereas lazy.js only uses bar.

There are a few possible outputs that could be considered ideal:

  • inline foo into the generated bundle for index.js, and bar into the bundle for lazy.js
  • split objects.js into separate bundles for foo and bar, used by the bundles for index.js and lazy.js

Conclusion

browserify

(Browserify test) although browserify does not support this out of the box, tinyify plugin make this possible.

parcel

Apart from the issues encountered in code-splitting/multi-entry, parcel does not split a module.

Issues

rollup

Rollup keeps foo and bar together in the same file.

Issues

webpack

Webpack inlines the common objects.js module as-is into the entry bundle, and the lazy bundle references that copy. While this is a very reasonable behavior, the ideal behavior would have been to "pull apart" the exports of objects.js so they can be used independently. No currently tested bundlers pass this test.