Javascript Polyfills und Transpiler

Polyfill vs Babel Transpiler oder Compiler

Die aktuellen Browser sind richtig gut. Wir können all die modischen Konstrukte wie promises, fetch und arrow functions, const und let benutzen und sie funktionieren in allen modernen Browsern.

Aber es gibt immer noch Besucher mit alten IEs oder Safaris, mit Rechnern, auf denen Firefox seit ewig und drei Jahren seine Runden zieht.

Auf kommerziellen Seiten müssen wir Rücksicht nehmen: Entweder müssen wir die Script-Elemente benutzen, die allen gängigen Browsern zur Verfügung stehen oder nach den neusten Standards skripten, aber dafür sorgen, dass Scripte auch in alten Browsern funktionieren.

Um neue Konstrukte in Javascript auch für alte Browser gängig zu machen, brauchen wir entweder Polyfills oder Transpiler (Trans-Compiler).

Polyfills

Ein Polyfill definiert neue Objekte oder Methoden für ältere Browser. Polyfills gibt es wie Sand am Meer für die verschiedensten Funktionen, aber natürlich bringen auch sie den ganz alten Browser keine neuen Kunststücke bei.

Transpiler – Babel

class BetterArray {
  constructor(arr) {
    this.arr = arr;
  }
  has(item) {
    return this.arr.includes(item);
  }
}

const myArray = new BetterArray([1, 2, 3]);

console.log(myArray.has(2)); // true
console.log(myArray.has(4)); // false

Quelle: davidgilbertson/babel-old-code.js

Babel class BetterArray

Ein Transpiler übersetzt die Syntax, die alte Browser nicht in petto haben und übersetzt sie in die Syntax, die sie verstehen. Babel ist so ein Übersetzer, der modernes Javascript in langatmige Monster übersetzt.

"use strict";
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var BetterArray = function () {
  function BetterArray(arr) {
    _classCallCheck(this, BetterArray);

    this.arr = arr;
  }

  _createClass(BetterArray, [{
    key: "has",
    value: function has(item) {
      return this.arr.includes(item);
    }
  }]);

  return BetterArray;
}();

var myArray = new BetterArray([1, 2, 3]);

console.log(myArray.has(2)); // true
console.log(myArray.has(4)); // false

Wer sparen will, kann Babel auf die für ihn relevanten Features und Browser reduzieren. Beschränken wir uns auf die letzten zwei Versionen der modernen Browser und IE11:

"babel": {
  "presets": [
    [
      "env",
      {
        "targets": {
          "browsers": [
            "last 2 versions",
            "IE >= 11"
          ]
        },
        "useBuiltIns": true
      }
    ]
  ]
},

Das reduziert die Babel-Last von 127 KB auf 121 KB. Oh. Oder besser: Oh weia.

Polyfill oder Transpiler?

Die Faustregel lautet: Wenn es ein neues Objekt oder eine neue Methode ist, kann ein Polyfill die Neuzeit einführen. Wenn es neue Syntax ist, brauchen wir einen Transpiler.

LeistungsmerkmalPolyfillTranspiler
Map
Promise
Fetch
String.prototype.padEnd()
Array.prototype.includes()
Promise
Fetch
String.prototype.padEnd()
class
const und let
object rest / spread
Arrow functions () => {}

Ein gute – wenn nicht die beste – Quelle für Polyfills ist Github. So gibt es z.B. ein Polyfill für scrollIntoView.

POLYFILL TRANSPILER