ES2015

ES2015 (früher ES6) ist ein großartiger Fortschritt für die JavaScript-Sprache. Es bietet neue Features und Zucker für Muster, für die in ES5 umfangreiche Standardklauseln erforderlich waren. Dazu gehören Klassen, Pfeilfunktionen und Module. In dieser Folge geht es um Tools, mit denen wir ES2015 beim Erstellen von JavaScript-Webanwendungen optimal nutzen können.

Transpilation mit Babel

Obwohl JavaScript-Engines große Fortschritte bei der nativen Implementierung von ES2015-Funktionen machen, gibt es ein Problem. Wenn Sie alle Features heute nutzen möchten, müssen Sie Ihren Code zurück in ES5 transpilieren, damit er von aktuellen Browsern interpretiert werden kann. Glücklicherweise gibt es Tools wie Babel, die diesen Prozess nahezu mühelos machen.

Babel im Build-Prozess verwenden

Mit Babel können Sie JavaScript-Code, der mit ES2015-Features geschrieben wurde, zurück in ES5 transpilieren, sodass er in Browsern funktioniert, die diese Funktionen derzeit nicht unterstützen. So können Sie Babel zu Ihrem Build-Prozess hinzufügen.

var gulp = require('gulp');
var babel = require('gulp-babel');

gulp.task('default', function () {
    return gulp.src('src/app.js')
        .pipe(babel())
        .pipe(gulp.dest('dist'));
});

Die einzige Funktion, die Babel nicht übertragen kann, sind Module. Mit Modulen in ES6 können Sie Klassen erstellen und Klassen zwischen Dateien exportieren / importieren. Wenn Sie Module transpilieren möchten, übergeben Sie Ihren JavaScript-Code über Browserify. Dabei werden die Dateien zusammengeführt und dann über Babelify übergeben. Dies ist eine Version von Babel, die die Ausgabe von Browserify verarbeiten kann.

var babelify = require('babelify');
var source = require('vinyl-source-stream');
var browserify = require('browserify');

gulp.task('babelify', function() {
  browserify({ entries: './src.js', debug: true })
    .transform(babelify)
    .bundle()
    .pipe(source('bundle.js'))
    .pipe(gulp.dest('./dist/js/'));
});

Mehrere JavaScript-Dateien

Im obigen Beispiel müssen Sie eine bestimmte Datei definieren, was etwas lästig werden kann. Matt führt in Gulp folgende Schritte aus, um Dateien zu suchen und zu transpilieren, die mit .es6.js enden.

var config = {
  src: 'src/scripts',
  dest: 'dist/scripts'
};
var es6FileGlob = '/**/*.es6.js';

var gulp = require('gulp');
var plugins = require('gulp-load-plugins')();
var glob = require('glob');
var path = require('path');
var browserify = require('browserify');
var babelify = require('babelify');
var source = require('vinyl-source-stream');

// Takes an array of bundles to run through browserify and babelify
function transpileES6Modules(browserifyFileEntries) {
  browserifyFileEntries.forEach(function(fileEntry) {
    var browserifyBundle = browserify({
        entries: [fileEntry.srcPath]
      })
      .transform(babelify);

    var finalStream = browserifyBundle.bundle()
      .on('log', plugins.util.log.bind(plugins.util, 'Browserify Log'))
      .on('error', plugins.util.log.bind(plugins.util, 'Browserify Error'))
      .pipe(source(fileEntry.outputFilename));

    return finalStream.pipe(gulp.dest(fileEntry.dest));
  });
}

// This takes a source path and finds all files ending
// with .es6.js and creates the bundles to run through browserify
// and babelify
function handleES6Scripts(srcPath) {
  var browserifyFileEntries = [];

  var es6Filepaths = glob.sync(srcPath + es6FileGlob);
  es6Filepaths.forEach(function(filepath) {
    var filename = path.basename(filepath);
    var directoryOfFile = path.dirname(filepath);
    var relativeDirectory = path.relative(
      srcPath,
      directoryOfFile);

    // Create an object and add to the browserify bundle array
    browserifyFileEntries.push({
      srcPath: './' + filepath,
      outputFilename: filename,
      dest: path.join(config.dest, relativeDirectory)
    });
  });

  transpileES6Modules(browserifyFileEntries);
}

gulp.task('scripts:es6', ['scripts:lint'], function(cb) {
  handleES6Scripts(config.src);

  cb();
});

Linting- und Stilprüfungen

