Ein Leitfaden zu Web Components

Avatar of Rob Dodson
Rob Dodson am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Der folgende Beitrag ist ein Gastbeitrag von Rob Dodson (@rob_dodson). Rob und ich haben uns im CodePen-Support ausgetauscht, um Polymer (ein Web Components Polyfill, sozusagen) für eine Demo von ihm zum Laufen zu bringen. Wir haben es zum Laufen gebracht, und die Dinge haben sich irgendwie zu diesem Artikel entwickelt. Übernehmen Sie, Rob.

Update: Rob hat diesen Artikel am 5. März 2014 aktualisiert, um alles auf den neuesten Stand zu bringen, da dies derzeit eine ziemlich schnelllebige Technologie ist.

Update: Erneute Aktualisierung am 9. September 2014!


Vor kurzem habe ich mit einem Kunden daran gearbeitet, seine internen Teams im Aufbau von Webanwendungen zu schulen. Während dieses Prozesses wurde mir klar, dass die Art und Weise, wie wir derzeit das Frontend-Frontend-Frontend aufbauen, sehr seltsam und sogar ein wenig kaputt ist. In vielen Fällen kopieren Sie riesige HTML-Teile aus einem Dokument und fügen diese dann in Ihre Anwendung ein (Bootstrap, Foundation usw.) oder Sie streuen jQuery-Plugins über die Seite, die mit JavaScript konfiguriert werden müssen. Dies bringt uns in die eher unglückliche Lage, zwischen aufgeblähtem HTML oder mysteriösem HTML wählen zu müssen, und oft wählen wir beides.

In einem idealen Szenario wäre die HTML-Sprache ausdrucksstark genug, um komplexe UI-Widgets zu erstellen und auch erweiterbar, so dass wir Entwickler Lücken mit eigenen Tags füllen könnten. Heute ist dies durch eine neue Reihe von Standards namens Web Components endlich möglich.

Web Components?

Web Components sind eine Sammlung von Standards, die sich derzeit im W3C in der Entwicklung befinden und nach und nach in Browsern eingeführt werden. Im Wesentlichen ermöglichen sie uns, Markup und Stile zu benutzerdefinierten HTML-Elementen zu bündeln. Was an diesen neuen Elementen wirklich erstaunlich ist, ist, dass sie ihren gesamten HTML- und CSS-Code vollständig kapseln. Das bedeutet, dass die von Ihnen geschriebenen Stile immer wie beabsichtigt gerendert werden und Ihr HTML vor den neugierigen Blicken externer JavaScript geschützt ist.

Wenn Sie mit nativen Web Components experimentieren möchten, empfehle ich die Verwendung von Chrome, da es die beste Unterstützung bietet. Ab Chrome Version 36 ist es der erste Browser, der alle neuen Standards ausliefert.

Praktisches Beispiel

Denken Sie darüber nach, wie Sie derzeit einen Bildschieberegler implementieren, er könnte etwa so aussehen

<div id="slider">
  <input checked="" type="radio" name="slider" id="slide1" selected="false">
  <input type="radio" name="slider" id="slide2" selected="false">
  <input type="radio" name="slider" id="slide3" selected="false">
  <input type="radio" name="slider" id="slide4" selected="false">
  <div id="slides">
    <div id="overflow">
      <div class="inner">
        <img src="images//rock.jpg">
        <img src="images/grooves.jpg">
        <img src="images/arch.jpg">
        <img src="images/sunset.jpg">
      </div>
    </div>
  </div>
  <label for="slide1"></label>
  <label for="slide2"></label>
  <label for="slide3"></label>
  <label for="slide4"></label>
</div>

Siehe den Pen CSS3 Slider von Rob Dodson (@robdodson) auf CodePen

Bildschieberegler adaptiert von CSScience. Bilder mit freundlicher Genehmigung von Eliya Selhub

Das ist ein ordentlicher Batzen HTML, und wir haben noch nicht einmal die CSS hinzugefügt! Aber stellen Sie sich vor, wir könnten all diesen zusätzlichen Ballast entfernen und ihn auf die wichtigen Teile reduzieren. Wie würde das aussehen?

<img-slider>
  <img src="images/sunset.jpg" alt="a dramatic sunset">
  <img src="images/arch.jpg" alt="a rock arch">
  <img src="images/grooves.jpg" alt="some neat grooves">
  <img src="images/rock.jpg" alt="an interesting rock">
