Erweiterung eines bestehenden Projekts mit ReactJS
Einleitung
Als Frontend-Entwickler stößt man heutzutage sehr oft auf die gehypte Javascript Library React. Die extreme Popularität der "Javascript-Bibliothek zum Erstellen von Benutzeroberflächen" (https://reactjs.org/) ist ungebrochen und wächst mit der immer größer werdenden Verbreitung von Web-Apps stetig. So setzt auch das vor kurzem veröffentlichte Magento PWA-Studio zur Erstellung einer Progressive Web App für Magento2 komplett auf die Bibliothek. Allerdings wird React mittlerweile sehr häufig nur noch mit Single-Page-Applikationen (SPA) in Verbindung gebracht, was aber einen großen Vorteil komplett unterschlägt: React wurde von Grund auf dahin konzipiert und optimiert, es als Erweiterung für bestehende Projekte zu verwenden. Hier zeigt sich auch, warum React als Bibliothek und nicht als Framework bezeichnet wird.
Im Entwickler-Alltag ist es oft eben nicht der Fall, dass man ein komplett neues Frontend (als SPA) erstellen soll, sondern ein bestehendes Projekt weiterentwickelt. Hier ist es oft schwierig, kostet zu viele Ressourcen oder ist komplett unnötig die gesamte Applikation zu einer SPA umzubauen. Gleichzeitig möchte man als Entwickler aber die Vorteile, die eine neue Technologie wie z.B. React bietet, nutzen.
Dieser Artikel soll also zeigen, wie React sehr einfach in ein bereits bestehendes Frontend integriert oder einzelne Komponenten ausgetauscht werden können. Im Folgenden werden einige grundlegende React-Kenntnisse vorausgesetzt.
Demo
Das im Folgenden beschriebene Beispiel-Setup und -Projekt ist als Demo-Code unter https://github.com/mothership-gmbh/react-demo verfügbar.
Setup/Installation
In diesem Beispiel wird ein möglichst einfaches Setup ohne Module-Bundler wie Webpack o.ä. gezeigt. Es wird einzig und allein eine Kompilierung von JSX zu Javascript aufgesetzt, hier über den Task Runner Gulp, der in vielen Projekten schon vorhanden sein könnte und entsprechend nur noch erweitert werden müsste.
Voraussetzungen:
- NodeJS (https://nodejs.org/de/)
- Gulp (https://gulpjs.com/)
Nachdem beides installiert ist, kann im Root-Verzeichnis folgende package.json
erzeugt werden.
package.json
{ "name": "mothership-react-demo", "version": "1.0.0", "description": "Wir integrieren React in eine bestehende App", "main": "index.js", "author": "Mothership GmbH", "devDependencies": { "@babel/core": "^7.1.2", "@babel/plugin-transform-react-jsx": "^7.0.0", "gulp": "^4.0.0", "gulp-babel": "^8.0.0-beta.2" } }
Nach dem Ausführen des Befehls npm install
ist das Grundsetup schon fertig. Nun fehlt nur noch die Konfiguration von Gulp, damit die JSX-Syntax in valides Javascript kompiliert wird. Dazu legen wir die Datei gulpfile.js
mit folgendem Inhalt an.
gulpfile.js
var gulp = require('gulp'); var babel = require('gulp-babel'); // JSX-Task um JSX in Javascript zu kompilieren gulp.task('jsx', () => { return gulp.src('web/js/react/src/**/*.js') .pipe(babel({ plugins: ['@babel/plugin-transform-react-jsx'] })) .pipe(gulp.dest('web/js/react/dist')); }); // Watch-Task um Änderungen am JSX automatisch zu kompilieren gulp.task('watch', function () { gulp.watch('web/js/react/src/**/*.js', {ignoreInitial: false}, gulp.series('jsx')); }); // Default Task von Gulp gulp.task('default', gulp.parallel(['watch']));
Die Dateistruktur sieht in diesem Beispiel also wie folgt aus: Alle React-spezifischen Dateien befinden sich im Ordner js/react
, um eine möglichst einfache Abgrenzung von evtl. bereits existierendem Javascript-Code zu schaffen. Die JSX-Quelldateien werden in web/js/react/src
abgelegt, die fertig kompilierten Dateien sind in web/js/react/dist
zu finden.
app ├── gulpfile.js ├── package-lock.json ├── package.json └── web ├── css ├── mothership.css └── styles.css ├── index.html └── js └── react ├── dist │ └── modal.js ├── src │ └── modal.js └── vendor ├── react-dom.js └── react.js
React Komponente entwickeln und in bestehender Seite verwenden
Um das Beispiel möglichst einfach zu halten, soll eine simple Modal-Komponente entwickelt werden, die sich durch den Klick eines Buttons aufrufen lässt.
Zuerst muss auf der Seite, die die React-Komponente enthalten soll (hier: index.html
), die React-Bibliothek eingebunden werden. Dazu braucht es zwei Dateien, react.js
und react-dom.js
. Diese können z.B. über ein CDN geladen werden, im Beispiel werden sie lokal bereitgestellt. Zu beachten ist, dass diese beiden Dateien vor dem Javascript der späteren Komponente eingebunden werden.
Im Folgenden wird nun die React-Komponente erstellt und in die Seite integriert. Dazu braucht es ein Container-Element im DOM, hier mit der ID react-modal
.
index.html
<html> <head>...</head> <body> ... <!-- Container-Element für die React-Komponente --> <div id="react-modal"></div> ... <script type="text/javascript" src="js/react/vendor/react.js"></script> <script type="text/javascript" src="js/react/vendor/react-dom.js"></script> <!-- Einbinden der Modal-Komponente --> <script type="text/javascript" src="js/react/dist/modal.js"></script> </body> </html>
Die React-Komponente ist sehr simpel gehalten. Da das Modal zuerst einmal ausgeblendet sein soll, wird der initiale State isOpen
auf false gesetzt. Über die Funktion toggleOpen
kann dieser Status gewechselt werden.
Gerendert wird das Modal so, dass sowohl bei Klick auf den Button "Modal öffnen" als auch bei Klick auf den Hintergrund (bei geöffnetem Modal) toggleOpen
aufgerufen wird, sodass sich das Modal entsprechend öffnet, bzw. schließt.
Zuletzt wird die Komponente in den zuvor beschriebenen DOM-Container mit der ID react-modal
eingefügt.
js/react/dist/modal.js
'use strict'; class Modal extends React.Component { constructor(props) { super(props); this.state = { isOpen: false }; this.toggleOpen = this.toggleOpen.bind(this); } toggleOpen() { this.setState({ isOpen: !this.state.isOpen }); } render() { var className = 'modal'; className += this.state.isOpen ? ' open' : ''; return <div> <button className='button-open' onClick={this.toggleOpen}>Modal öffnen</button> <div className={className}> <div className='content'> <button className='close-button' onClick={this.toggleOpen}>X</button> <div> <h2>Ich bin das Modal</h2> <div>Man kann mich über das X schließen, aber auch über einen Klick außerhalb</div> <iframe src="https://giphy.com/embed/xT77XWum9yH7zNkFW0" width="480" height="270" frameBorder="0" className='giphy-embed' allowFullScreen> </iframe> <p> <a href="https://giphy.com/gifs/9jumpin-wow-nice-well-done-xT77XWum9yH7zNkFW0">via GIPHY</a> </p> </div> </div> <button className='background' onClick={this.toggleOpen}/> </div> </div> } } const e = React.createElement; const domContainer = document.querySelector('#react-modal'); ReactDOM.render(e(Modal), domContainer);
Fazit
Obwohl React meist in einem Atemzug mit Single-Page-Applikationen genannt wird, eignet es sich auch hervorragend, um ein bereits bestehendes Frontend mit einigen dynamischen Elementen modular zu erweitern. So müssen Frontend-Entwickler nicht auf den Einsatz dieser modernen Technologie verzichten, ohne einen kompletten Relaunch/Rewrite des Frontends nötig zu machen. React-Neulinge haben des Weiteren so die Möglichkeit, schon jetzt mit wenig Aufwand Erfahrung mit der Bibliothek zu sammeln, um so für zukünftige Aufgaben (z.B. die Umsetzung einer Magento2 PWA-Storefront) gewappnet zu sein.
Weitere Blog-Artikel
Composable Commerce und Shopware: Ein Interview mit unserem Entwickler Niklas
Niklas, einer unserer Entwickler, erzählt uns von Shopware Frontends, Composable Commerce und seiner Arbeit bei Mothership.
Recap zur Shopware Unconference 2024
Andreas, Don Bosco und Niklas teilen ihre Erfahrungen von der Shopware Unconference 2024 in Köln.
Unser Co-Founder Don Bosco van Hoi im Interview
Unser Co-Geschäftsführer Bosco steht und Rede und Antwort rund um Mothership, Shopware und E-Commerce.