Beim Linting Ihres Codes auf mögliche Probleme und die Stilcompliance haben Sie mehrere Möglichkeiten.

JSHint und JSCS

JSHint und JSCS sind die häufigsten Tools, die für die heutige JavaScript-Stilüberprüfung verwendet werden.

JSHint weist auf mögliche Probleme in Ihrem Code sowie auf Muster hin, die im Allgemeinen als schlechte Praxis angesehen werden.

JSCS prüft den Stil Ihres Codes. Dazu gehört unter anderem, dass nur Tabulatoren oder Leerzeichen verwendet und Leerzeichen an konsistenten Orten platziert werden.

Um JSHint und JSCS mit ES2015-Code zu verwenden, müssen Sie "esnext": true zu den Dateien .jshintrc und .jscsrc hinzufügen.

ESLint

ESLint ist ein alternativer Linter und eine Stilprüfung in einem. Dieses Tool nimmt viel auf und bietet im Vergleich zu JSHint einige nützliche Funktionen, wie etwa die Anzeige von Umgebungen, für die JavaScript geschrieben ist, und die Fehler-/Warnungsstufe für bestimmte Probleme festzulegen.

ESLint ist vollständig anpassbar und bietet benutzerdefinierte Linting-Regeln, mit denen Sie die Kontrolle darüber haben, ob Optionen über die Konfigurationsdateien ab- oder abgeschwächt werden können. Wenn Sie React verwenden, funktioniert ESLint auch mit JSX.

Das Einrichten von ESLint in Ihrem Build-Prozess ist auch nicht allzu schwierig.

var gulp = require('gulp'),
    eslint = require('gulp-eslint');

gulp.task('lint', function () {
    return gulp.src(['js/**/*.js'])
        // eslint() attaches the lint output to the eslint property
        // of the file object so it can be used by other modules.
        .pipe(eslint())
        // eslint.format() outputs the lint results to the console.
        // Alternatively use eslint.formatEach() (see Docs).
        .pipe(eslint.format())
        // To have the process exit with an error code (1) on
        // lint error, return the stream and pipe to failOnError last.
        .pipe(eslint.failOnError());
});

gulp.task('default', ['lint'], function () {
    // This will only run if the lint task is successful...
});

Das Babel-Team pflegt babel-estlint, ein Tool, mit dem Sie gültigen Babel-Code mithilfe von ESLint Linting durchführen können. ESLint unterstützt zwar benutzerdefinierte Parser, aber ein Teil der von Babel unterstützten Syntax wird nicht direkt von ESLint unterstützt. Es ist also eine weitere Option, wenn Sie noch mehr Flexibilität benötigen. Sie können dies einrichten, indem Sie den Abschnitt parser der Datei .eslintrc anpassen:

{
  "parser": "babel-eslint",
  "rules": {
    "strict": 0
  }
}

Dan Abramov hat in Lint Like It's 2015 einen tollen Bericht über die Einrichtung von ESLint und babel-eslint verfasst. Außerdem wird beschrieben, wie Sie SublimeLinter-eslint in Ihren Workflow für die Linting-Unterstützung von ES2015 in Sublime Text einbinden.

Welches Tool sollten Sie verwenden? Probieren Sie sie aus und entscheiden Sie sich dann für das, was für Sie am besten funktioniert.

ES2015 Syntaxhervorhebung

Natürlich sollte der ES2015-Code korrekt in der Syntax hervorgehoben sein. Am besten verwenden wir babel-sublime, das über die Paketsteuerung installiert werden kann. Bei der Einrichtung sollten Sie diese als Standardeinstellung für alle Dateien festlegen, die Sie hervorheben müssen. Dies schließt JS ein, kann aber auch JSX abdecken,

Dokumentation zu ES2015

In der Vergangenheit haben wir uns bei der Dokumentation unseres JavaScript-Codes recht häufig auf JSDoc verlassen. Leider gibt es offene Probleme für die Unterstützung von ES2015 (aufgrund in JSDoc 3). Es gibt jedoch immer mehr Alternativen, während wir auf die Aktualisierung warten. Eine dieser Möglichkeiten ist ESDoc. Jonathan Creamer hat vor Kurzem eine Veröffentlichung dazu erarbeitet, die sich durchlesen lohnt.

Gulp.js-Dateien mit Babel erstellen