</img-slider>

Nicht schlecht! Wir haben den Boilerplate-Code entfernt, und der einzige verbleibende Code ist das, was uns wichtig ist. Das ist die Art von Dingen, die Web Components ermöglichen. Aber bevor ich ins Detail gehe, möchte ich Ihnen noch eine Geschichte erzählen.

Im Schatten verborgen

Jahrelang hatten die Browserhersteller einen heimlichen Trick auf Lager. Schauen Sie sich diesen <video>-Tag an und denken Sie wirklich über all die visuellen Schmankerl nach, die Sie mit nur einer Zeile HTML erhalten.

<video src="./foo.webm" controls></video>

Es gibt einen Wiedergabeknopf, einen Schieberegler, Zeitzähler und einen Lautstärkeregler. Viele Dinge, für die Sie keinen Markup schreiben mussten, sie erschienen einfach, als Sie nach <video> gefragt haben.

Aber was Sie tatsächlich sehen, ist eine Illusion. Die Browserhersteller brauchten eine Möglichkeit, zu garantieren, dass die von ihnen implementierten Tags immer gleich gerendert werden, unabhängig von jedem verrückten HTML, CSS oder JavaScript, das wir möglicherweise bereits auf der Seite haben. Um dies zu tun, schufen sie einen geheimen Durchgang, in dem sie ihren Code verstecken und ihn von unseren heißen kleinen Händen fernhalten konnten. Sie nannten diesen geheimen Ort: den Shadow DOM.

Wenn Sie zufällig Google Chrome verwenden, können Sie Ihre Entwicklertools öffnen und die Option Show user agent shadow DOM aktivieren. Dadurch können Sie das <video>-Element detaillierter inspizieren.

Enable Show Shadow DOM
Inspecting Show Shadow DOM

Im Inneren finden Sie eine Menge HTML, das alles versteckt ist. Stochern Sie lange genug herum und Sie werden den bereits erwähnten Wiedergabeknopf, den Lautstärkeregler und verschiedene andere Elemente entdecken.

Denken Sie nun an unseren Bildschieberegler zurück. Was wäre, wenn wir alle Zugriff auf den Shadow DOM und die Möglichkeit hätten, unsere eigenen Tags wie <video> zu deklarieren? Dann könnten wir tatsächlich unseren benutzerdefinierten <img-slider>-Tag implementieren und verwenden.

Werfen wir einen Blick darauf, wie das geht, mit der ersten Säule von Web Components, dem Template.

Templates

Jedes gute Bauprojekt muss mit einem Bauplan beginnen, und bei Web Components stammt dieser Bauplan vom neuen <template>-Tag. Der Template-Tag ermöglicht es Ihnen, Markup auf der Seite zu speichern, das Sie später klonen und wiederverwenden können. Wenn Sie bereits mit Bibliotheken wie Mustache oder Handlebars gearbeitet haben, dann sollte sich der <template>-Tag vertraut anfühlen.

<template>
  <h1>Hello there!</h1>
  <p>This content is top secret :)</p>
</template>

Alles innerhalb eines Templates wird vom Browser als inert betrachtet. Das bedeutet, dass Tags mit externen Quellen—<img>, <audio>, <video> usw.—keine HTTP-Anfragen stellen und <script>-Tags nicht ausgeführt werden. Es bedeutet auch, dass nichts aus dem Template auf der Seite gerendert wird, bis wir es mit JavaScript aktivieren.

Der erste Schritt zur Erstellung unseres <img-slider> ist also, all sein HTML und CSS in ein <template> zu packen.

Siehe den Pen CSS3 Slider Template von Rob Dodson (@robdodson) auf CodePen

Sobald wir das getan haben, sind wir bereit, es in den Shadow DOM zu verschieben.

Shadow DOM

Um wirklich sicherzustellen, dass unser HTML und CSS den Verbraucher nicht negativ beeinflusst, greifen wir manchmal auf iframes zurück. Sie erfüllen ihren Zweck, aber Sie möchten nicht Ihre gesamte Anwendung darin bauen.

Shadow DOM bietet uns die besten Funktionen von iframes, Stil- und Markup-Kapselung, ohne annähernd so viel Ballast.

