WP-Scripts mit pnpm Workspace nutzen

Introduction

WP-Scripts ist perfekt, um die Entwicklungsumgebung für die Arbeit an einzelnen Plugins und Themes zu vereinfachen und zu vereinheitlichen. Aber wie arbeite ich innerhalb eines WordPress-Projektes sinnvoll an mehreren Plugins und Themes parallel?

Mein Umstieg auf WP-Scripts

Mit @wordpress/scripts soll es alten PHP-Entwickler-Hasen, die bisher mit Node JS und Konsorten nichts am Hut hatten, leichter gemacht werden. Doch auch alle Anderen profitieren.

The idea boils down to moving all the necessary configurations and scripts to one single tool dependency.

WordPress Dokumentation

Bisher hatte ich ein Gulp-Task im Projektordner laufen, der alle meine Stylesheets und Scripte verarbeitet hat. Außerdem hatte ich dort eine Reihe an Konfigurationsdateien für Prettier, Eslint usw.

Meine eigenen Tools zu pflegen, wurde jedoch immer aufwendiger und WP-Scripts immer besser. Als ich dann vor der Aufgabe stand, das dependency-extraction-webpack-plugin für meinen gulp-esbuild-Workflow nachzubauen, habe ich kapituliert.

Nun möchte ich auf WP-Scripts umsteigen. Ich erhoffe mir davon in Zukunft weniger Zeit mit der Optimierung meiner Entwicklerumgebung und mehr Zeit mit der Entwicklung der Webseiten verbringen zu können.

Das Problem

Bei dem Umstieg bin ich auf ein Problem gestoßen. WP-Scripts ist so aufgebaut, dass alle Dateien von genau einem Source- in genau einen Dist-Ordner transpiliert werden. Ich habe jedoch in jedem Plugin und jedem Theme einen eigenen Source- und Dist-Ordner.

Lange hab ich herumgerätselt, was der beste Weg ist, an allen Dateien in meinem Projekt parallel zu arbeiten, ohne in jedem Plugin und jedem Theme manuell ein eigenes WP-Scripts zu starten.

Die Lösung lautet Workspace

Sowohl npm als auch yarn und pnpm bieten Workspacelösungen an. Diese werden vor allem in Monorepos genutzt. Das Ziel ist, mehrere Pakete parallel aus einem Projektordner heraus zu bearbeiten.

Warum pnpm und nicht npm?

Nachdem ich jahrelang npm genutzt hatte, war irgendwann meine Festplatte voll. Und wer macOS nutzt, weiß, dass Apple sich zusätzlichen Speicherplatz in Gold aufwiegen lässt. pnpm verwaltet die Dependencies auf deinem System zentral und bindet sie in dem jeweiligen Projekt nur als symbolische Links ein. So hast du nicht alle Pakete doppelt und dreifach auf deinem Rechner. Ansonsten funktioniert es nahezu identisch zu npm.

Durch einen pnpm-Workspace schlage ich gleich mehrere Fliegen mit einer Klappe:

  1. Ich kann den start und build command rekursiv von meinem Projektordner aus in allen nötigen Plugins und Themes ausführen
  2. Bei den Pfadangaben in der webpack.config.js muss ich mich nicht verrenken und nicht immer bedenken, dass das Script gerade im Projektordner läuft.
  3. Das einzelne Plugin oder Theme bleibt unabhängig. Man könnte WP-Scripts auch direkt in ihm ausführen.
  4. Jedes Paket (Plugin oder Theme) hat seine eigenen node_modules, aber diese doppeln sich nicht, sondern werden zentral verwaltet.

So wird’s gemacht

In deinem Projektordner erstellst du eine package.json Datei (pnpm init).

Installiere WP-Scripts als Dev-Dependency:
pnpm add @wordpress/scripts --save-dev

Außerdem erstellst du in deinem Projektordner eine pnpm-workspace.yaml Datei. In dieser legst du fest, welche Ordner als Paket deines Workspace behandelt werden sollen. In diesem Beispiel wäre das z.B. ein Theme namens „origenes“ und alle Plugins, die mit dem Präfix „origenes-“ anfangen.

packages:
  - 'wp-content/themes/origenes'
  - 'wp-content/plugins/origenes-*'Code-Sprache: YAML (yaml)

In jedem Ordner deines Projektes erstellst du eine eigene package.json und falls benötigt eine webpack.json. So, als würde jedes Paket für sich stehen. So sieht z.B. mein Theme aktuell aus:

In der package.json in meinem Projektordner habe ich diese beiden Skripte:

    "start": "pnpm -r start",
    "build": "pnpm -r build"Code-Sprache: JSON / JSON mit Kommentaren (json)

Das -r steht für „recursive“ und bedeutet, dass alle npm-Tasks in allen Paketen mit diesem Namen ausgeführt werden. Auf diese Weise kann ich mit pnpm start alle start-Tasks parallel ausführen.

Zuletzt erstellst du die nötigen Konfigurationsdateien in deinem Projektordner und erweiterst sie einfach nur mit dem jeweiligen Preset, welche durch WP-Scripts bereits in deinem Projekt installiert ist.

.eslintrc

{
	"extends": ["plugin:@wordpress/eslint-plugin/recommended"],
	"rules": {
		// Erlaube experimentelle imports
		"@wordpress/no-unsafe-wp-apis": "off"
	}
}Code-Sprache: JSON / JSON mit Kommentaren (json)

..prettierrc

"@wordpress/prettier-config"Code-Sprache: JSON / JSON mit Kommentaren (json)

.stylelintrc

"@wordpress/stylelint-config"Code-Sprache: JSON / JSON mit Kommentaren (json)

Fertig.

Perfektes Beispiel

Erst als ich alles fertig hatte, habe ich gesehen, dass das block-development-examples-Repo genau so aufgebaut ist.