Übersetzen von Staubvorlagen in JSX



Hallo Habr! Ich bin Miloš aus Badoo und dies ist mein erster Habr-Beitrag, der ursprünglich in unserem Tech-Blog veröffentlicht wurde . Ich hoffe es gefällt euch und bitte teile und kommentiere, wenn du irgendwelche Fragen hast

Also ... Reagiere, Amirit ???

Es erschien Mitte des Jahrzehnts (geplagt von den endlosen JavaScript-Framework-Kriegen), umfasste das DOM , schockierte alle, indem es HTML mit JavaScript mischte, und veränderte die Webentwicklungslandschaft bis zur Unkenntlichkeit.

All diese Errungenschaften, ohne auch nur ein Rahmen zu sein .

Lieben Sie es oder hassen Sie es, React macht einen Job wirklich gut, und das ist HTML-Vorlage. Zusammen mit einer großartigen Community und einem gesunden Ökosystem ist es nicht schwer zu verstehen, warum es zu einer der beliebtesten und einflussreichsten JavaScript-Bibliotheken wurde, wenn nicht sogar zu der beliebtesten von allen.


Hier im Mobile Web-Team folgen wir keinen strengen JS-Frameworks - oder zumindest keinen beliebten - und verwenden eine Mischung aus Legacy- und modernen Technologien. Obwohl dies für uns gut funktioniert, ist die Manipulation von DOM normalerweise schwierig. Wir wollten dies verringern, indem wir die Anzahl der "manuellen" Aktualisierungen reduzieren, die Wiederverwendung von Code erhöhen und uns weniger Gedanken über Speicherverluste machen.

Nach einigen Nachforschungen wurde React als die beste Wahl angesehen und wir entschieden uns dafür.

Ich bin mitten in diesem Prozess zu Badoo gekommen. Nachdem ich zuvor gebootet und an React-Projekten gearbeitet hatte, war ich mir der Vor- und Nachteile in der Praxis bewusst, aber die Migration einer ausgereiften Anwendung mit Hunderten von Millionen Benutzern ist eine völlig andere Herausforderung.

Jsx


React mischt HTML mit JavaScript in einem Format namens JSX . Obwohl es wie eine Vorlagensprache aussieht, ist JSX eigentlich nur eine Syntax oder syntaktischer Zucker, wenn man so will, für React-Aufrufe, die HTML sehr ähnlich sehen.

Unsere eigenen HTML-Dateien waren gut organisiert, und die meisten unserer Renderings wurden so einfach wie template.render() . Wie können wir diese Ordnung und Einfachheit beibehalten, während wir zu React übergehen? Abgesehen von technischen Schwierigkeiten war mir eine Idee klar: Ersetzen Sie unsere vorhandenen Aufrufe durch JSX-Code.

Bild


Nach anfänglicher Planung habe ich es ausprobiert und ein Befehlszeilentool eingepackt, das zwei einfache Dinge ausführt:

  1. Liest Vorlagen, auf die in der JavaScript-Datei (UI) verwiesen wird
  2. Ersetzen Sie die Aufrufe von template.render() durch den HTML-Inhalt

Dies würde uns natürlich nur zur Hälfte bewegen, da wir den HTML-Code immer noch manuell ändern müssten. Angesichts des Umfangs und der Anzahl unserer Vorlagen wusste ich, dass der beste Ansatz etwas Automatisiertes sein würde. Die ursprüngliche Idee klang einfach genug - und wenn sie erklärt werden kann, kann sie umgesetzt werden.

Nachdem ich das erste Tool für Teamkollegen vorgeführt hatte, erhielt ich das beste Feedback, dass für die von uns verwendete Vorlagensprache ein Parser verfügbar ist . Das bedeutet, dass wir Code viel einfacher analysieren und übersetzen können als beispielsweise mit regulären Ausdrücken . Da wusste ich wirklich, dass das funktionieren würde!

Bild


Und siehe da, nach einigen Tagen wurde ein Tool geboren, mit dem Dust.js HTML-ähnliche Vorlagen in JSX React-Code konvertiert werden können . Wir haben Dust verwendet, aber mit einer großen Verfügbarkeit von Parsern sollte der Prozess für die Übersetzung aller anderen gängigen Template-Sprachen ähnlich sein.