Um Shadow DOM zu erstellen, wählen Sie ein Element aus und rufen Sie seine Methode createShadowRoot auf. Dies gibt ein Dokumentfragment zurück, das Sie dann mit Inhalt füllen können.

<div class="container"></div>

<script>
  var host = document.querySelector('.container');
  var root = host.createShadowRoot();
  root.innerHTML = '<p>How <em>you</em> doin?</p>'
</script>

Shadow Host

Im Jargon des Shadow DOM wird das Element, auf dem Sie createShadowRoot aufrufen, als Shadow Host bezeichnet. Es ist das einzige Stück, das für den Benutzer sichtbar ist, und hier würden Sie den Benutzer bitten, Ihrem Element Inhalte zur Verfügung zu stellen.

Wenn Sie an unseren <video>-Tag von vorhin denken, ist das <video>-Element selbst der Shadow Host, und die Inhalte sind dieTags, die Sie darin verschachteln.

<video>
  <source src="trailer.mp4" type="video/mp4">
  <source src="trailer.webm" type="video/webm">
  <source src="trailer.ogv" type="video/ogg">
</video>

Shadow Root

Das von createShadowRoot zurückgegebene Dokumentfragment wird als Shadow Root bezeichnet. Die Shadow Root und ihre Nachkommen sind für den Benutzer verborgen, aber sie sind es, die der Browser tatsächlich rendert, wenn er unseren Tag sieht.

Im <video>-Beispiel sind der Wiedergabeknopf, der Schieberegler, die Zeitzähler usw. alles Nachkommen der Shadow Root. Sie erscheinen auf dem Bildschirm, aber ihr Markup ist für den Benutzer nicht sichtbar.

Shadow Boundary

Jegliches HTML und CSS innerhalb der Shadow Root ist durch eine unsichtbare Barriere namens Shadow Boundary vor dem Elterndokument geschützt. Die Shadow Boundary verhindert, dass CSS aus dem Elterndokument in den Shadow DOM eindringt, und sie verhindert auch, dass externes JavaScript in die Shadow Root navigiert.

Übersetzung: Nehmen wir an, Sie haben ein Style-Tag im Shadow DOM, das festlegt, dass alle h3s eine color von Rot haben sollen. Inzwischen gibt es im Elterndokument einen Stil, der festlegt, dass h3s eine color von Blau haben sollen. In diesem Fall werden h3s, die innerhalb des Shadow DOM erscheinen, rot sein, und h3s außerhalb des Shadow DOM werden blau sein. Die beiden Stile werden sich dank unseres Freundes, der Shadow Boundary, gegenseitig ignorieren.

Und wenn das Elterndokument zu einem bestimmten Zeitpunkt nach h3s mit $('h3') sucht, verhindert die Shadow Boundary jegliche Erkundung der Shadow Root und die Auswahl gibt nur h3s zurück, die extern zum Shadow DOM sind.

Dieses Maß an Privatsphäre ist etwas, von dem wir jahrelang geträumt und uns darum bemüht haben. Zu sagen, dass es die Art und Weise, wie wir Webanwendungen erstellen, verändern wird, ist eine reine Untertreibung.

Shadowy Sliders

Um unseren img-slider in den Shadow DOM zu bekommen, müssen wir einen Shadow Host erstellen und ihn mit dem Inhalt unseres Templates füllen.

<template>
  <!-- Full of slider awesomeness -->
</template>

<div class="img-slider"></div>

<script>
  // Add the template to the Shadow DOM
  var tmpl = document.querySelector('template');
  var host = document.querySelector('.img-slider');
  var root = host.createShadowRoot();
  root.appendChild(document.importNode(tmpl.content, true));
</script>

In diesem Fall haben wir ein div erstellt und ihm die Klasse img-slider gegeben, damit es als unser Shadow Host dienen kann.

Wir wählen das Template aus und machen eine tiefe Kopie seines Internen mit document.importNode. Diese Internen werden dann an unsere neu erstellte Shadow Root angehängt.

Wenn Sie Chrome verwenden, können Sie dies tatsächlich im folgenden Pen sehen.

Siehe den Pen CSS3 Slider Shadow DOM von Rob Dodson (@robdodson) auf CodePen

Insertion Points

