使用 WordPress Playground 和 WebAssembly 建構瀏覽器中的 WordPress 體驗

由 PHP 提供支援的完整 WordPress,僅在使用 WebAssembly 的瀏覽器中執行

Adam Zieliński
Adam Zieliński
Thomas Nattestad
Thomas Nattestad

第一次看到 WordPress Playground 時,它看起來就像是個普通的網站,除了色彩繽紛的背景。這完全不是事實。您實際上看到的是整個 WordPress 技術堆疊,包括直接在瀏覽器中執行的 PHP 和資料庫。

在本篇文章中,Adam Zieliński (WordPress Playground 的主管) 和 Thomas Nattestad (V8 產品經理) 將探討以下主題:

  • WordPress Playground 如何協助 WordPress 開發人員。
  • 運作原理。
  • 這對 WordPress 的未來有何影響。

在不安裝 WordPress 的情況下使用,並將其嵌入應用程式,甚至透過 JavaScript 控制 WordPress

您可以免費使用並自訂 playground.wordpress.net 中的 WordPress 嵌入功能。您不需要支付任何雲端基礎架構和支援費用,因為該網站完全位於您的瀏覽器中,其他人無法造訪。這也是暫時性的。只要您重新整理網頁,就會消失。您可以建立任意數量的這些網站,用於製作原型、試用外掛程式,以及快速探索構想。

您甚至可以使用內建的 PHP 和 WordPress 版本切換器,在不同環境中測試程式碼:

phpinfo 頁面。

WordPress Playground 是使用 WordPress 的全新方式。不過,只有在應用程式中加入這個功能,才能發揮其完整效能。簡單的方法是將 WordPress Playground 嵌入 <iframe>,然後使用查詢參數 API進行設定。這就是官方展示內容的用途。舉例來說,如果您選取 Pendant 主題Coblocks 外掛程式,嵌入的 iframe 就會更新為指向 https://playground.wordpress.net/?theme=pendant&plugin=coblocks

WordPress Playground 展示區。

iframe 是開始使用的方法,但也僅限於基本設定選項。如果您需要更多功能,我們還有其他更強大的 API。

WordPress Playground JavaScript 用戶端可讓您全面掌控嵌入的網站

您可以使用透過 @wp-playground/client npm 套件提供的完整 API,控制整個 WordPress 網站 (包括檔案系統和 PHP)。下列範例說明如何使用此功能。如需更多範例,請參閱互動式教學課程

import {
  connectPlayground,
  login,
  connectPlayground,
} from '@wp-playground/client';

const client = await connectPlayground(
  document.getElementById('wp'), // An iframe
  { loadRemote: 'https://playground.wordpress.net/remote.html' },
);
await client.isReady();

// Login the user as admin and go to the post editor:
await login(client, 'admin', 'password');
await client.goTo('/wp-admin/post-new.php');

// Run arbitrary PHP code:
await client.run({ code: '<?php echo "Hi!"; ?>' });

// Install a plugin:
const plugin = await fetchZipFile();
await installPlugin(client, plugin);

即使沒有 WordPress 也能使用 WebAssembly PHP

WordPress Playground 並非單一服務,WebAssembly PHP 是獨立於 WordPress 發布的,因此您也可以單獨使用。針對網頁,您可以使用 @php-wasm/web npm 套件,該套件經過最佳化處理,可產生較小的套件大小;在 Node.js 中,您可以使用 @php-wasm/node,該套件提供更多 PHP 擴充功能。Adam 使用前者,在這個 WP_HTML_Tag_Processor 教學課程中加入互動式 PHP 程式碼片段。以下是使用方式的預覽畫面:

import { PHP } from '@php-wasm/web';
const php = await PHP.load('8.0', {
  requestHandler: {
    documentRoot: '/www',
  },
});

// Create and run a script directly
php.mkdirTree('/www');
php.writeFile('/www/index.php', `<?php echo "Hello " . $_POST['name']; ?>`);
php.run({ scriptPath: '/www/index.php' });

// Or use the familiar HTTP concepts:
const response = php.request({
  method: 'POST',
  relativeUrl: '/index.php',
  data: { name: 'John' },
});
console.log(response.text); // Hello John

此時您一定會想:這怎麼可能?好問題!讓我們深入瞭解內部運作方式,請繫好安全帶!

在幕後,WebAssembly PHP、SQL 轉譯器和瀏覽器內伺服器

PHP 以 WebAssembly 二進位檔執行

