diff --git a/packages/playground/remote/src/lib/boot-playground-remote.ts b/packages/playground/remote/src/lib/boot-playground-remote.ts index d75a3162e4..96f3f6f8c6 100644 --- a/packages/playground/remote/src/lib/boot-playground-remote.ts +++ b/packages/playground/remote/src/lib/boot-playground-remote.ts @@ -197,6 +197,13 @@ export async function bootPlaygroundRemote() { ) { return await workerApi.bindOpfs(options, onProgress); }, + + /** + * Download WordPress assets. + */ + async backfillStaticFilesRemovedFromMinifiedBuild() { + await workerApi.backfillStaticFilesRemovedFromMinifiedBuild(); + }, }; await workerApi.isConnected(); @@ -232,6 +239,9 @@ export async function bootPlaygroundRemote() { throw e; } + wpFrame.addEventListener('load', () => { + webApi.backfillStaticFilesRemovedFromMinifiedBuild(); + }); /* * An assertion to make sure Playground Client is compatible * with Remote diff --git a/packages/playground/remote/src/lib/playground-client.ts b/packages/playground/remote/src/lib/playground-client.ts index eeb23f1bf1..dede3f2eca 100644 --- a/packages/playground/remote/src/lib/playground-client.ts +++ b/packages/playground/remote/src/lib/playground-client.ts @@ -52,6 +52,7 @@ export interface WebClientMixin extends ProgressReceiver { replayFSJournal: PlaygroundWorkerEndpoint['replayFSJournal']; addEventListener: PlaygroundWorkerEndpoint['addEventListener']; removeEventListener: PlaygroundWorkerEndpoint['removeEventListener']; + backfillStaticFilesRemovedFromMinifiedBuild: PlaygroundWorkerEndpoint['backfillStaticFilesRemovedFromMinifiedBuild']; /** @inheritDoc @php-wasm/universal!UniversalPHP.onMessage */ onMessage: PlaygroundWorkerEndpoint['onMessage']; diff --git a/packages/playground/remote/src/lib/worker-thread.ts b/packages/playground/remote/src/lib/worker-thread.ts index 4c0a9b5b93..5da9ea0904 100644 --- a/packages/playground/remote/src/lib/worker-thread.ts +++ b/packages/playground/remote/src/lib/worker-thread.ts @@ -35,13 +35,14 @@ import transportFetch from './playground-mu-plugin/playground-includes/wp_http_f import transportDummy from './playground-mu-plugin/playground-includes/wp_http_dummy.php?raw'; /** @ts-ignore */ import playgroundWebMuPlugin from './playground-mu-plugin/0-playground.php?raw'; -import { PHPWorker } from '@php-wasm/universal'; +import { PHP, PHPWorker } from '@php-wasm/universal'; import { bootWordPress, getLoadedWordPressVersion, } from '@wp-playground/wordpress'; import { wpVersionToStaticAssetsDirectory } from '@wp-playground/wordpress-builds'; import { logger } from '@php-wasm/logger'; +import { unzipFile } from '@wp-playground/common'; const scope = Math.random().toFixed(16); @@ -186,6 +187,67 @@ export class PlaygroundWorkerEndpoint extends PHPWorker { async replayFSJournal(events: FilesystemOperation[]) { return replayFSJournal(this.__internal_getPHP()!, events); } + + async backfillStaticFilesRemovedFromMinifiedBuild() { + await backfillStaticFilesRemovedFromMinifiedBuild( + this.__internal_getPHP()! + ); + } +} + +async function backfillStaticFilesRemovedFromMinifiedBuild(php: PHP) { + if (!php.requestHandler) { + logger.warn('No PHP request handler available'); + return; + } + + try { + const remoteAssetListPath = joinPaths( + php.requestHandler.documentRoot, + 'wordpress-remote-asset-paths' + ); + + /** + * Don't download static assets if they're already downloaded. + * WordPress may be loaded either from a production release or a minified bundle. + * Minified bundles are shipped without most CSS files, JS files, and other static assets. + * Instead, they contain a list of remote assets in wordpress-remote-asset-paths. + * We use this list to determine if we should fetch them on demand or if they are already downloaded. + * If the list is empty, we assume the assets are already downloaded. + * See https://github.com/WordPress/wordpress-playground/pull/1531 to understand how we use the remote asset list to backfill assets on demand. + */ + if ( + !php.fileExists(remoteAssetListPath) || + (await php.readFileAsText(remoteAssetListPath)) === '' + ) { + return; + } + const wpVersion = await getLoadedWordPressVersion(php.requestHandler); + const staticAssetsDirectory = + wpVersionToStaticAssetsDirectory(wpVersion); + if (!staticAssetsDirectory) { + return; + } + const response = await fetch( + joinPaths('/', staticAssetsDirectory, 'wordpress-static.zip') + ); + + if (!response.ok) { + throw new Error( + `Failed to fetch WordPress static assets: ${response.status} ${response.statusText}` + ); + } + + await unzipFile( + php, + new File([await response.blob()], 'wordpress-static.zip'), + php.requestHandler.documentRoot + ); + // Clear the remote asset list to indicate that the assets are downloaded. + await php.writeFile(remoteAssetListPath, ''); + } catch (e) { + logger.warn('Failed to download WordPress assets', e); + } } const apiEndpoint = new PlaygroundWorkerEndpoint( diff --git a/packages/playground/wordpress-builds/build/Dockerfile b/packages/playground/wordpress-builds/build/Dockerfile index fb62d4cc26..e810a25901 100644 --- a/packages/playground/wordpress-builds/build/Dockerfile +++ b/packages/playground/wordpress-builds/build/Dockerfile @@ -44,11 +44,19 @@ RUN rm -rf wordpress-static/wp-content/mu-plugins # to request a remote asset or delegate the request for a missing file to PHP. RUN find wordpress-static -type f | sed 's#^wordpress-static/##'> wordpress-remote-asset-paths -# Make the remote asset listing available remotely so it can be downloaded +# Make the remote asset listing available remotely so it can be downloaded # directly in cases where an older minified WordPress build without this file # has been saved to browser storage. RUN cp wordpress-remote-asset-paths wordpress-static/ +# ZIP the static files +RUN cd wordpress-static/ && \ + zip -r ../wordpress-static.zip . && \ + cd .. + +# Move ZIP to the public output directory +RUN cp wordpress-static.zip wordpress-static/ + # Move the static files to the final output directory RUN mkdir /root/output/$OUT_FILENAME RUN mv wordpress-static/* /root/output/$OUT_FILENAME/ @@ -135,6 +143,6 @@ RUN cd wordpress && \ # Build the final wp.zip file RUN mv wordpress /wordpress && \ cp wordpress-remote-asset-paths /wordpress/ && \ + cp wordpress-static.zip /wordpress/ && \ cd /wordpress && \ zip /root/output/$OUT_FILENAME.zip -r . - \ No newline at end of file diff --git a/packages/playground/wordpress-builds/public/wp-6.2/wordpress-static.zip b/packages/playground/wordpress-builds/public/wp-6.2/wordpress-static.zip new file mode 100644 index 0000000000..05d0b4f5ba Binary files /dev/null and b/packages/playground/wordpress-builds/public/wp-6.2/wordpress-static.zip differ diff --git a/packages/playground/wordpress-builds/public/wp-6.3/wordpress-static.zip b/packages/playground/wordpress-builds/public/wp-6.3/wordpress-static.zip new file mode 100644 index 0000000000..adad127d0a Binary files /dev/null and b/packages/playground/wordpress-builds/public/wp-6.3/wordpress-static.zip differ diff --git a/packages/playground/wordpress-builds/public/wp-6.4/wordpress-static.zip b/packages/playground/wordpress-builds/public/wp-6.4/wordpress-static.zip new file mode 100644 index 0000000000..56f70b3001 Binary files /dev/null and b/packages/playground/wordpress-builds/public/wp-6.4/wordpress-static.zip differ diff --git a/packages/playground/wordpress-builds/public/wp-6.5/wordpress-static.zip b/packages/playground/wordpress-builds/public/wp-6.5/wordpress-static.zip new file mode 100644 index 0000000000..6948ee63c9 Binary files /dev/null and b/packages/playground/wordpress-builds/public/wp-6.5/wordpress-static.zip differ diff --git a/packages/playground/wordpress-builds/public/wp-beta/wordpress-static.zip b/packages/playground/wordpress-builds/public/wp-beta/wordpress-static.zip new file mode 100644 index 0000000000..20588eacf4 Binary files /dev/null and b/packages/playground/wordpress-builds/public/wp-beta/wordpress-static.zip differ diff --git a/packages/playground/wordpress-builds/public/wp-nightly/wordpress-static.zip b/packages/playground/wordpress-builds/public/wp-nightly/wordpress-static.zip new file mode 100644 index 0000000000..01149593c3 Binary files /dev/null and b/packages/playground/wordpress-builds/public/wp-nightly/wordpress-static.zip differ diff --git a/packages/playground/wordpress/src/boot.ts b/packages/playground/wordpress/src/boot.ts index 2299ed431f..089ba32616 100644 --- a/packages/playground/wordpress/src/boot.ts +++ b/packages/playground/wordpress/src/boot.ts @@ -219,7 +219,7 @@ async function isWordPressInstalled(php: PHP) { return ( ( await php.run({ - code: `