An diesem Punkt ist unser img-slider im Shadow DOM, aber die Bildpfade sind fest kodiert. Genau wie die <source>-Tags, die in <video> verschachtelt sind, möchten wir, dass die Bilder vom Benutzer kommen, also müssen wir sie vom Shadow Host einladen.

Um Elemente in den Shadow DOM zu ziehen, verwenden wir das neue <content>-Tag. Das <content>-Tag verwendet CSS-Selektoren, um Elemente aus dem Shadow Host auszuwählen und in den Shadow DOM zu projizieren. Diese Projektionen werden als Insertion Points bezeichnet.

Wir machen es uns leicht und gehen davon aus, dass der Slider nur Bilder enthält, sodass wir einen Insertion Point mit dem img-Selektor erstellen können.

<template>
  ...
  <div class="inner">
    <content select="img"></content>
  </div>
</template>

Da wir Inhalte über einen Insertion Point in den Shadow DOM projizieren, müssen wir auch das neue ::content-Pseudoelement verwenden, um unsere CSS zu aktualisieren.

#slides ::content img {
  width: 25%;
  float: left;
}

Wenn Sie mehr über die neuen CSS-Selektoren und Kombinatoren erfahren möchten, die von Shadow DOM hinzugefügt wurden, werfen Sie einen Blick auf dieses Cheat Sheet, das ich zusammengestellt habe.

Jetzt sind wir bereit, unseren img-slider zu befüllen.

<div class="img-slider">
  <img src="images/rock.jpg" alt="an interesting rock">
  <img src="images/grooves.jpg" alt="some neat grooves">
  <img src="images/arch.jpg" alt="a rock arch">
  <img src="images/sunset.jpg" alt="a dramatic sunset">
</div>

Das ist wirklich cool! Wir haben die Menge des vom Benutzer angezeigten Markups stark reduziert. Aber warum hier aufhören? Wir können die Dinge noch weiter treiben und diesen img-slider zu einem eigenen Tag machen.

Custom Elements

Ein eigenes HTML-Element zu erstellen mag einschüchternd klingen, ist aber eigentlich ziemlich einfach. Im Jargon von Web Components ist dieses neue Element ein Custom Element, und die einzigen beiden Anforderungen sind, dass sein Name einen Bindestrich enthalten muss und sein Prototyp von HTMLElement erben muss.

Werfen wir einen Blick darauf, wie das funktionieren könnte.

<template>
  <!-- Full of image slider awesomeness -->
</template>

<script>
  // Grab our template full of slider markup and styles
  var tmpl = document.querySelector('template');

  // Create a prototype for a new element that extends HTMLElement
  var ImgSliderProto = Object.create(HTMLElement.prototype);

  // Setup our Shadow DOM and clone the template
  ImgSliderProto.createdCallback = function() {
    var root = this.createShadowRoot();
    root.appendChild(document.importNode(tmpl.content, true));
  };

  // Register our new element
  var ImgSlider = document.registerElement('img-slider', {
    prototype: ImgSliderProto
  });
</script>

Die Methode Object.create gibt einen neuen Prototyp zurück, der von HTMLElement erbt. Wenn der Parser unseren Tag im Dokument findet, prüft er, ob eine Methode namens createdCallback vorhanden ist. Wenn er diese Methode findet, führt er sie sofort aus. Dies ist ein guter Ort, um Setup-Arbeiten durchzuführen. Wir erstellen also Shadow DOM und klonen unser Template hinein.

Wir übergeben den Tag-Namen und den Prototyp an eine neue Methode auf dem document namens registerElement, und danach sind wir bereit.

Jetzt, wo unser Element registriert ist, gibt es ein paar verschiedene Möglichkeiten, es zu verwenden. Die erste und einfachste ist, einfach den <img-slider>-Tag irgendwo in unserem HTML zu verwenden. Aber wir können auch document.createElement("img-slider") aufrufen oder den Konstruktor verwenden, der von document.registerElement zurückgegeben und in der Variablen ImgSlider gespeichert wurde. Es bleibt Ihnen überlassen, welchen Stil Sie bevorzugen.

Unterstützung

Die Unterstützung für die verschiedenen Standards, aus denen Web Components bestehen, ist ermutigend und verbessert sich ständig. Diese Tabelle zeigt, wo wir uns derzeit befinden.