PHP 不只適用於瀏覽器。WordPress Playground 開發了專用管道,使用 EmscriptenPHP 解譯器建構為 WebAssembly。建構原始 PHP 並非太過複雜,只需要調整此處的函式簽名強制執行設定變數,以及套用一些小修補程式。您可以自行建構這個項目,步驟如下:

git clone https://github.com/WordPress/wordpress-playground
cd wordpress-playground && npm install
# Below, you can replace "8.2" with any other valid PHP version number.
npm run recompile:php:web:8.2

不過,純 PHP 版本在瀏覽器中並不實用。作為伺服器軟體,PHP 沒有 JavaScript API 可傳送要求主體、上傳檔案或填入 php://stdin 串流。WordPress Playground 必須從頭開始建立一個。WebAssembly 二進位檔隨附以 C 編寫的專屬 PHP API 模組,以及公開 writeFile()run() 等方法的 JavaScript PHP 類別

由於每個 PHP 版本都只是一個靜態 .wasm 檔案,因此 PHP 版本切換器其實相當無聊。它只是告訴瀏覽器下載 php_7_3.wasm,而非 php_8_2.wasm

資料庫支援 SQL 轉譯層

WordPress 需要 MySQL。不過,您無法在瀏覽器中執行 WebAssembly 版本的 MySQL。因此,WordPress Playground 會將 PHP 與原生 SQLite 驅動程式一起提供,並仰賴 SQLite。

但 WordPress 如何在其他資料庫上執行?

在幕後,官方 SQLite 資料庫整合 外掛程式會攔截所有 MySQL 查詢,並以 SQLite 方言重新撰寫。2.0 版提供新的 WordPress Playground 資訊轉譯層,可讓 SQLite 上的 WordPress 通過 99% 的 WordPress 單元測試套件。

網路伺服器位於瀏覽器內

在一般 WordPress 中,點選「Blog」等連結時,系統會向遠端後端發出 HTTP 要求,以擷取 blog 頁面。不過,WordPress Playground 沒有遠端後端。它具有一個Service Worker,可攔截所有傳出的要求,並將這些要求傳遞至在個別 Web Worker 中執行的瀏覽器內 PHP 例項。

流程圖從指向 wp-admin 資源的 iframe 開始,服務工作者會攔截對該資源的呼叫,在 worker 執行緒中算繪,並最終由瀏覽器內伺服器轉譯為 WordPress 回應。

網路功能可透過 WebSocket 支援

在網路連線方面,WebAssembly 程式只能呼叫 JavaScript API。這項功能雖然是安全防護機制,但也帶來了挑戰。如何使用 JavaScript 中的高階非同步 API,支援 PHP 使用的低階同步網路程式碼?

以 WordPress Playground 為例,答案包括 WebSocket 到 TCP 通訊端 Proxy、Asyncify,以及修補 php_select 等深層 PHP 內部元件。這項工作雖然複雜,但有回報。以 Node.js 為目標的 PHP 版本可以要求網路 API、安裝 Composer 套件,甚至連線至 MySQL 伺服器。

WordPress 的使用範圍比瀏覽器更廣泛

由於 WordPress 現在可在 WebAssembly 上執行,您也可以在 Node.js 伺服器中執行 WordPress,因為它使用的是相同的 V8 引擎!當然,您也可以透過 StackBlitz 直接在瀏覽器中執行 Node.js,也就是說,您可以執行編譯為 WebAssembly 的 WordPress 和 PHP,並在 Node.js 中執行,而 Node.js 也已編譯為在瀏覽器中執行的 WebAssembly。WebAssembly 在無伺服器領域的使用率也大幅成長,未來也可能會在該基礎架構上執行。

未來可能會推出無須設定、互動式和協作式 WordPress 應用程式

想像一下,您可以直接進入程式碼編輯器,在完成所有設定後,立即開始建構。您甚至可以分享簡單的連結,並開始多人編輯工作階段,例如在 Google 文件中。完成後,只需按一下滑鼠,即可將創作內容無縫部署至各種代管服務,而且完全不需要在本機安裝任何內容!

以上只是其中一部分!我們可能會看到互動式教學課程、外掛程式實機操作示範、測試網站、邊緣伺服器上的去中心化 WordPress,甚至是手機上的外掛程式建構。

未來充滿無限可能,歡迎加入我們的行列!您的想法和貢獻是 WordPress Playground 的養分,請前往 GitHub 存放區,在 #meta-playground WordPress.org Slack 頻道中打招呼,並隨時透過 adam@adamziel.com 與 Adam 聯絡。