babel / preset-modules

A Babel preset that targets modern browsers by fixing engine bugs (will be merged into preset-env eventually)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

bundle size worse than preset-env with esmodules:true ?

frehner opened this issue · comments

I was looking into migrating a project that I maintain to preset-modules. However, I've noticed that the resulting bundle size is actually bigger than when I use preset-env with esmodules:true.

I'm not entirely sure that this is the fault of preset-modules, but I can't seem to figure out why it's behaving the way that it is.

To reproduce:

If you clone single-spa, checkout the 5.0 branch, yarn install, and then run yarn build:analyze, here’s the output (which is using preset-env with targets:{esmodules:true} - focusing only on the esm bundle:

./src/single-spa.js → ./lib/esm/single-spa.dev.js...
-----------------------------
Rollup File Analysis
-----------------------------
bundle size:    42.974 KB
original size:  53.199 KB
code reduction: 19.22 %
module count:   23

Then, if you yarn add -D @babel/preset-modules, change the .babelrc file to use @babel/preset-modules (for the "esm" environment), and then run yarn build:analyze again, here’s the result:

./src/single-spa.js → ./lib/esm/single-spa.dev.js...
-----------------------------
Rollup File Analysis
-----------------------------
bundle size:    45.098 KB
original size:  96.12 KB
code reduction: 53.08 %
module count:   24

If I do a comparison between the two compiled files, it appears that the size difference comes down to two things: 1)there’s an additional function added:

function _typeof(obj) {
  if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
    _typeof = function (obj) {
      return typeof obj;
    };
  } else {
    _typeof = function (obj) {
      return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
    };
  }

  return _typeof(obj);
}

and 2) all the arrow functions were compiled back to normal function s.

I'm not sure why either of these things are happening, especially the transpilation of arrow functions to normal functions.

this sounds like a similar problem to #3. Did you try adding the { loose: true } flag in your config? #3 (comment)

I also don't see any reference to @babel/preset-modules in your package.json.

this sounds like a similar problem to #3. Did you try adding the { loose: true } flag in your config? #3 (comment)

Added it: no change to file size. :(

I also don't see any reference to @babel/preset-modules in your package.json.

From my original post:

Then, if you yarn add -D @babel/preset-modules, change the .babelrc file to use @babel/preset-modules (for the "esm" environment), and then run yarn build:analyze again, here’s the result:

Also to clarify:

this sounds like a similar problem to #3. Did you try adding the { loose: true } flag in your config? #3 (comment)

the difference is that preset-modules decreases the bundle size in that issue. In this issue, preset-modules increases the bundle size

I finally got a minute to look at this more closely, and I realized what the problem is: you're using both @babel/preset-env and @babel/preset-modules. Babel overrides, such as the "esm" one you're using, do not replace plugins and presets wholesale - they get merged. Since @babel/preset-env and @babel/preset-modules are different preset names, they are both included in the resolved configuration.

This will sort itself out once babel/babel#11083 is merged - you'll be able to simply have your "esm" override set { "target": { "esmodules": true }, "bugfixes": true } and it'll apply preset-modules optimizations.

I finally got a minute to look at this more closely, and I realized what the problem is: you're using both @babel/preset-env and @babel/preset-modules. Babel overrides, such as the "esm" one you're using, do not replace plugins and presets wholesale - they get merged. Since @babel/preset-env and @babel/preset-modules are different preset names, they are both included in the resolved configuration.

This will sort itself out once babel/babel#11083 is merged - you'll be able to simply have your "esm" override set { "target": { "esmodules": true }, "bugfixes": true } and it'll apply preset-modules optimizations.

Ah, thanks, I wasn't aware that babel behaved that way.

Thank you for looking into this.

confirmed to work while using latest babel and "bugfixes": true