Web Components Support Table

Aber lassen Sie sich von der fehlenden Unterstützung in einigen Browsern nicht entmutigen! Die schlauen Köpfe von Mozilla und Google haben hart daran gearbeitet, Polyfill-Bibliotheken zu entwickeln, die die Unterstützung für Web Components in allen modernen Browsern schleichen lassen! Das bedeutet, dass Sie heute mit diesen Technologien experimentieren und den Leuten, die die Spezifikationen schreiben, Feedback geben können. Dieses Feedback ist wichtig, damit wir nicht mit stinkender, schwer zu verwendender Syntax enden.

Schauen wir uns an, wie wir unseren img-slider mit Googles Web Components-Bibliothek Polymer neu schreiben könnten.

Polymer rettet den Tag!

Polymer fügt dem Browser einen neuen Tag hinzu, <polymer-element>, der Templates automatisch in Shadow DOM umwandelt und benutzerdefinierte Elemente für uns registriert. Alles, was wir tun müssen, ist, Polymer den Namen des Tags mitzuteilen und sicherzustellen, dass wir unser Template-Markup einfügen.

Siehe den Pen Polymer Slider von Chris Coyier (@chriscoyier) auf CodePen.

Ich finde es oft einfacher, Elemente mit Polymer zu erstellen, da die Bibliothek viele Annehmlichkeiten bietet. Dazu gehören Zwei-Wege-Bindung zwischen Elementen und Modellen, automatische Knotensuche und Unterstützung für andere neue Standards wie Web Animations. Außerdem sind die Entwickler auf der mailing list polymer-dev äußerst aktiv und hilfsbereit, was großartig ist, wenn man gerade die Grundlagen lernt, und die StackOverflow-Community wächst.

Dies ist nur ein winziges Beispiel dafür, was Polymer leisten kann. Besuchen Sie daher unbedingt die Projektseite und schauen Sie sich auch die Alternative von Mozilla, X-Tag, an.

Probleme

Jeder neue Standard kann kontrovers sein, und im Fall von Web Components scheinen sie besonders polarisierend zu sein. Bevor wir abschließen, möchte ich einige der Rückmeldungen, die ich in den letzten Monaten erhalten habe, zur Diskussion stellen und meine Meinung dazu äußern.

OMG, das ist XML!!!

Ich denke, das, was die meisten Entwickler wahrscheinlich erschreckt, wenn sie Custom Elements zum ersten Mal sehen, ist die Vorstellung, dass das Dokument in einen großen Haufen XML verwandelt wird, bei dem alles auf der Seite einen maßgeschneiderten Tag-Namen hat und wir auf diese Weise das Web praktisch unlesbar machen. Das ist ein valides Argument, also beschloss ich, die Gemüter zu erhitzen und es auf der Polymer-Mailingliste anzusprechen.

Die Hin- und Her-Diskussion ist ziemlich interessant, aber ich denke, der allgemeine Konsens ist, dass wir einfach experimentieren müssen, um zu sehen, was funktioniert und was nicht. Ist es besser und semantischer, einen Tag-Namen wie <img-slider> zu sehen, oder ist unser aktueller "div-Suppen"-Ansatz der einzig richtige Weg? Alex Rusell hat einen sehr nachdenklichen Beitrag zu diesem Thema verfasst, und ich empfehle jedem, sich die Zeit zu nehmen, ihn zu lesen, bevor er sich eine Meinung bildet.

SEO

Derzeit ist unklar, wie gut Crawler Custom Elements und Shadow DOM unterstützen. Das Polymer FAQ besagt

Suchmaschinen befassen sich seit einiger Zeit mit umfangreichen AJAX-basierten Anwendungen. Die Abkehr von JS und mehr Deklarativität ist eine gute Sache und wird im Allgemeinen die Dinge verbessern.

Der Google Webmaster Blog hat kürzlich angekündigt, dass der Google Crawler JavaScript auf Ihrer Seite ausführt, bevor er sie indiziert. Und mit einem Tool wie Fetch as Google können Sie sehen, was der Crawler sieht, während er Ihre Website analysiert. Ein gutes Beispiel ist die Polymer-Website, die mit Custom Elements erstellt wurde und bei Google leicht durchsuchbar ist.

