Parcel: Parcel build includes all Core-js polyfills, or none at all

Created on 4 Nov 2019  路  8Comments  路  Source: parcel-bundler/parcel

馃悰 bug report


When using .babelrc and specifying both targets and useBuiltIns: 'usage' I was expecting parcel to only include the core-js polyfills that were necessary to work with the targeted browsers. Instead all polyfills are including (making build size huge).

Alternatively, if import 'core-js/stable' is removed, then no polyfills are included.

馃帥 Configuration (.babelrc, package.json, cli command)

package.json

{
  "name": "core-js-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@babel/cli": "^7.6.4",
    "@babel/core": "^7.6.4",
    "@babel/preset-env": "^7.6.3",
    "core-js": "^3.3.6",
    "parcel-bundler": "^1.12.4"
  }
}

.babelrc

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": "Chrome >75, IE 11",
        "useBuiltIns": "usage",
        "corejs": 3
      }
    ]
  ]
}

index.js

import 'core-js/stable';

const str = 'Hello';

const arr = Array.from(str);

console.log(`The string contains an H: ${arr.includes('H')}`);

index-alternative.js

const str = 'Hello';

const arr = Array.from(str);

console.log(`The string contains an H: ${arr.includes('H')}`);

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Test of Core JS</title>
</head>
<body>
  <div id="app">Loading</div>
  <script src="index.js"></script>
  <script src="index-alternative.js"></script>
</body>
</html>

馃 Expected Behavior


I'm not exactly sure. I was expecting one of the index.js files to compile to a version where only the required polyfills was included, to polyfill the Array.prototype.From and Array.includes methods for IE 11:

  • require("core-js/modules/es.array.from");
  • require("core-js/modules/es.array.includes");
  • require("core-js/modules/es.string.includes");
  • require("core-js/modules/es.string.iterator");

馃槸 Current Behavior


When running parcel build index.html it outputs both js files:

| filename | size | time | notes
|----------|-----|-----|-----------|
| dist/core-js-test.e032cec8.js | 218.88 KB | 297ms | includes the entirety of core-js |
| dist/index-alternative.5ae4bc85.js | 1.22 KB | 8ms | includes no polyfills at all |

It's not clear from the documentation whether it's required to import core-js (I think it's not?) but if core-js isn't imported then the polyfills aren't included in the built script.

馃實 Your Environment

| Software | Version(s) |
| ---------------- | ---------- |
| Parcel | 1.12.4
| Node | 8.6.0
| npm/Yarn | 5.4.2
| Operating System | Mac OS Sierra 10.12.6

Bug Stale

Most helpful comment

A workaround is described in #3216 by modifying the babel config for an environment you're building for. This works with Parcel 1.

Example:

.babelrc:

{
  "plugins": ["@babel/plugin-transform-object-assign"],
  "env": {
    "production": {
      "presets": [
        [
          "@babel/preset-env",
          {
            "useBuiltIns": "usage",
            "corejs": 3
          }
        ]
      ],
    }
  }
}

Parcel 1 will use this configuration and babel will add the needed polyfill imports for you. The plugins: [] section with at least one plugin is needed to make this work.

The import in index.js:

import 'core-js/stable'

is only needed when you use "useBuiltIns": "entry" (see the entry section in the babel docs) which is a different cup of thea, I can't get this to work with Parcel 1).

Now if you run:

parcel build index.js --no-minify

Babel will then add the following imports (and parcel the bundled modules):

require("core-js/modules/es.array.from");

require("core-js/modules/es.array.includes");

require("core-js/modules/es.string.includes");

require("core-js/modules/es.string.iterator");

All 8 comments

I don't think useBuiltins works in parcel 1 and we kind of don't recommend it in Parcel 2 either as it results in larger bundle sizes due to duplicate polyfills all over the place.

Probably even better to just include everything as that wouldn't cause duplicates.

So the workaround right now is to run Babel manually to derive which polyfills are needed, and then manually include those polyfills in the file so Parcel can bundle them?

If you really wanna do all that work to save a small amount of data over the wire sure.

I'd just include it all

If you really wanna do all that work to save a small amount of data over the wire sure.

I'd just include it all

Please read this carefully: https://medium.com/@addyosmani/the-cost-of-javascript-in-2018-7d8950fbb5d4

core-js has ~180KB of minified filesize, wich equals slightly more than 1.5s of processing time on an average mobile phone, which are added to the time to interactive. It might seem like a rather small amount of data, but it is a huge downer on load times.

@Keyes I鈥檓 aware of the impacts this has on performance.

Just kind of meant it鈥檚 probably not worth it although it highly depends on target audience. For a business app it probably does not matter. If you鈥檙e mainly targeting mobile every bit counts though as you pointed out.

Eventually tooling should do all these tweaks automatically. We鈥檙e receiving a lot of help on this field for Parcel 2.

Sent with GitHawk

This is already resolved in the upcoming Parcel 2 and perhaps won鈥檛 be fixed in Parcel 1.

A workaround is described in #3216 by modifying the babel config for an environment you're building for. This works with Parcel 1.

Example:

.babelrc:

{
  "plugins": ["@babel/plugin-transform-object-assign"],
  "env": {
    "production": {
      "presets": [
        [
          "@babel/preset-env",
          {
            "useBuiltIns": "usage",
            "corejs": 3
          }
        ]
      ],
    }
  }
}

Parcel 1 will use this configuration and babel will add the needed polyfill imports for you. The plugins: [] section with at least one plugin is needed to make this work.

The import in index.js:

import 'core-js/stable'

is only needed when you use "useBuiltIns": "entry" (see the entry section in the babel docs) which is a different cup of thea, I can't get this to work with Parcel 1).

Now if you run:

parcel build index.js --no-minify

Babel will then add the following imports (and parcel the bundled modules):

require("core-js/modules/es.array.from");

require("core-js/modules/es.array.includes");

require("core-js/modules/es.string.includes");

require("core-js/modules/es.string.iterator");

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs.

Was this page helpful?
0 / 5 - 0 ratings