使用 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、將 WordPress 嵌入您的應用程式,甚至使用 JavaScript 控制 WordPress

您可以在 playground.wordpress.net 免費使用及自訂內嵌的 WordPress。我們不提供雲端基礎架構和支援服務,因為該網站完全以瀏覽器運作,任何人都無法造訪。。只要重新整理頁面,這個頁面就會消失。您可以視需求建立這些網站 (數量不限),以便進行原型設計、試用外掛程式,以及快速探索各種想法。

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

「phpinfo」頁面。

WordPress Playground 是全新的 WordPress 使用方法。不過,只有將 WordPress Playground 包含在應用程式內才能完全解鎖。簡單的做法是將 WordPress Playground 嵌入 <iframe>,並使用查詢參數 API 進行設定。這就是官方展示的用途。舉例來說,選取「吊人主題」和「Coblocks 外掛程式」等選項後,嵌入的 iframe 會更新為指向 https://playground.wordpress.net/?theme=pendant&plugin=coblocks

WordPress Playground 展示區。

iframe 是入門的簡便方法,但此 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 曾利用前者將互動式 PHP 程式碼片段新增至這個 WP_HTML_Tag_Processor 教學課程。以下簡單介紹如何使用這項工具:

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 開發了專用管道,使用 Emscripten 建構 PHP 解譯器至 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

但 Cookie 版本在瀏覽器上不太實用。做為伺服器軟體,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 會透過原生 SQLite 驅動程式提供 PHP,並且依賴 SQLite。

但 WordPress 如何在不同的資料庫中運作?

官方 SQLite Database Integration 外掛程式會在背景攔截所有 MySQL 查詢,並以 SQLite 方言重新編寫。2.0 版提供新的 WordPress Playground 相關資訊翻譯層,讓 SQLite 上的 WordPress 能夠通過 99% 的 WordPress 單元測試套件。

網路伺服器就在瀏覽器內

在一般 WordPress 中點選連結 Blog 後,系統會向遠端後端發出 HTTP 要求,以擷取 blog 頁面。但是 WordPress Playground 沒有遠端後端。它的服務工作處理程序會攔截所有傳出要求,並將這些要求傳送到在另一個 Web Worker 上執行的瀏覽器內 PHP 執行個體。

流程圖的開頭是指向資源 wp-admin 的 iframe,並由服務 Worker 攔截該呼叫,再由服務工作處理程序攔截,最後再由瀏覽器內伺服器轉譯為 WordPress 回應。

支援透過 WebSocket 使用網路

在網路方面,WebAssembly 程式只能呼叫 JavaScript API。這是安全功能,但也帶來挑戰。如何支援 PHP 使用的低階同步網路程式碼,與 JavaScript 提供的高階非同步 API 搭配使用?

針對 WordPress Playground,答案涉及到 TCP 通訊端 Proxy、Asyncify 以及修補 PHP 內部 (例如 php_select)。這很複雜,但值得你獲得獎勵。指定 Node.js 的 PHP 版本可以要求網路 API、安裝 Composer 套件,甚至連線至 MySQL 伺服器。

WordPress 的功能比瀏覽器更多

由於 WordPress 現在可在 WebAssembly 上執行,您也可以在 Node.js 伺服器中執行 WordPress,也是相同的 V8 引擎!當然,使用 StackBlitz 也可以直接在瀏覽器中執行 Node.js。也就是說,您可以執行編譯為 WebAssembly 的 WordPress 和 PHP,在 Node.js 中執行 (後者也會在瀏覽器中執行編譯為 WebAssembly)。WebAssembly 也在無伺服器空間中人氣竄升,日後也能在該基礎架構上執行。

未來可能會提供零設定、互動和協作的 WordPress 應用程式

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

而這只是個小小事!我們可以是互動式教學課程、即時外掛程式示範、測試網站、在邊緣伺服器上去中心化 WordPress,甚至是在手機上建構外掛程式。

展望未來,相信您也會成為計畫的一分子!各位的想法和貢獻 是 WordPress Playground 的核心價值請造訪 GitHub 存放區,前往 #meta-playground WordPress.org Slack 頻道,歡迎透過 adam@adamziel.com 與 Adam 聯絡。