Einleitung
Aktuell arbeite ich an einer Overlay Suche mit Live-Ergebnissen. Obwohl es von WordPress ein Paket für den Request auf einen REST-Endpoint gibt – @wordpress/api-fetch – ließ sich dieses nicht so einfach in dem Script-Modul meines Blocks zu nutzen. Hier kommt die Lösung.

Warum überhaupt Script Module?
Das Script-Module-System wurde eingeführt, um die bisherige Einbindung von JavaScript in WordPress langfristig zu modernisieren. Statt globale Objekte wie wp.*
zu nutzen oder Abhängigkeiten manuell über Handles zu steuern, können ES-Modulen dynamisch geladen werden. Das bringt Klarheit und weniger Redundanz. Wenn mehrere Module dasselbe Modul benötigen, wird es dennoch nur einmal geladen und nicht mit jedem der Skripte gebündelt. Die Interactivity API war der erste Teil von WordPress, der auf dieser neuen Technik basiert.
Was nicht funktioniert
Ich dachte ES-Modules, das kenne ich: import
, export
– kein Problem.
// view.js
import { store, getContext } from "@wordpress/interactivity";
import apiFetch from '@wordpress/api-fetch';
import { addQueryArgs } from '@wordpress/url';
const { actions } = store("live-search-overlay/container", {
// ...
actions: {
* fetchLiveSearchResults(searchTerm) {
// ...
const data = yield apiFetch({
path: addQueryArgs("/wp-json/live-search-overlay/v1/search", {
q: searchTerm
}),
method: "GET",
})
.then((response) => {
return response.json();
});
// ...
}
}
});
Code-Sprache: JavaScript (javascript)
Tja. Wäre wohl auch zu leicht.
Das Problem ist, dass die meisten @wordpress/...
-Pakete nicht als modul geladen werden sondern als normales Skript. So auch @wordpress/api-fetch
. Deswegen können diese bisher auch nicht in einem Script Module – wie etwas in mein view.js
, das ich in meiner block.json
unter viewScriptModule
geladen haben – importiert werden.
Nagut, wenn ich das hier so als Blogartikel schreibe macht es auf einmal irgendwie Sinn 👀.
Auch eine Abhängigkeit über ein dependecy Array herzustellen scheint nicht möglich zu sein: „Script modules cannot depend on existing scripts such as wp-url, wp-i18n, or wp-api-fetch„. Das hier sollte also nicht funktionieren:
// block.json
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
// ...
"viewScriptModule": [
"file:./view.js",
"@wordpress/url",
"@wordpress/api-fetch"
]
}
Code-Sprache: JSON / JSON mit Kommentaren (json)
Der aktuelle Workaround
Eine Lösung habe ich bei dem Seth Rubenstein gefunden. Seth arbeitet als In-House-Entwickler bzw. Team Lead für das Pew Research Center und baut da quasi alles mit Gutenberg Blöcken. Auf Github findet man die Block-Sammlung, die sie sich dort aufgebaut haben. Eine Goldgrube für „Wie machen das eigentlich andere“-Fragestellungen.
Der Workaround besteht nun darin, die benötigen Scripts im render.php
bzw. im render_callback
anzufordern.
So z.B. hier im Mailchimp Block des Pew Research Centers:
-> https://github.com/pewresearch/prc-block-library/blob/develop/blocks/mailchimp-form/src/render.php#L5-L6
// render.php
//@benwormald see example of how to manually include @wordpress packages in a module for now... this will be automatic once the modules system is complete and wordpress/scripts is updated accordingly.
wp_enqueue_script('wp-api-fetch');
wp_enqueue_script('wp-url');
Code-Sprache: PHP (php)
Im Script-Modul greift man dann auf das wp
-Object des window
zu:
// view.js
import { store, getContext } from "@wordpress/interactivity";
const { actions } = store("live-search-overlay/container", {
// ...
actions: {
* fetchLiveSearchResults(searchTerm) {
// ...
const data = yield wp.apiFetch({
path: wp.url.addQueryArgs("/wp-json/live-search-overlay/v1/search", {
q: searchTerm
}),
method: "GET",
})
.then((response) => {
return response.json();
});
// ...
}
}
});
Code-Sprache: JavaScript (javascript)
(Der Fetch hier ist stark vereinfacht. Es fehlen AbortController, Vanilla fetch
-Fallback und anderer Schnick-Schnack. Mir ging es hier erst mal nur um den Workaround für apiFetch
.)
Wirkt ein bisschen „hacky“, ist aber tatsächlich auch der Weg den Jon Surrell in seinem Artikel zu WP 6.5 unter der Überschrift Limitations empfiehlt: https://make.wordpress.org/core/2024/03/04/script-modules-in-6-5/
Warum nicht einfach die Vanilla JS fetch
-Funktion nutzen?
Das hatte ich auch erst gemacht. Aber dann wollte ich an meinem REST Endpoint wissen ob der Nutzer eingeloggt ist – um z.B. interne Suchergebnisse auszugeben. Mit apiFetch
muss ich mich nicht um nonce
usw. kümmern, sondern der macht das alles für mich.
Was bringt die Zukunft
Wenn ich mir das richtig zusammengereimt hat, sollen künftig alle WordPress Pakete als echte ES-Module nutzbar sein. Ich habe aber keine aktuellen Informationen zu dem Thema gefunden. Für WP 6.9 ändert sich, glaube ich, erst mal noch nichts.
Links
-> https://make.wordpress.org/core/2024/03/04/script-modules-in-6-5/
-> https://make.wordpress.org/core/2024/10/14/updates-to-script-modules-in-6-7/