{"id":21086,"date":"2018-05-28T13:09:54","date_gmt":"2018-05-28T11:09:54","guid":{"rendered":"http:\/\/www.inovex.de\/blog\/?p=12924"},"modified":"2025-03-19T07:29:30","modified_gmt":"2025-03-19T06:29:30","slug":"komponentenbibliotheken","status":"publish","type":"post","link":"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/","title":{"rendered":"Komponentenbibliotheken f\u00fcr die Web-Entwicklung"},"content":{"rendered":"<p>F\u00fcr gr\u00f6\u00dfere Projekte, in denen mehrere Teams parallel an Web-Applikationen entwickeln, k\u00f6nnen wir bedenkenlos die Entwicklung und den Einsatz einer Komponentenbibliothek empfehlen. Im Folgenden m\u00f6chten wir diesen Begriff erl\u00e4utern und aus unseren Erfahrungen berichten.<!--more--><\/p>\n<p>Moderne JavaScript Frontend-Bibliotheken wie z.B. <a href=\"https:\/\/reactjs.org\/\">React<\/a>, <a href=\"https:\/\/angular.io\/\">Angular<\/a> oder <a href=\"https:\/\/vuejs.org\/\">Vue.js<\/a> setzen allesamt auf einen komponentenbasierten Aufbau. In diesem Ansatz wird versucht, jedes beliebig gro\u00dfe Teilst\u00fcck einer Web-Applikation abstrakt zu fassen und isoliert zu betrachten. Eine Komponente kapselt dabei die Darstellung und Anwendungslogik eines HTML-Fragments ab.<\/p>\n<figure id=\"attachment_12926\" aria-describedby=\"caption-attachment-12926\" style=\"width: 1024px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/TODOComponents.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-12926\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/TODOComponents-1024x379.jpg\" alt=\"Komponentenbibliothek: Beispiel einer Todo-App \" width=\"1024\" height=\"379\" \/><\/a><figcaption id=\"caption-attachment-12926\" class=\"wp-caption-text\">Beispiel f\u00fcr einen Komponentenschnitt innerhalb einer <a href=\"http:\/\/todomvc.com\/examples\/react\/#\/\">Todo-App<\/a><\/figcaption><\/figure>\n<p>Dies f\u00fchrt zu einer Reihe von Vorteilen:<\/p>\n<ul>\n<li>Jede Komponente erf\u00fcllt einen speziellen Zweck.<\/li>\n<li>Komponenten k\u00f6nnen ineinander geschachtelt und \u00fcber ihre API verkn\u00fcpft werden. Auf diese Art lassen sich komplexere Anwendungsf\u00e4lle abbilden.<\/li>\n<li>Das Isolieren von Komponenten erm\u00f6glicht eine hohe Testbarkeit mit minimalem Aufwand bei gleichzeitig hoher Wiederverwendbarkeit.<\/li>\n<\/ul>\n<p>Eine Komponentenbibliothek, manchmal auch Pattern Library oder Styleguide genannt, ist eine zentralisierte Sammlung wiederverwendbarer Komponenten und kann in gr\u00f6\u00dferen Systemlandschaften team\u00fcbergreifend eingesetzt werden. In der Konsequenz kann die Bereitstellung einer Komponentenbibliothek eine <em>Time to value<\/em> erheblich reduzieren. Die Entwicklung an einer zentralen Stelle minimiert zudem die Wartungskosten.<\/p>\n<p>Der Mehrwert einer Komponentenbibliothek ist insbesondere auch die enge Verzahnung der Entwicklung mit dem Design. Sie schafft zum einen eine gemeinsame Sprache, ein gemeinsames Verst\u00e4ndnis beim Schnitt der Anwendungen und setzt zum anderen die UI\/UX-Vorgaben direkt um.<\/p>\n<p>Je nach Implementierung kann die Ger\u00e4te- und Browser-\u00fcbergreifende Kompatibilit\u00e4t der Komponenten durch sinnvolle E2E-Tests sichergestellt werden. Die Erstellung von barrierefreiem Inhalt kann vereinfacht werden, wenn dies innerhalb der Komponenten bereits ber\u00fccksichtigt und durch entsprechende Tests, z.B. mithilfe von <a href=\"https:\/\/axe-core.org\/\">aXe<\/a>, abgesichert wird.<\/p>\n<p>Es sollte jedoch unbedingt bedacht werden, ob Komponenten in realen Projekten wiederverwendet werden k\u00f6nnen, oder ob diese nur eine Idealvorstellung darstellen. M\u00f6glicherweise sind Applikationen und\/oder organisatorische Strukturen derart heterogen, dass sich der zus\u00e4tzliche Aufwand, den eine Implementierung erfordert, nicht rechnet. Dies gilt insbesondere f\u00fcr (kleine) Teams mit sehr unterschiedlichen Applikationsanforderungen.<\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_79_2 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\"><p class=\"ez-toc-title\" style=\"cursor:inherit\"><\/p>\n<\/div><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#Technische-Entscheidungen\" >Technische Entscheidungen<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#Auswahl-des-Frameworks\" >Auswahl des Frameworks<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#Web-Components\" >Web Components<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#Bereitstellung-der-Komponentenbibliothek\" >Bereitstellung der Komponentenbibliothek<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#Strukturierung\" >Strukturierung<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#Definieren-einer-API\" >Definieren einer API<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#Ausliefern-von-CSS\" >Ausliefern von CSS<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#Organisation\" >Organisation<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#Einheitliche-API\" >Einheitliche API<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#Kontextfrei\" >Kontextfrei<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#Semantic-VersioningChangelog\" >Semantic Versioning\/Changelog<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#Composability\" >Composability<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#Dokumentation\" >Dokumentation<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#Case-Study-ERGO-Elements\" >Case Study: ERGO Elements<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#Referenzen\" >Referenzen<\/a><\/li><\/ul><\/nav><\/div>\n<h2 id=\"technische-entscheidungen\"><span class=\"ez-toc-section\" id=\"Technische-Entscheidungen\"><\/span>Technische Entscheidungen<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Beim Aufbau einer Komponentenbibliothek gilt es, eine Reihe von technischen Entscheidungen zu treffen, die je nach Use-Case Vor- und Nachteile mit sich bringen. Wir wollen auf die wichtigsten Punkte eingehen und einen High-Level-\u00dcberblick \u00fcber m\u00f6gliche L\u00f6sungen bieten. Hierbei erheben wir keinen Anspruch auf Vollst\u00e4ndigkeit, sondern legen vor allem die in unseren Augen wesentlichen Punkte dar, \u00fcber die es nachzudenken gilt.<\/p>\n<h3 id=\"auswahl-des-frameworks\"><span class=\"ez-toc-section\" id=\"Auswahl-des-Frameworks\"><\/span>Auswahl des Frameworks<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Eine der komplexesten und weitreichendsten Entscheidungen ist die Auswahl des Frameworks, da hiervon die gesamte Anwendung betroffen ist, nicht nur die UI-Komponenten. Hinzu kommt, dass sich dieser Bereich der Web-Entwicklung aktuell sehr schnell bewegt und in kurzen Abst\u00e4nden zahlreiche neue Frameworks ver\u00f6ffentlicht werden. Dieser Artikel soll nicht dazu dienen Frameworks zu vergleichen, sondern sich der Arbeit mit Komponenten widmen, daher werden wir nicht n\u00e4her auf einzelne Frameworks eingehen \u2013 mit einer Ausnahme, den Web Components. Einen guten \u00dcberblick \u00fcber den aktuellen Stand der Frameworks und deren Produktiveinsatz gibt auch die\u00a0<a href=\"https:\/\/stateofjs.com\/\">JavaScript Survey 2017<\/a>.<\/p>\n<h4 id=\"web-components\"><span class=\"ez-toc-section\" id=\"Web-Components\"><\/span>Web Components<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>Eine Besonderheit stellen <a href=\"https:\/\/www.webcomponents.org\/\">Web Components<\/a> dar. Hierbei handelt es sich um den Versuch der WHATWG, eine <a href=\"https:\/\/html.spec.whatwg.org\/multipage\/custom-elements.html\">standardisierte L\u00f6sung<\/a> f\u00fcr Custom Elements zu etablieren. Web Components erlauben es, Komponenten von einem Framework loszul\u00f6sen und direkt in einer Abstraktionsschicht zu definieren, die moderne Browser mitbringen. Das hat den Vorteil, dass die daraus entstehenden Komponenten, analog zu nativen HTML-Elementen, in jedem Kontext einsetzbar sind und nicht nur im Rahmen eines Frameworks, wie dies zum Beispiel bei React- oder Angular-Komponenten der Fall ist. Damit eignen sie sich prinzipiell gut f\u00fcr eine Komponentenbibliothek in einem Umfeld heterogener Web-Technologien.<\/p>\n<p>Nachteilig ist jedoch, dass sich Browser-Hersteller bei wichtigen Details der Web-Components-Spezifikation noch nicht einig sind, was dazu f\u00fchrt, dass nicht alle Browser eine einheitliche API unterst\u00fctzen. Stellvertretend hierf\u00fcr sei die <a href=\"https:\/\/developers.google.com\/web\/fundamentals\/web-components\/customelements#extendhtml\">Diskussion um das <code>is<\/code>-Attribut<\/a> genannt. Wir sind der Meinung, dass man momentan je nach Einzelfall pr\u00fcfen und entscheiden sollte, ob es Sinn macht, seine Komponentenbibliothek mit Web Components aufzubauen. Vor allem der <a href=\"https:\/\/caniuse.com\/#search=Web%20components\">Browsersupport<\/a> spielt hier eine zentrale Rolle.<\/p>\n<p>Nach aktuellem Stand der Technik eigenen sich zudem einige Frameworks mehr als andere, um mit Web Components nahtlos zusammen zu spielen. Besonders hervorzugehen sind hier Angular und Vue.js, wohingegen React und AngularJS einige Probleme haben. Mehr technische Details hierzu sind auf der Seite <a href=\"https:\/\/custom-elements-everywhere.com\/\">Custom Components Everywhere<\/a> gelistet.<\/p>\n<p>Hinzu kommt, dass derzeit nach unserer Einsch\u00e4tzung im Bereich Web Components noch sehr viel experimentiert wird und wenig Zuverl\u00e4ssiges existiert. So hat Google im Oktober 2018 <a href=\"https:\/\/www.polymer-project.org\/blog\/2017-08-22-npm-modules\">bekannt gegeben<\/a>, ab Polymer 3 auf eine ihrer Kernideen, den HTML-Import, zu verzichten und nutzt statt dessen ES2015 Imports. F\u00fcr die Anwender:innen und Early Adopter von Web Components via Polymer bedeutet dies einige Arbeit, denn bereits existierende Komponenten m\u00fcssen hierf\u00fcr angepasst werden.<\/p>\n<p>Auch andere Frameworks wie <a href=\"https:\/\/stenciljs.com\/\">Stencil.js<\/a> oder Skate.js werden bisher nur vereinzelt produktiv eingesetzt und k\u00f6nnen, Stand heute, nur unter Vorbehalt empfohlen werden, da deren Weiterentwicklung h\u00e4ufig nur an einzelnen Entwickler:innen h\u00e4ngt.<\/p>\n<p>Zudem stellen sich auch bei Web Components Fragen nach SEO, Performance und Accessibility, die es zu beantworten gilt. Au\u00dferdem stehen Web Components immer in einem globalen Namespace zur Verf\u00fcgung, der eine Versionierung schwierig macht. All diese Fragestellungen sprengen jedoch den Umfang dieses Beitrags und w\u00e4ren einen eigenen Blogpost wert.<\/p>\n<h3 id=\"bereitstellung-der-bibliothek\"><span class=\"ez-toc-section\" id=\"Bereitstellung-der-Komponentenbibliothek\"><\/span>Bereitstellung der Komponentenbibliothek<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Die entwickelten Komponenten sollten den Applikationsentwickler:innen zentral bereit gestellt werden. Im JavaScript-Kontext gibt es hierf\u00fcr unterschiedliche M\u00f6glichkeiten:<\/p>\n<ol>\n<li><strong>npm-Package <\/strong>Die Komponentenbibliothek kann \u00fcber die zentrale Paketverwaltung <a href=\"https:\/\/npmjs.com\">npm<\/a> bereitgestellt werden. Soll die Bibliothek nicht \u00f6ffentlich verf\u00fcgbar sein, muss hierzu entweder ein <a href=\"https:\/\/docs.npmjs.com\/private-modules\/intro\">privates Repository<\/a> oder eine eigene Registry wie beispielsweise Nexus vorgeschalten sein.<\/li>\n<li><strong>Content-Delivery-Network (CDN) <\/strong>Die Komponentenbibliothek kann auch mittels eines CDNs bereitgestellt werden. Die Komponenten m\u00fcssen dann als <a href=\"https:\/\/github.com\/umdjs\/umd\">UMD-Module<\/a> bereitgestellt werden.<\/li>\n<\/ol>\n<p>Einige der Vor- und Nachteile der beiden M\u00f6glichkeiten sind:<\/p>\n<table>\n<thead>\n<tr>\n<th>Methode<\/th>\n<th align=\"center\">npm<\/th>\n<th align=\"center\">CDN<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Keine globale Variablen notwendig<\/td>\n<td align=\"center\">\u2713<\/td>\n<td align=\"center\">\u2717<\/td>\n<\/tr>\n<tr>\n<td>Tree-Shaking im Build m\u00f6glich<\/td>\n<td align=\"center\">\u2713<\/td>\n<td align=\"center\">\u2717<\/td>\n<\/tr>\n<tr>\n<td>Verwenden von unterschiedlichen Versionen<\/p>\n<p>der Komponentenbibliothek m\u00f6glich<\/td>\n<td align=\"center\">\u2713<\/td>\n<td align=\"center\">\u2717<\/td>\n<\/tr>\n<tr>\n<td>Anwendungs\u00fcbergreifendes Caching m\u00f6glich<\/td>\n<td align=\"center\">\u2717<\/td>\n<td align=\"center\">\u2713<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3 id=\"strukturierung\"><span class=\"ez-toc-section\" id=\"Strukturierung\"><\/span>Strukturierung<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>H\u00e4ufig verwendet man zur Strukturierung von Komponenten die Methodik des <a href=\"http:\/\/bradfrost.com\/blog\/post\/atomic-web-design\/\">Atomic Design<\/a>. Beim Design und Schnitt der Komponenten wird hierbei zun\u00e4chst nach nicht weiter zerlegbaren Elementen, den Atomen, gesucht. Diese k\u00f6nnen beispielsweise ein Button oder ein Input-Feld sein \u2013 selbstverst\u00e4ndlich im entsprechenden Corporate Design. Ausgehend von den <strong>Atomen<\/strong> k\u00f6nnen komplexere Elemente wie eine UI Card entstehen, welche als <strong>Molek\u00fcle<\/strong> bezeichnet werden. Eine Ver\u00adschach\u00adte\u00adlung von Molek\u00fclen f\u00fchrt dann zu den sogenannten <strong>Habitaten<\/strong>.<\/p>\n<p>Atome sind die Elemente mit den wenigsten Annahmen \u00fcber ihre Umgebung. Sie m\u00fcssen eine Vielzahl von Anwendungsf\u00e4llen unterst\u00fctzen und sollten sehr generisch gehalten werden. Zum Beispiel sollte ein Eingabefeld sowohl f\u00fcr Suchbegriffe als auch f\u00fcr die Eingabe eines Passwort verwendet werden k\u00f6nnen.<\/p>\n<p>Molek\u00fcle hingegen setzen h\u00e4ufig schon einen gewissen Kontext voraus. Eine UI Card zum Beispiel ist selbst-konsistent, kann und soll aber nicht f\u00fcr jeden Use-Case eingesetzt werden. Es kann hingegen unterschiedliche Auspr\u00e4gungen von Karten geben, die einen unterschiedlichen Use-Case implementieren, wie z.B. eine <code>UserCard<\/code> zur Anzeige von Benutzer:inneninformationen und <code>ProductCard<\/code>, die Produktdaten bereitstellt.<\/p>\n<p>Generell ist beim Definieren der Komponenten darauf zu achten, dass diese so generisch wie m\u00f6glich sind \u2013 allerdings immer nur unter den gegebenen Rahmenbedingungen.<\/p>\n<p>F\u00fcr das Komponenten-Design gilt daher:<\/p>\n<blockquote><p>So generisch wie m\u00f6glich, so voreingenommen wie n\u00f6tig.<\/p><\/blockquote>\n<h4 id=\"definieren-einer-api\"><span class=\"ez-toc-section\" id=\"Definieren-einer-API\"><\/span>Definieren einer API<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>Jede Komponente stellt ihre eigene Funktionalit\u00e4t zur Verf\u00fcgung. Hierzu muss sie mit ihrer Umgebung kommunizieren und stellt zu diesem Zweck eine eigene API (Application Programming Interface) bereit.<\/p>\n<p>Das Interface einer Komponente ist das, womit jede:r Anwender:in arbeiten muss. Es ist die einzige Schnittstelle zur Au\u00dfenwelt, die Komponente stellt ansonsten eine Blackbox dar. Das ist sinnvoll, denn ein Anwender soll sich keine Gedanken machen m\u00fcssen, wie die Komponente funktioniert, sondern nur dar\u00fcber, wie man sie anspricht.<\/p>\n<p>An die Spezifikation von Komponenten sind hohe Anforderungen gestellt. Die API sollte den folgenden Rahmenbedinungen gen\u00fcgen:<\/p>\n<ul>\n<li><strong>Stabilit\u00e4t <\/strong>Eine API sollte sich \u00fcber die Zeit so wenig wie m\u00f6glich \u00e4ndern (v.a. keine nicht-r\u00fcckw\u00e4rtskompatiblen Changes, sogenannte <a href=\"https:\/\/semver.org\/#spec-item-8\">Breaking Changes<\/a>), da jede \u00c4nderung Anpassungen beim Anwender notwendig macht. Im schlechtesten Fall l\u00f6sen solche \u00c4nderungen in den Anwendungen kaskadierende Effekte aus, die hohe Kosten- und Zeitaufw\u00e4nde n\u00f6tig machen.<\/li>\n<li><strong>Konsistenz <\/strong>Die API sollte sich konsistent verhalten &#8211; auch \u00fcber mehrere Komponenten hinweg. Kann man z.B. mehreren Elementen einen Tooltip mitgeben, sollte das entsprechende Attribut immer gleich genannt werden und sich immer gleich verhalten. Der Vorteil liegt auf der Hand: Die Komponentenbibliothek verh\u00e4lt sich wie aus einem Guss und dies erleichtert den t\u00e4glichen Umgang mit ihr.<\/li>\n<\/ul>\n<h3 id=\"ausliefern-von-css\"><span class=\"ez-toc-section\" id=\"Ausliefern-von-CSS\"><\/span>Ausliefern von CSS<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Die Komponenten werden, wie in der Web-Entwicklung \u00fcblich, mit CSS (Cascading StyleSheets) gestyled. In der klassischen Web-Entwicklung werden oftmals einige wenige CSS-Dateien angelegt, die dann Regeln f\u00fcr alle Teile der Website beinhalten (vgl. <a href=\"https:\/\/getbootstrap.com\/\">Bootstrap<\/a>, <a href=\"https:\/\/foundation.zurb.com\/\">Foundation<\/a>). Das Isolationsprinzip bei der komponentenbasierten Entwicklung hingegen sieht vor, dass jede Komponente unabh\u00e4ngig von anderen existieren kann und ein in sich geschlossenes System darstellt. Dazu geh\u00f6ren auch die Styles, so dass in diesem Ansatz jede Komponente ihr CSS definiert und selbst mitbringt.<\/p>\n<p>Jede Komponente sollte isoliert verwendbar sein, Redundanzen sind also h\u00e4ufig unabdingbar und k\u00f6nnen nicht vollst\u00e4ndig vermieden werden. Im Source-Code hingegen k\u00f6nnen Redundanzen, also Schnittmengen zwischen Komponenten, \u00fcber Mixins abgebildet werden. Diese k\u00f6nnen mit einem CSS-Pr\u00e4prozessor wie z.B. <a href=\"http:\/\/lesscss.org\/\">LESS<\/a> oder <a href=\"http:\/\/sass-lang.com\/\">SASS<\/a> abgebildet werden, um den Code m\u00f6glichst <a href=\"https:\/\/de.wikipedia.org\/wiki\/Don%E2%80%99t_repeat_yourself\">DRY<\/a> zu halten.<\/p>\n<p>Eine Nomenklatur wie <a href=\"http:\/\/getbem.com\/introduction\/\">BEM<\/a> hilft bei der spezifischen Benennung der Klassen und vermeidet somit Kollisionen im Namensraum. Au\u00dferdem sollte, falls erforderlich, eine Versionierung der StyleSheets \u00fcber den Namensraum ber\u00fccksichtigt werden.<\/p>\n<p>Es existieren unterschiedliche Methoden, um das CSS an den User auszuliefern.<\/p>\n<ol>\n<li><strong>Dynamisch <\/strong>Hierbei ist jede Komponente selbst verantwortlich, ihr CSS in den Dokumentenbaum (DOM) einzubetten. Typischerweise stellen Module-Bundler wie beispielsweise <a href=\"https:\/\/webpack.js.org\/\">webpack<\/a> hierf\u00fcr die notwendigen Code-Snippets bereit (z.B. <a href=\"https:\/\/github.com\/webpack-contrib\/style-loader\">style-loader<\/a>).<\/li>\n<li><strong>Statisch <\/strong>Bei diesem Ansatz wird aus dem modularisierten CSS beim Build-Schritt eine globale CSS-Datei erstellt, welche das CSS von allen Komponenten beinhaltet. Dieses wird nun einmalig in die Seite eingebettet. Dieser Ansatz widerspricht dabei nicht der Isolation, da die Definition der CSS-Regeln wie oben beschrieben innerhalb der Komponente passiert und erst beim Build extrahiert und global abgelegt wird (z.B. <a href=\"https:\/\/github.com\/webpack-contrib\/extract-text-webpack-plugin\">webpack-extract-text-plugin<\/a>).<\/li>\n<\/ol>\n<h3 id=\"organisation\"><span class=\"ez-toc-section\" id=\"Organisation\"><\/span>Organisation<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Eine Komponentenbibliothek zu erstellen und zu verwalten stellt auch organisatorisch eine Herausforderung dar. Es m\u00fcssen viele Fragen bedacht und beantwortet werden, darunter die folgenden:<\/p>\n<ul>\n<li>Wer plant und schneidet Komponenten und definiert deren API?<\/li>\n<li>Wer ist zust\u00e4ndig f\u00fcr die Entwicklung\/Weiterentwicklung von Komponenten (Owner)?<\/li>\n<li>Wer fixt Bugs in der Komponentenbibliothek?<\/li>\n<li>Wer dokumentiert die Komponenten?<\/li>\n<li>Wer ist zust\u00e4ndig f\u00fcr das Testen von Komponenten auf allen unterst\u00fctzten Browsern und Betriebsystemen?<\/li>\n<li>Wer k\u00fcmmert sich um die allgemeine Pipeline, die notwendig ist, um ein Release zu erzeugen?<\/li>\n<\/ul>\n<p>In unserer Erfahrung mit Komponentenbibliotheken hat sich gezeigt, dass es oft sinnvoll ist, ein dediziertes Komponenten-Team bereitzustellen, das sich um die Planung, Entwicklung, Dokumentation, das Testen und Weiterentwickeln der Komponenten sowie die daf\u00fcr notwendige Infrastruktur k\u00fcmmert. Aufgabe dieses Teams ist es dabei auch, eng mit Designer:innen und Fachkr\u00e4ften der User-Experience-Abteilung (UX) zusammen zu arbeiten. In die Zust\u00e4ndigkeit des Teams f\u00e4llt auch die Pflege der Komponenten (Maintenance).<\/p>\n<p>Es ist aber auch vorstellbar, viele Teams an der Komponentenbibliothek arbeiten zu lassen und diese je nach Bedarf um die Komponenten anzureichern, die im aktuellen Entwicklungsschritt in diversen Projekten gebraucht werden.<\/p>\n<p>Ein eigenes Komponenten-Team hilft aus unserer Erfahrung, einige der im folgenden gelisteten Ziele einfach zu erreichen.<\/p>\n<h4 id=\"einheitliche-api\"><span class=\"ez-toc-section\" id=\"Einheitliche-API\"><\/span>Einheitliche API<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>Jede Komponente definiert ihre eigene API. Jedoch sind die Komponenten aus Sicht von Entwickler:innen nicht g\u00e4nzlich unabh\u00e4ngig voneinander, sondern bilden in ihrer Gesamtheit eine Einheit, die widerspruchsfrei definiert sein sollte. Dies spiegelt sich vor allem in der API wider. Beim Designen neuer Komponenten muss daher bekannt sein, wie bisherige Komponenten geschrieben sind, so dass sich ihre API wenn m\u00f6glich analog zu der anderer Komponenten verh\u00e4lt.<\/p>\n<p>Besch\u00e4ftigt sich ein dediziertes Team mit der Aufgabe einer Komponentenbibliothek, so hat dieses Team den \u00dcberblick \u00fcber alle existierenden Komponenten, deren API und Use Cases. Neue Komponenten k\u00f6nnen so einfach kritisch hinterfragt und so ausdefiniert werden, dass sie sich widerspruchsfrei in die schon existierenden Komponenten einbetten lassen. Der gro\u00dfe Vorteil ist dann eine konsistente Ausf\u00fchrung der Komponenten, was es anderen Teams erlaubt, eine gewisse Routine im Umgang und Geschwindigkeit in der Anwendung\u00a0 der Komponenten zu entwickeln.<\/p>\n<h4 id=\"kontextfrei\"><span class=\"ez-toc-section\" id=\"Kontextfrei\"><\/span>Kontextfrei<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>Oft f\u00e4llt es Teams schwer Komponenten, die im Zuge einer Projektarbeit entstehen sollen, vollst\u00e4ndig vom Projektkontext zu l\u00f6sen. Es ist schwierig, die notwendige Abstraktion zu erreichen, die es anderen Teams erlaubt, die Komponente ohne Probleme in einem unterschiedlichen Kontext zu verwenden. Dies ist nicht weiter verwunderlich, da jedes Team seinen eigenen Projektkontext sehr genau kennt und Design-Entscheidungen h\u00e4ufig in Bezug auf diesen Kontext f\u00e4llt. Eine so entstandene Komponente ist dann nur allzu oft in anderen Kontexten nicht zu gebrauchen und muss signifikant (breaking changes) ge\u00e4ndert werden, wenn ein anderes Team diese nutzen m\u00f6chte. Dies birgt die Gefahr von aufw\u00e4ndigen Refactorings aufgrund fehlender Abstraktion.<\/p>\n<p>Auf der anderen Seite hilft es jedoch, sich immer wieder mit der Frage zu besch\u00e4ftigen, in welcher Form die Komponenten eingesetzt werden. Unter Umst\u00e4nden lassen sich immer wiederkehrende Muster in der Verwendung bereits in einer Komponentenbibliothek integrieren, um somit eine\u00a0 Zeitersparnis bei allen Konsumenten zu schaffen.<\/p>\n<h3 id=\"semantic-versioning--changelog\"><span class=\"ez-toc-section\" id=\"Semantic-VersioningChangelog\"><\/span>Semantic Versioning\/Changelog<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Bei einer Komponentenbibliothek sollte unbedingt auf <a href=\"https:\/\/semver.org\">semantische Versionierung<\/a> geachtet werden. Semantisches Versionieren erlaubt es in nur drei Zahlen auszudr\u00fccken, ob \u00c4nderungen an der Bibliothek weitreichende Code-Anpassungen beim Konsumenten erforderlich machen.<\/p>\n<p>Aus unserer Sicht ist es zudem sehr sinnvoll ein Changelog zu f\u00fchren, in dem alle Ver\u00e4nderungen zwischen Versionen notiert werden, sodass Anwender der Bibliothek einfach nachvollziehen k\u00f6nnen, ob und welche Codestellen im eigenen Code angepasst werden m\u00fcssen.<\/p>\n<p>Idealerweise sind bei <em>Breaking Changes<\/em>, also \u00c4nderungen, die eine Anpassung erfordern, auch die entsprechenden Migrationswege dokumentiert.<\/p>\n<h3 id=\"composability\"><span class=\"ez-toc-section\" id=\"Composability\"><\/span>Composability<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Komponenten sollten so geschrieben sein, dass sie schachtelbar sind. Im Geiste von HTML, das \u00fcber das Document Object Model (DOM) beschrieben wird, beinhalten Komponenten oft andere Komponenten und sollten im Allgemeinen unvoreingenommen sein gegen\u00fcber den Komponenten, die ihnen als Kind-Elemente hereingereicht werden.<\/p>\n<p>Eine Ausnahme bilden sogenannte Leaf-Nodes, z.B. Input-Felder, die keine weiteren Kind-Elemente beinhalten k\u00f6nnen, oder solche, die gezielt nur daf\u00fcr gebaut werden, mit ganz speziellen Kind-Elementen zurecht zu kommen (vgl. das <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTML\/Element\/select\">HTML Select Element<\/a>).<\/p>\n<h3 id=\"dokumentation\"><span class=\"ez-toc-section\" id=\"Dokumentation\"><\/span>Dokumentation<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Ein essenzieller Teil einer Komponentenbibliothek ist deren Dokumentation. Die Anwender:innen einer solchen Bibliothek sind andere Entwickler:innen, sodass der Fokus der Dokumentation darauf gerichtet sein sollte, dass sich Entwickler:innen schnell darin zurechtfinden. Die Dokumentation muss neben der vollst\u00e4ndigen API einer Komponente auch deren gew\u00fcnschtes Verhalten beschreiben, sowie ggfs. den Rahmen definieren, in dem die Komponente verwendet werden soll.<\/p>\n<p>Im Idealfall bieten Dokumentationen den Anwendern:innen auch die M\u00f6glichkeit, Live-Beispiele auszuprobieren und den Code zu ver\u00e4ndern, um so spielerisch die Komponente zu erfahren und kennenzulernen. Dies erlaubt es Anwender:innen relativ einfach, ohne komplizierte Beispielprojekte aufsetzten zu m\u00fcssen, abzusch\u00e4tzen, ob eine Komponente das erf\u00fcllt, was sie im Rahmen einer technischen Anforderung leisten muss.<\/p>\n<p>Zudem bietet die Dokumentation den perfekten Ort, um Entscheidungen im Hinblick auf die User Experience zu dokumentieren. Zum Beispiel den Kontext, in dem die Komponente eingesetzt werden darf. In klassischen Projekten existiert dieses Wissen oft entweder nur in den K\u00f6pfen oder in parallel gef\u00fchrten Dokumenten wie Word-Dokumenten oder \u00e4hnlichem. Dies f\u00fchrt h\u00e4ufig dazu, dass UX-Richtlinien nur mangelhaft umgesetzt werden. Die Dokumentation hingegen bietet die richtige Stelle, zus\u00e4tzliche Regeln, die nicht sowieso schon innerhalb der Komponente gekapselt sind, niederzuschreiben und sie den Entwicklern zu verdeutlichen.<\/p>\n<h2 id=\"case-study-ergo-elements\"><span class=\"ez-toc-section\" id=\"Case-Study-ERGO-Elements\"><\/span>Case Study: ERGO Elements<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>&nbsp;<\/p>\n<p><a href=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/05\/styleguide-ergo-elements.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-13716\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/05\/styleguide-ergo-elements-1024x547.png\" alt=\"Komponentenbibliothek f\u00fcr Elemente von ERGO\" width=\"1024\" height=\"547\" srcset=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/05\/styleguide-ergo-elements-1024x547.png 1024w, https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/05\/styleguide-ergo-elements-300x160.png 300w, https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/05\/styleguide-ergo-elements-768x410.png 768w, https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/05\/styleguide-ergo-elements-1536x820.png 1536w, https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/05\/styleguide-ergo-elements-2048x1093.png 2048w, https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/05\/styleguide-ergo-elements-1920x1025.png 1920w, https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/05\/styleguide-ergo-elements-400x214.png 400w, https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/05\/styleguide-ergo-elements-360x192.png 360w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/p>\n<p>Im Rahmen des Projekts \u201c<em>Ergo Elements<\/em>\u201c f\u00fcr unseren Kunden <a href=\"https:\/\/ergodirekt.de\/\">ERGO Direkt<\/a> implementierten wir React-Komponenten und stellten diese weiteren Teams als npm-Bibliothek zur Verf\u00fcgung. Diese Bibliothek wurde nach den oben genannten Ma\u00dfst\u00e4ben und Empfehlungen angefertigt. Die Komponenten wurden daraufhin in Online-Tarifstrecken eingesetzt.<\/p>\n<p>Die Kernentwicklung von etwa 40 Komponenten (mehrheitlich Atome und Molek\u00fcle) und die Anfertigung eines Styleguides ben\u00f6tigte in Summe etwa 250\u2013300 PPT (Projektpersonentage). Zu den Komponenten geh\u00f6rten sowohl einfache Elemente wie ein Button, der sich im Wesentlichen nur durch ein angepasstes Styling auszeichnet, als auch komplexere Komponenten wie ein Datepicker, eine Vergleichstabelle und diverse Komponenten f\u00fcr Frageb\u00f6gen.<\/p>\n<p>Das Erstellen einer Komponentenbibliothek resultierte in gestiegener Qualit\u00e4t und\u00a0 Zeitgewinn: Darstellungs- und browserspezifische Probleme konnten in der Bibliothek zentral behoben werden. Die Anzahl der Probleme in den Projekten wurde dadurch deutlich reduziert, sodass sie die Teams nicht weiter blockierten. Eine individuelle Fehlererfassung z.B. von Styling-Problemen war nicht weiter erforderlich.<\/p>\n<p>Bei einem tiefgreifendem Redesign ein oder mehrerer Web-Applikationen bietet es sich also an, mit ausreichend Vorlauf mit der Ausarbeitung der Komponenten zu beginnen. Diese k\u00f6nnen anschlie\u00dfend von allen Teams eingesetzt werden, um deutlich Zeit einzusparen.<\/p>\n<p>F\u00fcr die Darstellung unserer Komponenten in einem Living Styleguide setzen wir die Open Source Software <a href=\"https:\/\/react-styleguidist.js.org\/\">React Styleguidist<\/a><sup class=\"footnote-ref\"><a id=\"fnref1\" href=\"#fn1\">1<\/a><\/sup> ein. Diese bietet eine Reihe wertvoller Features wie<\/p>\n<ul>\n<li>Dokumentation in <a href=\"https:\/\/de.wikipedia.org\/wiki\/Markdown\">Markdown<\/a><sup class=\"footnote-ref\"><a id=\"fnref2\" href=\"#fn2\">2<\/a><\/sup>,<\/li>\n<li>Verwendung von <a href=\"http:\/\/usejsdoc.org\/\">JSDoc<\/a>, um die Komponenten-APIs darzustellen<sup class=\"footnote-ref\"><a id=\"fnref3\" href=\"#fn3\">3<\/a>\u00a0<\/sup>und<\/li>\n<li>Interaktiv bearbeitbare Code-Beispiele.<\/li>\n<\/ul>\n<p>Der Styleguide beinhaltet sowohl die technische Dokumentation als auch die Dokumentation f\u00fcr Anwender:innen. Zu allen Komponenten werden mehrere Einsatzbeispiele gelistet, welche die unterschiedlichen Zust\u00e4nde der Komponenten dokumentieren. Insbesondere wurde darauf geachtet, realit\u00e4tsbezogene Anwendungsbeispiele zu dokumentieren.<sup class=\"footnote-ref\"><a id=\"fnref4\" href=\"#fn4\">4<\/a><\/sup><\/p>\n<p>Des weiteren enth\u00e4lt der Styleguide alle wichtigen Informationen zur Einrichtung und Verwendung der Komponentenbibliothek und Zusatzinformationen zu den h\u00e4ufigsten Use-Cases, wie z.B. der Verwendung der Komponentenbibliothek im Zusammenspiel mit Validierungs-Frameworks.<\/p>\n<p>Der entstandene Styleguide ist nicht \u00f6ffentlich zug\u00e4nglich, sodass wir uns im folgenden auf eine Reihe von Screenshots beschr\u00e4nken, die den Styleguide zeigen. In Absprache mit unserem Kunden ERGO Direkt d\u00fcrfen wir den Styleguide an dieser Stelle zeigen, wof\u00fcr wir uns recht herzlich bedanken wollen. Generell kann die Funktionsweise des React Styleguidist in deren <a href=\"https:\/\/react-styleguidist.js.org\/examples\/basic\/\">Demo-Anwendung<\/a> nachvollzogen werden.<\/p>\n<figure id=\"attachment_12930\" aria-describedby=\"caption-attachment-12930\" style=\"width: 1024px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/styleguide-component-view.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-12930\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/styleguide-component-view-1024x698.png\" alt=\"Doku der QuestionGroup-Komponente\" width=\"1024\" height=\"698\" \/><\/a><figcaption id=\"caption-attachment-12930\" class=\"wp-caption-text\">Dokumentation der <code>QuestionGroup<\/code>-Komponente, die Fragen in einem Fragebogen kapselt. Die API des Container-Elements ist schmal gehalten, da im konkreten Beispiel die Komponente nur f\u00fcr die Aufz\u00e4hlung der Fragen verantwortlich ist.<\/figcaption><\/figure>\n<figure id=\"attachment_12931\" aria-describedby=\"caption-attachment-12931\" style=\"width: 1024px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/styleguide-component-example.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-12931\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/styleguide-component-example-1024x319.png\" alt=\"Atome einer Komponentenbibliothek ergeben einen Fragebbogen\" width=\"1024\" height=\"319\" \/><\/a><figcaption id=\"caption-attachment-12931\" class=\"wp-caption-text\">Beispiel eines Fragebogens, der aus einzelnen Atomen der Komponentenbibliothek zusammengesetzt ist und als eine neue Komponente bereitgestellt wird. Dieses sogenannte Molek\u00fcl ist dabei aus sieben unterschiedlichen Komponenten zusammengesetzt.<\/figcaption><\/figure>\n<figure id=\"attachment_12932\" aria-describedby=\"caption-attachment-12932\" style=\"width: 1024px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/styleguide-component-example-2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-12932\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/styleguide-component-example-2-1024x379.png\" alt=\"Schachtelung von Komponenten\" width=\"1024\" height=\"379\" \/><\/a><figcaption id=\"caption-attachment-12932\" class=\"wp-caption-text\">Ansicht der Komponente von oben mit aufgeklapptem Tooltip. Die zugrundeliegende Komponente, das <code>TooltipIcon<\/code> wird als eigene Komponente bereitgestellt und kann ohne Mehraufwand in die Komponente eingebunden werden. Dies zeigt, wie Komponenten einfach geschachtelt und wiederverwendet werden k\u00f6nnen.<\/figcaption><\/figure>\n<figure id=\"attachment_12933\" aria-describedby=\"caption-attachment-12933\" style=\"width: 1024px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/styleguide-component-view-2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-12933\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/styleguide-component-view-2-1024x753.png\" alt=\"Properties einer Komponente\" width=\"1024\" height=\"753\" \/><\/a><figcaption id=\"caption-attachment-12933\" class=\"wp-caption-text\">Dokumentation der <code>Question<\/code>-Komponente, die als Teil eines Fragebogens zum Einsatz kommt. Generell werden f\u00fcr jede Komponente ihre Properties dokumentiert. Auch klar ersichtlich ist, ob es sich um verbindliche oder optionale Properties handelt und was ihr Typ und Standard-Wert ist; au\u00dferdem, wie das Verhalten der Komponente durch das Property ver\u00e4ndert wird.<\/figcaption><\/figure>\n<figure id=\"attachment_12934\" aria-describedby=\"caption-attachment-12934\" style=\"width: 1024px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/styleguide-live-code-preview.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-12934\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/styleguide-live-code-preview-1024x445.png\" alt=\"Live-bearbeitung im Styleguide\" width=\"1024\" height=\"445\" \/><\/a><figcaption id=\"caption-attachment-12934\" class=\"wp-caption-text\">Jedes Beispiel kann live im Styleguide bearbeitet werden, so dassder Entwickler die Komponenten schnell und einfach verproben kann.<\/figcaption><\/figure>\n<figure id=\"attachment_12935\" aria-describedby=\"caption-attachment-12935\" style=\"width: 1024px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/styleguide-ux-hint.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-12935\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/styleguide-ux-hint-1024x130.png\" alt=\"Hinweis f\u00fcr bessere UX\" width=\"1024\" height=\"130\" \/><\/a><figcaption id=\"caption-attachment-12935\" class=\"wp-caption-text\">Ansicht eines UX-Hinweises, bei dem darauf aufmerksam gemacht wird, dass das beschriebene Element nur bis maximal drei Optionen haben sollte. Bei mehr als drei Optionen wird dem\/der Entwickler:in eine andere Komponente empfohlen, die ebenfalls in der Komponentenbibliothek bereitgestellt wird. Hierbei handelt es sich um ein nicht-technisches Limit, welches durch Nutzer:innen-Feedback gewonnen wurde.<\/figcaption><\/figure>\n<figure id=\"attachment_12936\" aria-describedby=\"caption-attachment-12936\" style=\"width: 1024px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/webpack-bundle-with-treeshaking.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-12936\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/webpack-bundle-with-treeshaking-1024x1024.png\" alt=\"Kreisdiagram verwendeter und nichtverwendeter Komponenten\" width=\"1024\" height=\"1024\" \/><\/a><figcaption id=\"caption-attachment-12936\" class=\"wp-caption-text\">Die Bibliothek ist so geschrieben, dass alle Komponenten, die in der Anwendung keinen Einsatz finden, im Build-Prozess entfernt werden. Diesen Prozess bezeichnet man als <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Glossary\/Tree_shaking\">Tree Shaking<\/a>.<\/figcaption><\/figure>\n<h2 id=\"referenzen\"><span class=\"ez-toc-section\" id=\"Referenzen\"><\/span>Referenzen<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<ul>\n<li>Styleguide in React, der die <a href=\"https:\/\/material.io\/guidelines\/\">Google Material Design<\/a> Richtlinien aufgreift: <a href=\"http:\/\/www.material-ui.com\/#\/\">Material UI<\/a><\/li>\n<li><a href=\"https:\/\/www.smashingmagazine.com\/taking-pattern-libraries-next-level\/\">Taking The Pattern Library To The Next Level<\/a><\/li>\n<li><a href=\"https:\/\/clearleft.com\/posts\/on-building-component-libraries\">On Building Component Libraries<\/a><\/li>\n<\/ul>\n<section class=\"footnotes\" style=\"font-size: 12pt;\">\n<ol class=\"footnotes-list\">\n<li id=\"fn1\" class=\"footnote-item\">Die Software steht unter <a href=\"https:\/\/github.com\/styleguidist\/react-styleguidist\/blob\/master\/License.md\">MIT-Lizenz<\/a>.<\/li>\n<li id=\"fn2\" class=\"footnote-item\">Code-Beispiele k\u00f6nnen in Markdown <a href=\"https:\/\/help.github.com\/articles\/creating-and-highlighting-code-blocks\/#fenced-code-blocks\">Code-Fences<\/a> definiert werden. Diese werden im Styleguide in Beispiele \u00fcbersetzt, die live im Browser ver\u00e4ndert werden k\u00f6nnen.<\/li>\n<li id=\"fn3\" class=\"footnote-item\">Die Properties der Komponenten k\u00f6nnen wahlweise mittels <a href=\"https:\/\/github.com\/reactjs\/react-docgen\">React Prop-Types (JavaScript)<\/a> oder <a href=\"https:\/\/github.com\/styleguidist\/react-docgen-typescript\">Interfaces (TypeScript)<\/a> definiert werden.<\/li>\n<li id=\"fn4\" class=\"footnote-item\">Wir haben uns bewusst dagegen entschieden jede m\u00f6gliche Konfiguration zu dokumentieren. H\u00e4ufig gibt es schlicht zu viele Konfigurationen, die zwar technisch m\u00f6glich, aber oft nicht sinnvoll sind. Wir versuchen im Rahmen des Styleguides, die h\u00e4ufigsten Anwendungsf\u00e4lle abzudecken. Im Rahmen von Tests werden jedoch auch die Anwendungsf\u00e4lle abgedeckt, die technisch spezifiziert sind, jedoch nicht zu den prim\u00e4ren Use Cases geh\u00f6ren.<\/li>\n<\/ol>\n<\/section>\n","protected":false},"excerpt":{"rendered":"<p>F\u00fcr gr\u00f6\u00dfere Projekte, in denen mehrere Teams parallel an Web-Applikationen entwickeln, k\u00f6nnen wir bedenkenlos die Entwicklung und den Einsatz einer Komponentenbibliothek empfehlen. Im Folgenden m\u00f6chten wir diesen Begriff erl\u00e4utern und aus unseren Erfahrungen berichten.<\/p>\n","protected":false},"author":38,"featured_media":13406,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"ep_exclude_from_search":false,"footnotes":""},"tags":[70],"service":[425,444],"coauthors":[{"id":38,"display_name":"Johannes Reuter","user_nicename":"jreuter"}],"class_list":["post-21086","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","tag-web","service-backend","service-frontend"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Komponentenbibliotheken f\u00fcr die Web-Entwicklung - inovex GmbH<\/title>\n<meta name=\"description\" content=\"Im Folgenden m\u00f6chten wir den Begriff der Komponentenbibliothek erl\u00e4utern und aus unseren Erfahrungen der parallelen Web-Entwicklung berichten.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Komponentenbibliotheken f\u00fcr die Web-Entwicklung - inovex GmbH\" \/>\n<meta property=\"og:description\" content=\"Im Folgenden m\u00f6chten wir den Begriff der Komponentenbibliothek erl\u00e4utern und aus unseren Erfahrungen der parallelen Web-Entwicklung berichten.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/\" \/>\n<meta property=\"og:site_name\" content=\"inovex GmbH\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/inovexde\" \/>\n<meta property=\"article:published_time\" content=\"2018-05-28T11:09:54+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-03-19T06:29:30+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/komponentenbibliothek.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1920\" \/>\n\t<meta property=\"og:image:height\" content=\"1080\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Johannes Reuter\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/komponentenbibliothek-1024x576.png\" \/>\n<meta name=\"twitter:creator\" content=\"@inovexgmbh\" \/>\n<meta name=\"twitter:site\" content=\"@inovexgmbh\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Johannes Reuter\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"20\u00a0Minuten\" \/>\n\t<meta name=\"twitter:label3\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data3\" content=\"Johannes Reuter\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/\"},\"author\":{\"name\":\"Johannes Reuter\",\"@id\":\"https:\/\/www.inovex.de\/de\/#\/schema\/person\/2e7c8f474580d46832a7666b61f8c1ec\"},\"headline\":\"Komponentenbibliotheken f\u00fcr die Web-Entwicklung\",\"datePublished\":\"2018-05-28T11:09:54+00:00\",\"dateModified\":\"2025-03-19T06:29:30+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/\"},\"wordCount\":3427,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\/\/www.inovex.de\/de\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/komponentenbibliothek.png\",\"keywords\":[\"Web\"],\"articleSection\":[\"Applications\",\"General\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/\",\"url\":\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/\",\"name\":\"Komponentenbibliotheken f\u00fcr die Web-Entwicklung - inovex GmbH\",\"isPartOf\":{\"@id\":\"https:\/\/www.inovex.de\/de\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/komponentenbibliothek.png\",\"datePublished\":\"2018-05-28T11:09:54+00:00\",\"dateModified\":\"2025-03-19T06:29:30+00:00\",\"description\":\"Im Folgenden m\u00f6chten wir den Begriff der Komponentenbibliothek erl\u00e4utern und aus unseren Erfahrungen der parallelen Web-Entwicklung berichten.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#primaryimage\",\"url\":\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/komponentenbibliothek.png\",\"contentUrl\":\"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/komponentenbibliothek.png\",\"width\":1920,\"height\":1080,\"caption\":\"Das Wort Bibliothek zusammengesetzt aus geometrischen Komponenten\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.inovex.de\/de\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Komponentenbibliotheken f\u00fcr die Web-Entwicklung\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.inovex.de\/de\/#website\",\"url\":\"https:\/\/www.inovex.de\/de\/\",\"name\":\"inovex GmbH\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/www.inovex.de\/de\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.inovex.de\/de\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.inovex.de\/de\/#organization\",\"name\":\"inovex GmbH\",\"url\":\"https:\/\/www.inovex.de\/de\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\/\/www.inovex.de\/de\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.inovex.de\/wp-content\/uploads\/2021\/03\/inovex-logo-16-9-1.png\",\"contentUrl\":\"https:\/\/www.inovex.de\/wp-content\/uploads\/2021\/03\/inovex-logo-16-9-1.png\",\"width\":1921,\"height\":1081,\"caption\":\"inovex GmbH\"},\"image\":{\"@id\":\"https:\/\/www.inovex.de\/de\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/inovexde\",\"https:\/\/x.com\/inovexgmbh\",\"https:\/\/www.instagram.com\/inovexlife\/\",\"https:\/\/www.linkedin.com\/company\/inovex\",\"https:\/\/www.youtube.com\/channel\/UC7r66GT14hROB_RQsQBAQUQ\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.inovex.de\/de\/#\/schema\/person\/2e7c8f474580d46832a7666b61f8c1ec\",\"name\":\"Johannes Reuter\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\/\/www.inovex.de\/de\/#\/schema\/person\/image\/6e76acaf394b88ba3914670bfc4db231\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/4cd215069ed19f8429692365d40f5a8e94a674eea57579c97b182c853c9cd0d0?s=96&d=retro&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/4cd215069ed19f8429692365d40f5a8e94a674eea57579c97b182c853c9cd0d0?s=96&d=retro&r=g\",\"caption\":\"Johannes Reuter\"},\"url\":\"https:\/\/www.inovex.de\/de\/blog\/author\/jreuter\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Komponentenbibliotheken f\u00fcr die Web-Entwicklung - inovex GmbH","description":"Im Folgenden m\u00f6chten wir den Begriff der Komponentenbibliothek erl\u00e4utern und aus unseren Erfahrungen der parallelen Web-Entwicklung berichten.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/","og_locale":"de_DE","og_type":"article","og_title":"Komponentenbibliotheken f\u00fcr die Web-Entwicklung - inovex GmbH","og_description":"Im Folgenden m\u00f6chten wir den Begriff der Komponentenbibliothek erl\u00e4utern und aus unseren Erfahrungen der parallelen Web-Entwicklung berichten.","og_url":"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/","og_site_name":"inovex GmbH","article_publisher":"https:\/\/www.facebook.com\/inovexde","article_published_time":"2018-05-28T11:09:54+00:00","article_modified_time":"2025-03-19T06:29:30+00:00","og_image":[{"width":1920,"height":1080,"url":"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/komponentenbibliothek.png","type":"image\/png"}],"author":"Johannes Reuter","twitter_card":"summary_large_image","twitter_image":"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/komponentenbibliothek-1024x576.png","twitter_creator":"@inovexgmbh","twitter_site":"@inovexgmbh","twitter_misc":{"Verfasst von":"Johannes Reuter","Gesch\u00e4tzte Lesezeit":"20\u00a0Minuten","Written by":"Johannes Reuter"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#article","isPartOf":{"@id":"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/"},"author":{"name":"Johannes Reuter","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/person\/2e7c8f474580d46832a7666b61f8c1ec"},"headline":"Komponentenbibliotheken f\u00fcr die Web-Entwicklung","datePublished":"2018-05-28T11:09:54+00:00","dateModified":"2025-03-19T06:29:30+00:00","mainEntityOfPage":{"@id":"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/"},"wordCount":3427,"commentCount":1,"publisher":{"@id":"https:\/\/www.inovex.de\/de\/#organization"},"image":{"@id":"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#primaryimage"},"thumbnailUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/komponentenbibliothek.png","keywords":["Web"],"articleSection":["Applications","General"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/","url":"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/","name":"Komponentenbibliotheken f\u00fcr die Web-Entwicklung - inovex GmbH","isPartOf":{"@id":"https:\/\/www.inovex.de\/de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#primaryimage"},"image":{"@id":"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#primaryimage"},"thumbnailUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/komponentenbibliothek.png","datePublished":"2018-05-28T11:09:54+00:00","dateModified":"2025-03-19T06:29:30+00:00","description":"Im Folgenden m\u00f6chten wir den Begriff der Komponentenbibliothek erl\u00e4utern und aus unseren Erfahrungen der parallelen Web-Entwicklung berichten.","breadcrumb":{"@id":"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#primaryimage","url":"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/komponentenbibliothek.png","contentUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2018\/03\/komponentenbibliothek.png","width":1920,"height":1080,"caption":"Das Wort Bibliothek zusammengesetzt aus geometrischen Komponenten"},{"@type":"BreadcrumbList","@id":"https:\/\/www.inovex.de\/de\/blog\/komponentenbibliotheken\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.inovex.de\/de\/"},{"@type":"ListItem","position":2,"name":"Komponentenbibliotheken f\u00fcr die Web-Entwicklung"}]},{"@type":"WebSite","@id":"https:\/\/www.inovex.de\/de\/#website","url":"https:\/\/www.inovex.de\/de\/","name":"inovex GmbH","description":"","publisher":{"@id":"https:\/\/www.inovex.de\/de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.inovex.de\/de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/www.inovex.de\/de\/#organization","name":"inovex GmbH","url":"https:\/\/www.inovex.de\/de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/logo\/image\/","url":"https:\/\/www.inovex.de\/wp-content\/uploads\/2021\/03\/inovex-logo-16-9-1.png","contentUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2021\/03\/inovex-logo-16-9-1.png","width":1921,"height":1081,"caption":"inovex GmbH"},"image":{"@id":"https:\/\/www.inovex.de\/de\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/inovexde","https:\/\/x.com\/inovexgmbh","https:\/\/www.instagram.com\/inovexlife\/","https:\/\/www.linkedin.com\/company\/inovex","https:\/\/www.youtube.com\/channel\/UC7r66GT14hROB_RQsQBAQUQ"]},{"@type":"Person","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/person\/2e7c8f474580d46832a7666b61f8c1ec","name":"Johannes Reuter","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/person\/image\/6e76acaf394b88ba3914670bfc4db231","url":"https:\/\/secure.gravatar.com\/avatar\/4cd215069ed19f8429692365d40f5a8e94a674eea57579c97b182c853c9cd0d0?s=96&d=retro&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/4cd215069ed19f8429692365d40f5a8e94a674eea57579c97b182c853c9cd0d0?s=96&d=retro&r=g","caption":"Johannes Reuter"},"url":"https:\/\/www.inovex.de\/de\/blog\/author\/jreuter\/"}]}},"_links":{"self":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/21086","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/users\/38"}],"replies":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/comments?post=21086"}],"version-history":[{"count":5,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/21086\/revisions"}],"predecessor-version":[{"id":61294,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/21086\/revisions\/61294"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/media\/13406"}],"wp:attachment":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/media?parent=21086"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/tags?post=21086"},{"taxonomy":"service","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/service?post=21086"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/coauthors?post=21086"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}