Material-components-web: Babel config should follow browsers specification

Created on 8 Mar 2017  路  6Comments  路  Source: material-components/material-components-web

Using babel-preset-es2015 is now considered bad practice, and babel-preset-env is preferred.

This is because the env plugin allows for specifying a list of target browsers, which enables babel to automatically determine which plugins and polyfills to use, resulting in less code. https://github.com/babel/babel-preset-env

It will also enable code size to go down as we remove supported browsers in the future (looking at you, IE 11).

Tasks:

  • [ ] Replace babel-preset-es2015 by babel-preset-env in package.json
  • [ ] Set up an env configuration in package.json matching our supported browsers (validate string at http://browserl.ist/)
  • [ ] Ensure the output includes no polyfills, adjusting options if needed (see useBuiltIns and exclude options)
  • [ ] Ensure output remains sane and works across all supported browsers
  • [ ] (Optional) Measure generated JS size delta and brag about it on this issue :) Note that this may actually be small because of IE11 :(
help wanted techdebt

All 6 comments

I've done some experimentation and these are my findings.

Before:

-rw-r--r--  1 User  staff  248529 Mar  9 15:40 build/material-components-web.js
-rw-r--r--  1 User  staff   99880 Mar  9 15:40 build/material-components-web.min.js

After:

-rw-r--r--  1 User  staff  248529 Mar  9 15:40 build/material-components-web.js
-rw-r--r--  1 User  staff   99880 Mar  9 15:40 build/material-components-web.min.js

So that's a _whopping_ difference of 0 bytes.

As an experiment I removed IE 11 and got this:

-rw-r--r--  1 User  staff  247917 Mar  9 15:43 build/material-components-web.js

A difference of 612 bytes, but with a big caveat. It will fail on creating the .min.js file, as webpack uses uglifyjs internally to minify the code and it doesn't yet support es2016 (or later) code.

So switching from babel-preset-es2015 to babel-preset-env isn't viable until webpack/uglifyjs support es2016 (and newer) imho.

Thanks for looking into this, @BBosman! uglify not supporting ES2015 is a known issue, yes, good point :-/

If we are to this we'll need to add investigating a replacement, such as babili to the list of tasks.

@BBosman if you'd like to try out babili instead of uglifyJS as our minifier, and it doesn't lead to an increase in overall code size, we'd definitely consider making that change to facilitate this. Is this something you'd be interested in looking into?

It does look like there's a babili plugin for webpack

@traviskaufman It might not even be necessary, as afaik you can run it through Babel with babel-preset-babili.

Switching tot babili turns out to be more difficult than it sounds. If you pass -p to webpack it will always load the UglifyJsPlugin, resulting in errors. So to switch to babili we would need to drop the -p switch. This would mean that we would have to mimic all the other things -p does as well, like minifying the css.

Another, easier, option is to manually install the UglifyJsPlugin, which allows you to specify the version of UglifyJs through a peer dependency. Which we can then point to the Harmony branch of UglifyJs, which has ES2015+ support. Downside to this is that the package.json will point to a git url instead of a npm package.

Resulting package.json excerpt:

  "devDependencies": {
    ...
    "babel-loader": "^6.2.10",
    "babel-plugin-transform-object-assign": "^6.8.0",
    "babel-preset-env": "^1.2.1",
    ...
    "uglify-js": "git://github.com/mishoo/UglifyJS2.git#harmony",
    "uglifyjs-webpack-plugin": "^0.3.0",
    ...
  },
  "babel": {
    "presets": [
      [
        "env",
        {
          "modules": false,
          "targets": {
            "browsers": [
              "last 2 versions",
              "not ie 10"
            ]
          }
        }
      ]
    ],
    "plugins": [
      "transform-object-assign"
    ],
    "env": {
      "test": {
        "presets": [
          "env"
        ]
      }
    }
  },

Is this a viable option?

On the other hand, it's also possible to stick to babel-preset-es2015 for now, because as long as IE11 support is still required switching won't give us a single byte of benefit. And maybe by the time IE11 support is dropped, UglifyJs will have native ES2016 support.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ronnieroyston picture ronnieroyston  路  3Comments

trimox picture trimox  路  4Comments

broros picture broros  路  3Comments

jimyhdolores picture jimyhdolores  路  3Comments

m-alzam picture m-alzam  路  3Comments