Babel Upgrade & Overhaul

What is Babel?

Babel is a JavaScript transpiler (compiler) that turns bleeding edge JavaScript into JavaScript a browser can execute.

What's that look like?

How do we use Babel?

In the Ember UI (asoc/sa-ui), babel is run whenever ember-cli is run on the codebase

With `ember test`, `ember exam`, `ember serve`, before any of the UI code is used, it is first transpiled by babel

How do we use Babel?

ember-cil reports on the performance of the babel compilation when the ember task is complete

How do we use Babel?

In e2e, it is used twice. Once to allow the e2e framework code...

 

...which runs in node.js, not in the browser...

 

 to be in modern JavaScript.

 

This isn't for the tests themselves, which execute in the browser

 

https://github.rsa.lab.emc.com/asoc/nw-e2e/blob/master/index.js#L1-L3

How do we use Babel?

It is also used by the framework to compile the tests, 1 file at a time, from the `test-src` directory to the `test-lib` directory. This happens before the tests run.

 

 

 

  

 

https://github.rsa.lab.emc.com/asoc/nw-e2e/blob/60203673c11e11b6f6f7ce2a5522a33d82de23b2/lib/util.js#L122-L153

So Babel turns JavaScript with cool modern features into JavaScript that functions in all the browsers.

But who is responsible for inventing the cool modern features?

"TC39 is the committee that evolves JavaScript. Its members are companies. TC39 meets regularly, its meetings are attended by delegates that members send and by invited experts."

TC39

TC39 - What Companies?

The companies that wish to, send representatives to participate in committee meetings.

That is who evolves JavaScript...

 

but how is JavaScript evolved?

They go through a multi-stage process that can, if they are not rejected, take years to result in a approved update to the specification

TC39 - Process

Language Proposals can be made by anyone

  • Just an idea
  • No entrance criteria
  • Proposals in this stage allow for the community and the committee to provide feedback

Stage 0 - Strawperson

  • Requires a "champion" on the TC39 committee who will help guide the proposal through the process
  • During this stage the case is made for addition and major roadblocks are identified
  • To get here, documentation is required. Examples, APIs, algorithms
  • An implementation must exist, either via a polyfill, babel plugin, or some form of demonstration

Stage 1 - Proposal

  • A formal specification, using specific specification language, is created
  • all major semantics, syntax and API are covered, but TODOs, placeholders and editorial issues are expected

  • Committee approvals take place

  • Spec editors approve as well

Stage 2 - Draft

  • If it makes it this far, the committee expects it will get included in the language
  • No TODOs, complete specification text

  • Tests written

  • Compatible implementations exist

Stage 3 - Candidate

Stage 4 - Finished

Our History with Babel

Just minor updates since then

Our History with Babel

What language features are we using that Babel transpiles for us?

Default Parameters

var add = function(a, b) {
  if (b === undefined) {
    b = 5;
  }
  return a + b;
};

add(1, 10) // 11
add(1) // 6
var add = function(a, b = 5) {
  return a + b;
};

add(1, 10) // 11
add(1) // 6
var add = function(obj) {
  return obj.a + obj.b;
};

add({ a: 1, b: 2 }) // 3
var add = function({ a, b }) {
  return a + b;
};

add({ a: 1, b: 2 }) // 3

Parameter Deconstruction

Parameter Deconstruction

var add = function(arr) {
  return arr[0] + arr[1];
};

add([1, 2]) // 3
var add = function([a, b]) {
  return a + b;
};

add([1, 2]) // 3
var add = function({ a: left, b: right }) {
  return left + right;
};

add({ a: 1, b: 2 }) // 3
var add = function({ a: left, b: right = 5}) {
  return left + right;
};

add({ a: 1 }) // 6

Array Spread

var foo = [1, 2, 3];
var bar = [4, 5, 6];

var baz = [...foo, ...bar];
// [1, 2, 3, 4, 5, 6]
var foo = [1, 2, 3];
var bar = [4, 5, 6];

var baz = foo.concat(bar);
// [1, 2, 3, 4, 5, 6]
var foo = [1, 2, 3];
var bar = [4, 5, 6];

var baz = [
  0,
  ...foo, 
  ...bar,
  7, 
  8, 
  9
];
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Object Spread

var foo = { a: 1, b: 2, c: 3 };
var bar = { c: 4, d: 5 };
Object.assign(foo, bar);
// foo = { a: 1, b: 2, c: 4, d: 5 }
var foo = { a: 1, b: 2, c: 3 };
var bar = { c: 4, d: 5 };

var merge = function(obj1, obj2) {
  for (var attr in obj2) { 
    obj1[attr] = obj2[attr]; 
  }
};

