Kategorien
Projekte Webentwicklung

Astro, Netlify und falsche Annahmen

Gestern habe ich endlich herausgefunden, warum Netlify in meinem Preview-Build keine Bilder in bestimmten Seiten anzeigt. In meinem Fall war das eine Gallery, die einen Ordner übergeben bekommt.

Danach habe ich alle Bilder, die in Astro gefunden werden über diesen Filter gejagt. Lokal und im statischen Build war alles wunderbar.

Erster Gedanke war, dass bei Netlify die Bilder-Ausgabe einen Timeout hat, da ich am Anfang noch recht große Bilder verwendet habe. Allerdings hat der Resize der Bilder nichts bewirkt. Das war’s dann nicht.

Dann war die nächste Vermutung es läge an der fehlenden Netlify Integration, aber die ist für den static Build völlig unerheblich, wichtig ist die hauptsächlich für den Betrieb einer SSR Anwendung. Das Image-CDN und die Bearbeitung der Bilder ist davon (im static Build) nicht betroffen.

Am Ende habe ich in meiner Verzweiflung angefangen, in der Anwendung an verschiedenen Stellen zu debuggen, unter anderem an dem Mechanismus, mit dem ich die Bilder zusammensuche. Tatsächlich war das nur als Übergang gedacht, da ich damit ja den Bildern auch keine alt-Texte und Co. übergeben konnte, aber die Galeriemodule funktional schon mal testen konnte.

Spannenderweise hat die obige Debug-Ausgabe lokal das erwartete Ergebnis gezeigt.

Im Netlify-Build-Log war allerdings trotz gefundenen Images das filteredImages-Log leer, bzw. ein leeres Array:

Und wie man sieht: Netlify findet Bilder scheinbar nur – in schon bearbeiteter Form – in dem _astro-Ordner, wenn die Components gebaut werden. Blöd, aber genau der Grund, warum der Filter nicht funktioniert und damit keine Bilder zurückgegeben werden. Leider unterscheided sich das von der Lokalen Bauweise, wo die Bilder noch in den korrekten Ordnern liegen.

Verlinkt man die Bilder normal, z.B. aus der Content-Collection, dann geht natürlich alles korrekt und auch der Preview Build bei Netlify funktioniert korrekt. Jetzt sogar schon mit Alt-Texten, zumindest bei den Contents, in denen ich das ganze schon gepflegt habe. Wird der nächste Schritt mit SEO-und Accessibility-Screening halt schon etwas schneller möglich.

Kategorien
Allgemein Webentwicklung Werkzeuge

Webdriver und das Problem mit dem unsichtbaren Text.

Neulich stand ich vor einem Problem, in dem ich mittels PHP-Webdriver versuchte, portentiell versteckten Inhalt aus einer Seite auszulesen.

Leider ist es so, dass das ganze nicht funktioniert, wenn der Inhalt versteckt ist. Dann wird zwar das Element gefunden, wenn man $element->getText() nutzt, wird aber null bzw ein leerer String ausgegeben. Das ist natürlich unschön und Webdriver selbst hat auch keine Möglichkeit, das DOM selbst zu verändern.

Aber natürlich gibt es einen Weg, dafür zu sorgen, dass man die Inhalte auslesen kann, immerhin muss das Element einfach nur sichtbar sein. Aber was, wenn das Element selbst nicht unsichtbar ist, sondern ein Eltern-Element das verursacht?

Hier die mögliche Lösung

PHP-Webdriver hat die Möglichkeit, einen Javascript-Codeblock an den Browser zu senden (analog zu browser.execute), der zweite Parameter von executeScript wird als arguments[] an die JS-Funktion übergeben. Damit bekommen wir das zu untersuchende Element.

In einer While-Schleife geht es dann (wenn ein Element nicht sichtbar ist) Element für Element nach oben. Dabei bekommt jedes einzelne Element ein display: block !important gesetzt.

Sobald ein überordnetes Element sichtbar ist, sind wir fertig. Eine while-Schleife stellt hier eine einfache Möglichkeit dar, den DOM-Tree rekursiv hochzuwandern.

Es besteht dabei auch die Möglichkeit, ein Element aus diesem Codeblock, der in eine Lambda-Funktion (auch “anonyme Funktion”) gepackt wird, zurückzugeben und das Element in PHP weiterzuverarbeiten. Allerdings müsste das Element dann zwischen den beiden Umgebungen ständig das Element für meine Schleifen hin- und hergereicht werden, das ist vermutlich weniger performant, als das einmal am Stück durchzugehen und das komplett in Javascript durchzuziehen, ohne vorher zurückzuspringen.

    /**
     * @param Client $client
     * @param RemoteWebElement $element
     * @throws \Exception
     */
    private function makeElementTreeVisible($client, $element): void
    {
        if (!$element->isDisplayed()) {
            $response = $client->executeScript('
                var element = arguments[0];

                function isVisible(elem){
                    return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length )
                    && window.getComputedStyle(elem).visibility !== "hidden";
                }

                while (!isVisible(element) ) {
                    element.setAttribute("style", "display: block !important")
                    element = element.parentNode;
                }
            ', [$element]);
        }
    }