Ein Tipp, den ich von Gesprächen mit Mitgliedern des Polymer-Teams gelernt habe, ist, darauf zu achten, dass der Inhalt Ihres Custom Elements statisch ist und nicht aus einer Datenbindung stammt.

<!-- probably good -->
<x-foo>
  Here is some interesting, and searchable content...
</x-foo>

<!-- probably bad -->
<x-foo>
  {{crazyDynamicContent}}
</x-foo>

<!-- also probably bad -->
<a href="{{aDynamicLink}}">Click here</a>

Fairerweise muss man sagen, dass dies kein neues Problem ist. AJAX-lastige Seiten befassen sich seit einigen Jahren mit diesem Problem und glücklicherweise gibt es Lösungen.

Barrierefreiheit (Accessibility)

Offensichtlich wird das Thema Zugänglichkeit ziemlich wichtig, wenn wir Markup in geheimen Shadow DOM Sandboxes verstecken. Steve Faulkner hat sich die Zugänglichkeit im Shadow DOM angesehen und schien mit dem zufrieden zu sein, was er fand.

Ergebnisse aus ersten Tests deuten darauf hin, dass die Einbeziehung von ARIA-Rollen, Zuständen und Eigenschaften in Inhalte, die sich vollständig im Shadow DOM befinden, gut funktioniert. Die Barrierefreiheitsinformationen werden über die Barrierefreiheits-API korrekt exponiert. Screenreader können ohne Probleme auf Inhalte im Shadow DOM zugreifen.

Der vollständige Beitrag ist hier verfügbar.

Marcy Sutton* hat ebenfalls einen Beitrag zu diesem Thema verfasst, in dem sie erklärt:

Web Components, einschließlich Shadow DOM, sind barrierefrei, da assistierende Technologien Seiten als gerendert wahrnehmen, was bedeutet, dass das gesamte Dokument als "ein einziger glücklicher Baum" gelesen wird.

* Marcy weist auch darauf hin, dass der von mir in diesem Beitrag erstellte img-slider nicht barrierefrei ist, da unser CSS-Label-Trick ihn für die Tastatur unzugänglich macht. Behalten Sie das im Hinterkopf, wenn Sie ihn in einem Projekt wiederverwenden möchten.

Sicherlich wird es auf dem Weg einige Hindernisse geben, aber das klingt nach einem ziemlich guten Anfang!

Style-Tags? Ähm, nein danke.

Leider funktionieren <link>-Tags nicht innerhalb des Shadow DOM, was bedeutet, dass die einzige Möglichkeit, externe CSS einzubinden, über @import ist. Mit anderen Worten, <style>-Tags sind – vorerst – unvermeidlich.*

Beachten Sie, dass die von uns besprochenen Stile nur für eine Komponente relevant sind, während wir zuvor dazu trainiert wurden, externe Dateien zu bevorzugen, da sie oft unsere gesamte Anwendung beeinflussen. Ist es also so schlimm, ein <style>-Tag in ein Element einzufügen, wenn all diese Stile nur auf diese eine Entität beschränkt sind? Persönlich finde ich es in Ordnung, aber die Option für externe Dateien wäre sehr wünschenswert.

* Es sei denn, Sie verwenden Polymer, das diese Einschränkung mit XHR umgeht.

Jetzt sind Sie dran

Es liegt an uns, herauszufinden, wohin diese Standards gehen und welche Best Practices sie leiten werden. Probieren Sie Polymer aus und schauen Sie sich auch die Alternative von Mozilla, X-Tag, an (die Unterstützung bis hinunter zu Internet Explorer 9 bietet).

Stellen Sie außerdem sicher, dass Sie sich an die Entwickler bei Google und Mozilla wenden, die diese Standards vorantreiben. Unser Feedback ist notwendig, um diese Werkzeuge zu etwas zu formen, das wir alle nutzen wollen.

Obwohl es noch einige Kanten gibt, glaube ich, dass Web Components schließlich einen neuen Stil der Anwendungsentwicklung einläuten werden, etwas, das dem Zusammenstecken von Legosteinen ähnlicher ist, und weniger wie unser aktueller Ansatz, der oft von überschüssigem Boilerplate geplagt wird. Ich bin ziemlich begeistert von der Richtung, in die das alles geht, und ich freue mich auf das, was die Zukunft bringen mag.