merge(foo, bar);
// foo = { a: 1, b: 2, c: 4, d: 5 }
var foo = { a: 1, b: 2, c: 3 };
var bar = { c: 4, d: 5 };
var baz = {
  ...foo,
  ...bar
};

// foo = { a: 1, b: 2, c: 4, d: 5 }
var foo = { a: 1, b: 2, c: 3 };
var bar = { c: 4, d: 5 };
var baz = {
  ...foo,
  ...bar
  e: 7,
  r: 19
};

// foo = { 
//   a: 1, b: 2, c: 4, d: 5, e: 7, r: 19
// }

Shorthand Properties

var foo = 1;
var bar = 2;
var obj = {
  foo: foo,
  bar: bar
};
var foo = 1;
var bar = 2;
var obj = {
  foo,
  bar
};

Arrow Functions

var sum = function(...nums) {
  return nums.reduce(function(a, b) {
    return a + b;
  });
}
var sum = (...nums) => {
  return nums.reduce((a, b) => {
    return a + b;
  });
}
var sum = (...nums) => nums.reduce((a, b) => a + b);

Arrow functions also preserve the calling context for `this`, but we don't have time to talk about JavaScript context.

And those are just some of the ones we use a bunch, there's also...

Those are all the things that, right now, we are transpiling.

If Babel encounters these new features in your JavaScript, it will transform your JavaScript into something else that performs the desired task, but works in all browsers

We use it

Babel also has a polyfill

It adds even more

Polyfill

A polyfill is a piece of code used to provide modern functionality on older browsers that do not natively support it.

Polyfills add the missing feature by including it in the browser, not by changing your code

Polyfill: For Example

`Array.includes` doesn't exist in many browsers, but you can add `Array.includes` by altering the Array prototype

if(!Array.prototype.includes){
   Array.prototype.includes = function(search){
    return !!~this.indexOf(search);
  }
}

Make this the first code executed, and Array.includes becomes available to all code that follows

core-js

Babel's polyfill comes from a library called "core-js". Babel 6 uses core-js 2, which adds a bunch more language features.

And many, many, many, many more

 

https://github.com/zloirock/core-js/tree/v2.6.9

Between transpiling and polyfilling, Babel is busy

But Babel gets us to the point where our modern code works in all browsers

For instance, browsers like IE11

About IE11...

We don't need to support IE 11 anymore

But 3 years ago, 80% of these features needed to be transpiled or polyfilled for other browsers we do support

3 years ago...

How are we looking now?

Everything is supported!!!

Well, almost...

We may have some spread/rest issues in Safari

And then there's the feature we may use more than any other and hasn't been mentioned yet

Decorators

TC39 is struggling with decorators. 5 years after starting, decorators are still at stage 2.

The expected implementation has changed multiple times. It may still be awhile.

With the exception of decorators, and potentially spread/rest...

 

...we can stop transpiling...

 

...remove the polyfill...

 

..and realize the promise Babel makes, to be able to use modern JavaScript until the browsers catch up, at which point remove Babel and It Just Works

And it does Just Work, mostly, and I've got the branch builds to prove it

What does this buy us?

Smaller JS payloads

 

Less JS to evaluate and run

 

Faster native implementations of features

Is that it?

The point of Babel is to allow us to stay on the bleeding edge

Clearly the edge we are on stopped bleeding awhile ago

In the meantime TC39 has mostly been dormant...

...just kidding, there's all kinds of new 💩! 

We haven't updated anything in 3 years and in 3 years all sorts of cool stuff has happened

New Transpiled Stuff

Numeric Separator

100000000000

100_000_000_000

New Transpiled Stuff

Nullish Coalescing Operator

New Transpiled Stuff

Throw Expression

New Transpiled Stuff

Logical Assignment Operators

New Transpiled Stuff

Pipeline Operators

New Transpiled Stuff

Do Expressions

New Transpiled Stuff

Optional Chaining

New Transpiled Stuff

New core-js Polyfills

Set Method Updates

New core-js Polyfills

String.replaceAll

New core-js Polyfills

Array.lastItem/Index

New Polyfills (Stage 1)

New Set/Map functions to match Array options

https://github.com/tc39/proposal-collection-methods

Polyfills

We are using other polyfills of lesser note, check the core-js site for details

 

https://github.com/zloirock/core-js/tree/v3.2.1

When do we get all this?

Ember UI: PR is ready to be submit

e2e: within a few weeks

Challenges?

  • Had to update Jenkins Chrome version
  • Just a few (3ish) tests/code needed to be updated to get tests to pass
  • Safari may struggle with a few things
    • Encourage QE to spend time in Safari/Firefox
    • Any struggle can be immediately remedied by reintroducing a babel plugin

Questions?

Babel Upgrades

By David Bashford

Babel Upgrades

  • 415