Weitere technische Details finden Sie im folgenden Open-Source-Abschnitt. Wir haben Tools wie Esprima verwendet , um JS-Code zu analysieren, und einen PEG.js- Parser-Generator, um Staubvorlagen zu analysieren. Im einfachsten Fall geht es darum, diese Art von Vorlagencode zu übersetzen:

 <div class="encounters {?isExpanded}is-expanded{/isExpanded}"> {?showTooltip} <div class="tooltip"> <span>{#_t}{encounters_tooltip}{/_t}</span> <div class="icon"> {@Icon name="icon-encounters" size="stretch" /} </div> </div> {/showTooltip} <div class="images"> {#images} <img src="{src}"> <input type="radio" id="{id}" {?selected}checked{/selected} /> <label for="showme-{id}"> {name} </label> {/images} </div> <div class="footer"> {! encounters-footer template will be injected here !} </div> </div> 

zu seinem JSX-Code-Äquivalent:

 <div className="encounters {props.isExpanded ? 'is-expanded' : ''}"> {props.showTooltip ? <div className="tooltip"> <span>{i18n.get('encounters_tooltip')}</span> <div className="icon"> <Icon name="icon-encounters" size="stretch" /> </div> </div> : null} <div className="images"> {props.images.map(item => <img src={item.src}> <input type="radio" id={`showme-${item.id}`} defaultChecked={item.selected ? true : undefined} /> <label htmlFor={`showme-${item.id}`}> {item.name} </label> )} </div> <div className="footer"> {/* encounters-footer template will be injected here */} </div> </div> 

Siehe nebeneinander Vergleich hier .

Danach war unser Prozess ziemlich unkompliziert. Wir haben unsere Vorlagen automatisch von einem Format in ein anderes konvertiert und alles hat wie erwartet funktioniert (danke, automatisiertes Testen). Zunächst haben wir unsere alte template.render() API beibehalten, um Änderungen isoliert zu halten.

Bei diesem Ansatz erhalten Sie natürlich immer noch Vorlagen und keine „richtigen“ React-Komponenten. Der eigentliche Vorteil besteht darin, dass es viel einfacher, wenn nicht trivial ist, von Vorlagen, die bereits JSX sind, zu React zu wechseln. In den meisten Fällen wird ein Vorlagencode einfach in einen Funktionsaufruf eingeschlossen.

Sie könnten denken: Warum nicht stattdessen neue Vorlagen von Grund auf neu schreiben? Die kurze Antwort lautet: An unseren alten Vorlagen war nichts auszusetzen - wir hatten einfach viele davon. Das ist eine andere Geschichte , wenn man sie umschreibt und auf eine echte Komponentisierung hinarbeitet .



Einige könnten argumentieren, dass das Komponentenmodell nur ein weiterer Trend ist, der vorübergehen könnte. Warum sollten Sie sich also dazu verpflichten? Es ist schwer vorherzusagen, aber eine mögliche Antwort ist, dass Sie nicht müssen . Wenn Sie schnell iterieren, können Sie verschiedene Optionen ausprobieren, ohne zu viel Zeit damit zu verbringen, bis Sie das Format gefunden haben, das für Ihr Team am besten geeignet ist. Das ist eines der Kernkonzepte für uns bei Badoo.

Mit dem Aufstieg von ES7 / 8 / Next, Elm und Reason, ganz zu schweigen von TypeScript und ähnlichen Lösungen, wird Code, der früher *.js , immer weniger von JavaScript zu unterscheiden, und dieser Trend *.js sich fortzusetzen. Warum nicht zu unserem Vorteil nutzen, anstatt davon überwältigt zu werden?

Open Source


Um eines gut zu machen , haben wir diese internen Tools in mehreren Teilen aufgebaut:

  1. Dust2JSX - Paket, das für die tatsächliche Übersetzung von Staub in JSX verantwortlich ist
  2. ratt (React All The Things) - Befehlszeilentool zum Lesen / Schreiben von Dateien auf der Festplatte. Verantwortlich für das dust2jsx Vorlagen, auf die dust2jsx , und verwendet intern dust2jsx um Code zu transformieren

Wir haben diese Tools sogar als Open-Source-Version bereitgestellt. Schauen Sie sich diese sowie andere Open-Source-Materialien auf unserer GitHub- Seite an. Bitte tragen Sie bei oder hinterlassen Sie uns einfach einen Kommentar, wenn Sie diese nützlich finden.

Source: https://habr.com/ru/post/de437224/


All Articles