Vermutlich nicht die super-perfomanteste Weise, aber zumindest sollten damit alle Edge Cases abgebildet sein.

Andere Möglichkeiten wären noch: den Style für alle Elemente setzen oder versuchen alle CSS-Styles zu entfernen (hilft halt nicht gegen Inline-Styles).

Habt ihr dieses Problem schon einmal gehabt? Wie habt ihr das gelöst?

Kategorien
Webentwicklung Werkzeuge

“To fix this issue you can simply rename your file to api2.php”

Ich bin ja auch Nutzer von InfiniteWP. Das ist eigentlich ein sehr gutes Tool zum Verwalten von mehreren WordPress-Instanzen.

Nun hatte ich in einem Kundenprojekt eine API entwickelt, die zur Authentifizierung ein WordPress mit einer Nutzerdatenbank verwendet. Dazu habe ich von einem externen Projekt die wp-load.php inkludiert. Das funktionierte auch eine zeitlang auch sehr gut, bis die Agentur, die die Seite betreut, ein paar Änderungen vornahm. Sie installierten unter anderem InfiniteWP. In der datei “api.php” von InfiniteWP ist folgender Code:

if(basename($_SERVER['SCRIPT_FILENAME']) == "api.php"):
    exit;
endif;

Das Ziel dieses Codes ist relativ offensichtlich: Die Datei sollte nicht direkt geladen werden können. Blöd ist: Es wird nur auf den Dateinamen geprüft. Da meine externe Datei, auch api.php heisst, wird aber, sobald ich die wp-load.php include, das exit; ausgeführt.

Ich regte also an, vielleicht nicht nur den Filename zu überprüfen, sondern vielleicht auch den Pfad des aufgerufenen Scripts oder – wie unter WP auch nicht unüblich – auf eine gesetzte Konstante. Auf meine Anfrage beim Support bekam ich folgende Antwort:

Thanks for taking the time to reach out to us on your query. Your patience is greatly appreciated.

We are using api.php in our client plugin to use call back functions for our addons.
To fix this issue you can simply rename your file to api2.php

Are you experiencing any conflict issues with IWP client plugin and other plugins?
Please give us more information so that I can assist you accordingly.

Ich habe dann etwas möglicherweise etwas unhöflich reagiert und gefragt, wie sich das verhält, wenn der nächste dann das gleiche mit proxy.php und jemand anderes dann die index.php seines Plugins so schützt. Und dass ein HTTP Status 200 und eine weiße Seite in dem Fall auch nicht sinnvoll debugbar sind und dass mich das einige Tage Projektverzögerung gekostet hat und ziemlich beschissen ist. Zumal es in WordPress ja auch Beispiele gibt, wie es besser geht.

Erst darauf hin habe ich die Antwort bekommen, dass ein “scope of improvement on our end” vorhanden sei. Da geben sich dann Codequalität und Servicequalität dann echt nichts.

Ich habe mal ein Beispiel geschickt, wie man das sinnvoller lösen kann. Mal sehen, wann ein Update dafür kommt.

Kategorien
Changelog Releases Webentwicklung Werkzeuge

Statischer Seitengenerator: Hugo

Ich bin ja Fan von Hugo, und versuche, viele Probleme mit einem Statischen Tool zu erschlagen, wenn es denn geht.

Im Fall von Hugo sind das in den letzten Versionen ein paar mehr Dinge mehr geworden, die man damit lösen kann.

  1. Multi-Language. Eine ziemlich durchdachte Geschichte, die man da gebaut hat.
  2. Neue Struktur. Alles ist eine Seite. Damit lassen sich auch Index-Seiten als ganz normale Seiten behandeln
  3. Neue Template-Möglichkeiten: block templates

Diese letzten beiden Releases haben gezeigt, dass Hugo einen deutlichen Innovationsvorsprung gegenüber Jekyll und teilweise sogar WordPress hat. Im Forum von Hugo findet man sehr viele hilfsbereite User und Entwickler, die teilweise auch mal eigene Ideen vorstellen, die man super adaptieren kann.

Beispiel gefällig? Das Tutorial mit dem “Simple JSON site index” eignet sich auch hervorragend als Grundlage für das erstellen einer JSON-API für Apps oder ähnliches.

Kategorien
Changelog Releases Webentwicklung Werkzeuge

pimcore 4.4.x

Ich hatte ja schon vor einer Weile mal Artikel zum Thema pimcore veröffentlicht. Damals habe ich, ganz besonders unter “Was ist pimcore und wofür brauche ich das?” an einigen Stellen kein gutes Haar gelassen.

Die Erfahrungen, die ich mit den frühen Versionen von pimcore gesammelt habe, was das Thema Anpassung des Datenmodells bei einer Weiterentwicklung eines Projekts in verschiedenen Entwicklungsstufen angeht, habe ich damals stark kritisiert.

Innerhalb dieser 1,5 Jahre seit Erscheinen des Artikels hat sich einiges verändert, eigentlich ziemlich konstant zum Guten hin.

Unter diesen Umständen habe ich pimcore neu evaluiert und bin zu dem Entschluss gekommen, dass das ganze durchaus eine neue Chance verdient hat und sicher bei dem einen oder anderen Projekt in Zukunft zum Einsatz kommen wird.