Wenn Sie Gulp für Ihren Build-Prozess verwenden, können Sie Gulpfiles jetzt mit jeder von Babel unterstützten Syntax erstellen. Wir führen diesen Vorgang im Web Starter Kit durch und es ist relativ einfach einzurichten. Wenn Sie eine aktuelle Version von Gulp und der Gulp-Befehlszeile verwenden, benennen Sie gulpfile.js einfach in gulpfile.babel.js um. Gulp interpretiert und transpiliert dann Ihre ES2015-gulpfile automatisch mit Babel.

Beliebte ES2015-Funktionen

Module

Mit Modulen können Sie Werte, Funktionen und Klassen aus einer Datei exportieren, um sie in eine andere Datei zu importieren.

export function exampleFunction() {
  console.log('I\'m an example. #TrueStory');
}



import { exampleFunction } from './example-function';
import BaseController from './base-controller';

export default class ExampleController extends BaseController {
  constructor() {
    super();

    exampleFunction();
  }

  doSomething() {
    console.log('What should I do? Change the DOM? Print a dancing shark to the console?');
  }
}

Auf dieser Website finden Sie einige gute Beispiele und Erklärungen zu Modulen.

Vorlagenstrings

Mit Vorlagenstrings können Sie den Port eines Strings durch eine Variable ersetzen.

// Simple string substitution
var name = "Brendan";
console.log('Yo, ${name}!');

// => "Yo, Brendan!"

Das Tolle an Vorlagenstrings ist, dass die Substitution eine JavaScript-Ausführung ist, d. h., Sie können Funktionen oder Inline-Ausdrücke verwenden.

var a = 10;
var b = 10;
console.log('a+b = ${a+b}.');
//=> a+b = 20.

function fn() { return "I am a result. Rarr"; }
console.log('foo ${fn()} bar');
//=> foo I am a result. Rarr bar.

Weitere Informationen finden Sie in diesem praktischen Blogpost von Addy.

Kurzschreibweise für Objektliterale

Mit Objektliteralen können Sie vermeiden, dass Schlüssel und Wert beim Erstellen eines Objekts definiert werden müssen, wenn die Variable den Namen des Schlüssels hat, den das Objekt haben soll.

Bedeutung:

function createObject(name, data) {
  return { name: name, data: data };
}

Wird zu:

function createObject(name, data) {
  return { name, data };
}

Berechnete Attributnamen

Mit dieser Funktion in ES2015 können Sie Attributnamen dynamisch für ein Objekt erstellen. Die Mozilla-Dokumentation ist eine hervorragende Informationsquelle. Hier finden Sie auch dieses tolle Beispiel.

var a = {
  ["foo" + ++i]: i,
  ["foo" + ++i]: i,
  ["foo" + ++i]: i
};

console.log(a.foo1); // 1
console.log(a.foo2); // 2
console.log(a.foo3); // 3

Fettpfeilfunktionen

Mit Fettpfeilfunktionen können Sie Funktionen kurz schreiben, wenn:

button.addEventListener('click', function(event) {
  console.log('The button has received a click', event);
});

Wird zu:

button.addEventListener('click', (event) => {
  console.log('The button has received a click', event);
});

Abgesehen von der kürzeren Syntax besteht ein großer Vorteil von Fettpfeilfunktionen darin, dass der Umfang des Objekts der einschließenden Anweisung entspricht. Das bedeutet, dass Sie .bind(this) nicht für Ihre Funktion aufrufen oder eine Variable erstellen müssen, die = this.

Es gibt noch viele weitere Beispiele auf der MDN.

Addys ES6-Tools-Repository

Addy hat damit beschäftigt, eine Liste der ES2015-Tools zu führen. Wenn die oben genannten Tools für Sie nicht geeignet sind, verwenden Sie vielleicht Grunt anstelle von Gulp, dann hat das hier vielleicht eine Antwort für Sie.

https://github.com/addyosmani/es6-tools

Oben finden Sie auch Links zu weiteren Babel-Tools, die Sie während des Einheitentests und darüber hinaus unterstützen können.

Bücher zum Lesen

Es gibt zwei Bücher, die Sie kostenlos online ausleihen können, um mehr über ES2015 zu erfahren. Understanding ECMAScript 6 von Nicholas C. Zakas und Exploring ES6, geschrieben von Dr. Axel Rauschmayer.

Turm von Babel

Wenn Sie die Features von ES2015 über die Befehlszeile kennenlernen möchten, bietet tower-of-babel eine Reihe von Übungen, die für Sie von Interesse sein könnten. Sie lernen alle Schritt für die Nutzung von Babel.

Weitere Informationen: