Support » Allgemeine Fragen » JS Konflikte

  • pezi

    (@pezi)


    Hallo!

    Mitunter kommen sich div. JS gesteuerte Elemente gegenseitig in die Quere. Mal lädt eines davon gar nicht, manchmal erscheint ein Element nur zeitweise, manchmal ist es nur durch Shift+F5 wiederzuerwecken, uvam.

    Dabei ist es oft egal, wie diese eingebunden werden: ob einfach Copy+Paste Code in ein Text/HTML/… Widget, von einem Plugin oder mittels des Code-Inserter Plugins „Code-Snippet“ (uä.).
    Ebenfalls ist es scheinbar(?) egal, ob man die Scripts im Header oder Footer lädt, bzw. laden lässt, falls ein Plugin diese Option bietet.

    Einzige Lösung ist manchmal der Verzicht, zwei oder mehrere sture Elemente wenigstens nicht in der gleichen Ansicht (Start oder Beitrags/Archiv) zu zeigen. Manche vertragen sich aber nicht einmal auf der gleichen Website.

    Beim einfügen von JS mit „Code-Snippet“ gibt es ja so eine Option „Priorität“. Doch auch da scheint keine Auswirkungen zu haben. Was sich (aus welchen Grund auch immer) nicht verträgt, lässt sich eben nicht zusammen einsetzen.

    Klar ist das schwammig, ich kann wenig konkrete Beispiele nennen und schon gar keine Links zu einer Testsite. Ich experimentiere eben nur am XAMPP, wo es auch kein HTTP2 gibt usw.
    Beispiel: Ein BoD-Script(ebook Anzeige von http://www.bod.de) kommt einem (per JS eingebunden) Banner in die Quere. (Klar kann es da auch sein, dass sich irgendwelche gleichlautenden Vars oder gar Funktionen der (oft externen JS Quellen) gegenseitig stören, oder?)

    Die Kernfrage ist: Welche (WP) Optionen, Tricks, Infoquellen, Analysen, … könnten helfen, wenn sich zwei JS in WP mal nicht vertragen? Wo beginnt man mit der Spurensuche?

    Danke!

Ansicht von 7 Antworten - 1 bis 7 (von insgesamt 7)
  • Moderator Bego Mario Garde

    (@pixolin)

    42. Also, die Amtwort „auf die Frage nach dem Leben, dem Universum und dem ganzen Rest“ lautet 42. Ob dir das bei deiner sehr, sehr breit gehaltenen Frage hilft, kann ich nicht beurteilen. 😀

    OK, blöde Antwort? Fangen wir anders an: Ich habe vor langer Zeit mal ein kleines Plugin geschrieben – mehr aus Neugierde, wie eigentlich das Plugin-Verzeichnis funktioniert, was die Voraussetzungen sind, wie das Plugin dort landet, was dann passiert. Das Plugin sollte Anwendern die Möglichkeit geben, mit dem TinyMCE-Editor (Classic Editor) im Text Link-Anker zu setzen (sehr praktisch, wenn z.B. auf einer Rezeptsammlung nach einer ausführlichen Diskussion einiger Zutat das Rezept erst ganz am Ende kommt: <div id="rezept">Rezept</div> mit einem Link <a href="#rezept">Zum Rezept springen"</a>) und mit einer kleinen jQuery-Funktion sollte der Link mit einer sanften Scroll-Animation angesteuert werden. Kein großes Ding, mir ging’s ja mehr um die Erfahrung.

    Meine jQuery-Funktion suchte dazu mit $('a[href*="#"]') nach allen internen Links, deren Attribut zur Link-Quelle mit dem Rautezeichen begann. Und damit fing der Ärger an.

    • Als erstes meldete sich jemand, weil es zu einem Konflikt mit „Platzhalter-Links“ kam, die anderes JavaScript triggern sollen (<a href="#" onclick="javascriptfunktion()">anderes JavaScript ausführen</a>).
    • Dann machte jemand darauf aufmerksam, dass das Kommentar-Formular auch eine ID hat, die im Theme als Link verwendet werden kann (#respond).
    • Ein anderer Anwender machte mich darauf aufmerksam, dass Woocommerce für die Produkt-Tabs Hyperlinks verwenden würde (.woocommerce #tabs) und durch meine jQuery-Funktion die Tabs nicht mehr funktionieren würden … 

    Die Liste wurde dann fortgesetzt und ich habe ein Optionsfeld eingetragen, mit dem solche ID’s ganz indivduell ausgeschlossen werden konnten, was das Plugin aber nun eben nicht mehr ganz so einfach machte. Ich hab’s dann irgendwann aus dem Plugin-Verzeichnis entfernen lassen und bekam dafür dann auch noch mein Contributor-Badge als Plugin-Entwickler entzogen. Blöd gelaufen.

    Mein persönliches Fazit war, dass es mit JavaScript- bzw. jQuery-Funktionen rasch möglich ist, ungewollt Konflikte zu erzeugen. Dazu musst du gar nicht irgendwelche Namenskonflikte erzeugen, es reicht, wenn deine Funktion auf ganz selbstverständliche Dinge wie ein Anchor-Tag zugreift, ganz einfach weil JavaScript das übliche Verhalten von HTML und CSS verändert und es keine Vorgaben gibt, was eine JavaScript-Funktion in einem Plugin darf oder nicht. Sicher werden Entwickler ihr Plugin mit „großen“ Plugins wie WooCommerce, Jetpack, Gutenberg usw. testen, aber es ist unmöglich, die Funktionalität gegen alle 58.987 Plugins (sowie einige kommerzielle und individuell angefertigte Lösungen) zu testen.

    Grundsätzlich hilft immer ein Blick in die Entwickler-Tools, weil dir dort zumindest in der Konsole JavaScript-Fehler (einschließlich der verursachenden Datei) angezeigt werden. Durch Deativieren von Plugins lässt sich die Fehlerquelle meist schnell eingrenzen.

    Soviel zu „Welche Tipps und Tricks gibt es, wenn sich zwei JavaScript-Funktionen nicht vertragen“. Und das Handtuch nicht vergessen.

    Thread-Ersteller pezi

    (@pezi)

    Vielen Dank für die ausführliche Antwort nach dem Sinn des (Coder)Lebens.
    Ja, es hilft mir.

    Verstehe auch die Intention und das spätere Aufgeben des Plugin Projekts. Das Wertvollste daran war vielleicht der technische Lerneffekt. Und die Erkenntnis, wie viel mehr Zeit dann der Support für ein (evtl. kostenloses) Plugin kostet, gell.

    Bez. technischer Konflikte lag ich also nicht so weit daneben, wenn ich eben Namenskonflikte usw. als Ursache vermutete.

    aber es ist unmöglich, die Funktionalität gegen alle 58.987 Plugins … zu testen

    Wow, das da nicht mehr passiert, bei Mio an Vars, Funktionsnamen, IDs. … ist ein Wunder.
    Gibt es eigentlich eine Art Empfehlung für Entwickler, ihre Sachen mit möglichst unverwechselbaren präfix/suffix oder so zu kennzeichnen?

    Durch Deativieren von Plugins lässt sich die Fehlerquelle meist schnell eingrenzen.

    Naja, „Fehler„: 2 Scripts vertragen sich nicht, wegen [beliebige Ursache einsetzen], sind aber für sich allein fehlerfrei.

    Will man nun beide haben, ist nur eigene Bastelarbeit an fertigen Sachen angesagt (die beim Update wieder überschrieben wird). Das zeitversetzte Laden hilft nicht, weil das zuletzt ausgeführte Script der beiden Streithähne das Sagen hat. Glaub ich zumindest.

    Moderator Bego Mario Garde

    (@pixolin)

    Im Plugin Developer Handbook (sowas wie der Intergalaktische Reiseführer für Plugin-Entwickler/-innen) gibt es einen Abschnitt zu Best Practices, in dem verschiedene Möglichkeiten erläutert werden, wie du bei PHP-Funktionen Namenskollisionen vermeiden kannst. (Einige Kritiker behaupten, dass in WordPress Objektorientierte Programmierung nur zu diesem Zweck verwendet wird. 😉 )

    Außerdem gibt es in WordPress die Funktion wp_enqueue_script(), die Bibliotheken wie jQuery nur läd, wenn sie nicht bereits geladen sind. Statt eine JavaScript-Funktion über den Hook wp_head() einfach irgendwie in den Header zu laden, sollten JavaScript-Funktionen deshalb bevorzugt mit wp_enqueue_script() geladen werden.

    Darüber hinaus gibt es aber (soviel ich weiß) keine Best Pratices für JavaScript und mein Beispiel sollte vor allem zeigen, dass auch die Funktionalität widersprüchlich sein kann, was noch erheblich schwieriger zu debuggen ist. (In diesem Zusammenhang interessant zu lesen: Javascript Namespace Collisions (and How to Avoid Them) und diese Antwort auf Stackoverflow.)

    Ein Kritikpunkt am neuen Block-Editor bezieht sich auch darauf, dass durch die Nutzung von JavaScript schwer nachvollziehbare Änderungen am DOM (laienhaft ausgedrückt: am HTML-Dokument) vorgenommen werden. Du findest auch öfters HTML-Elemente, denen nachträglich (z.B. bei einer Animation) „wie aus dem Nichts“ mit JavaScript eigene Inline-CSS-Regeln zugewiesen werden, die du in keinem Stylesheet findest. Die Gestaltung eines Elements anzupassen, bei dem du zuerst nicht verstehst, woher die vorhandenen CSS-Regeln stammen, kann kniffelig werden.

    „Fehler„: 2 Scripts vertragen sich nicht, wegen [beliebige Ursache einsetzen], sind aber für sich allein fehlerfrei.

    Das ist tatsächlich ein Problem und der Entwickler des einen Plugins kommt auch nicht so einfach auf die Idee, dass sein Plugin mit dem Code eines anderen Plugins kollidiert. In meinem Fall habe ich das erst durch Support-Anfragen gelernt.

    Moderator Hans-Gerd Gerhards

    (@hage)

    Hallo @pezi
    bei einem Plugin von mir, das im WordPress Repository gelistet ist, habe ich als Präfix für die Funktionen die Anfangsbuchstaben des Pluginnamen („ait_“) genutzt. Damit bin ich dann relativ sicher und kann so gut wie sicher ausschließen, dass es da Konflikte gibt.
    Bei mir war es ähnlich wie bei Bego. Ich wollte mal sehen, wie aufwendig es ist, wenn man ein Plugin im Repository positionieren möchte. Und in der Tat: Es war aufwendig.
    Nur zur Info: Das Plugin ist ein Addon für The Events Calendar, das mir sehr viel Zeit hinsichtlich Copyrights erspart.
    Viele Grüße
    Hans-Gerd

    Moderator Bego Mario Garde

    (@pixolin)

    Der wahre Wahnsinn erschließt sich erst, wenn du weißt, wie wenig Leute eigentlich für die Freigabe von Plugins im Plugin-Verzeichnis verantwortlich sind und welchen Anfeindungen sie immer wieder ausgesetzt sind, weil es auch um finanzielle Interessen geht. Das Plugin-Review-Team darf nicht nur Plugins nach diversen Sicherheits-Vorgaben prüfen, sondern muss sich auch damit beschäftigen, ob z.B. ein „Software as a Service“-Plugin noch dem OpenSource-Charakter entspricht (wenn das Plugin nicht viel mehr leistet, als die Anbindung an einen zahlungspfllichtigen Dienst zu gewährleisten). Sonderregeln für Plugins wie WooCommerce und Jetpack eingeschlossen.

    Aber ich schweife ab …

    Thread-Ersteller pezi

    (@pezi)

    @pixolin

    sollten JavaScript-Funktionen deshalb bevorzugt mit wp_enqueue_script() geladen werden.

    Aha. Auch im „Code Snippet“ Plugin?
    Also statt

    add_action( 'wp_head', function () { ?>
    <script>
    /* Schreibe Deinen JavaScript Code hier */

    so:

    add_action( 'wp_enqueue_script', function () { ?>
    ...

    oder ist das zu simple gedacht?

    Die Gestaltung eines Elements anzupassen, bei dem du zuerst nicht verstehst, woher die vorhandenen CSS-Regeln stammen, kann kniffelig werden

    Achso! Daher musste mir in einem Fall, wo ich den Style nirgends fand, der Programmierer mit einem JS Schnippsel aushelfen.
    Danke!

    @hage

    als Präfix für die Funktionen die Anfangsbuchstaben des Pluginnamen („ait_“) genutzt. Damit … ausschließen, dass es da Konflikte gibt.

    Und was ist mit Variablennamen? Sind die sicher, weil die ja ohne ‚global‘ nur innerhalb der eigenen Funktion(en) gelten?

    Jedenfalls interessant, diese Einblicke in die Profiliga, Hersteller usw. Verstehe zwar nicht alles, aber dennoch Danke dafür!

    Moderator Bego Mario Garde

    (@pixolin)

    Ich sehe die Code-Snippets immer als „letzte Anpassung“ und verwenden dann einfach den wp_head-Hook, um JavaScript oder CSS in den Header zu setzen. Der Hook wp_enqueue_script setzt ja auch voraus, dass du eine zusätzliche Datei verlinkst, was sich mit dem Plugin Code Snippets wohl kaum realisieren lässt. 🙂

    Und was ist mit Variablennamen?

    Die sind wegen des Geltungsbereich der Variablen selten ein Problem. Kritischer finde ich, wenn zwei unterschiedliche JavaScript-Funktion das gleiche HTML-Element ansprechen und dabei widersprüchliche Aktionen ausführen.

    Verstehe zwar nicht alles, aber dennoch Danke dafür!

    Das geht mir auch nach einigen Jahren Erfahrung nicht anders. Viel Lesen hilft und die Fragen anderer Benutzer/-innen zu beantworten, hilft die eigene Filterblase zu verlassen. Ab und zu „Ausprobieren“ ist wichtig, weil „nur Lesen“ schnell den Eindruck vermittelt „ich kann und weiß alles“, dann aber in der Praxis an ganz banalen Dingen scheitert, die man vorher übersehen hat.

Ansicht von 7 Antworten - 1 bis 7 (von insgesamt 7)