Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use .zip files instead of .data files for loading WordPress #978

Merged
merged 6 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/docs/site/docs/09-blueprints-api/06-isomorphic.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ With this PR applied, all of the following `login()` calls are valid:

```ts
// In the browser
const phpInSameThread = await WebPHP.load('7.4', { dataModules: ['wp.data'] });
const phpInSameThread = await WebPHP.load('7.4');
// unzip WordPress in /wordpress
await login(phpInSameThread);

const phpInWorker = await consumeAPI(playgroundIframe);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ nx bundle-wordpress playground-wordpress --wp-version=6.1

The bundler outputs:

- `packages/playground/wordpress/public/wp-6.1.js` – the JavaScript loader for `wp.data`
- `packages/playground/wordpress/public/wp-6.1.data` – the WordPress data bundle consisting of concatenated contents of all WordPress files
- `packages/playground/wordpress/public/wp-6.1.zip` – zipped WordPress files
- `packages/playground/wordpress/public/wp-6.1/` – a directory with static assets for the specified WordPress versions

Consult [the web bundler Dockerfile](https://github.com/WordPress/wordpress-playground/blob/trunk/src/wordpress-playground/wordpress/Dockerfile) for more details (like the list of supported WordPress versions) and modify it to customize the default WordPress installation.
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ You may need to adjust the above according to server specifics, particularly how

## Customize bundled data

The file `wp.data` is a bundle of all the files for the virtual file system in Playground. There's a data file for each available WordPress version.
The file `wp.zip` is a bundle of all the files for the virtual file system in Playground. There's a data file for each available WordPress version.

The package at `packages/playground/wordpress` is responsible for building these data files.

Expand Down
16 changes: 2 additions & 14 deletions packages/php-wasm/node/src/lib/node-php.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
import { lstatSync, readdirSync } from 'node:fs';
import { getPHPLoaderModule } from '.';
import { withNetworking } from './networking/with-networking.js';
import { withLocalDataModuleLoader } from './with-local-data-module-loader';

export interface PHPLoaderOptions {
emscriptenOptions?: EmscriptenOptions;
Expand Down Expand Up @@ -79,20 +78,9 @@ export class NodePHP extends BasePHP {
const php = new NodePHP(undefined, options.requestHandler);

const doLoad = async () => {
const allModules = await Promise.all([
getPHPLoaderModule(phpVersion),
...(options.dataModules || []),
]);
const [phpLoaderModule, ...dataModules] = allModules;

let emscriptenOptions = options.emscriptenOptions || {};
emscriptenOptions = await withNetworking(emscriptenOptions);
emscriptenOptions = withLocalDataModuleLoader(emscriptenOptions);

const runtimeId = await loadPHPRuntime(
phpLoaderModule,
emscriptenOptions,
dataModules
await getPHPLoaderModule(phpVersion),
await withNetworking(options.emscriptenOptions || {})
);
php.initializeRuntime(runtimeId);
};
Expand Down
82 changes: 0 additions & 82 deletions packages/php-wasm/node/src/lib/with-local-data-module-loader.ts

This file was deleted.

75 changes: 19 additions & 56 deletions packages/php-wasm/progress/src/lib/emscripten-download-monitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@
*/
const FALLBACK_FILE_SIZE = 5 * 1024 * 1024;

export interface MonitoredModule {
dependencyFilename: string;
dependenciesTotalSize: number;
}

/**
* Monitors the download #progress of Emscripten modules
*
Expand All @@ -37,37 +32,32 @@ export class EmscriptenDownloadMonitor extends EventTarget {
#assetsSizes: Record<string, number> = {};
#progress: Record<string, number> = {};

constructor(modules: MonitoredModule[] = []) {
constructor() {
super();

this.setModules(modules);
this.#monitorWebAssemblyStreaming();
}

getEmscriptenOptions() {
return {
dataFileDownloads: this.#createDataFileDownloadsProxy(),
};
expectAssets(assets: Record<string, number>) {
for (const [urlLike, size] of Object.entries(assets)) {
const dummyBaseUrl = 'http://example.com/';
const pathname = new URL(urlLike, dummyBaseUrl).pathname;
const filename = pathname.split('/').pop()!;
if (!(filename in this.#assetsSizes)) {
this.#assetsSizes[filename] = size;
}
if (!(filename in this.#progress)) {
this.#progress[filename] = 0;
}
}
}

setModules(modules: MonitoredModule[]) {
this.#assetsSizes = modules.reduce((acc, module) => {
if (module.dependenciesTotalSize > 0) {
// Required to create a valid URL object
const dummyBaseUrl = 'http://example.com/';
const url = new URL(module.dependencyFilename, dummyBaseUrl)
.pathname;
const filename = url.split('/').pop()!;
acc[filename] = Math.max(
filename in acc ? acc[filename] : 0,
module.dependenciesTotalSize
);
}
return acc;
}, {} as Record<string, number>);
this.#progress = Object.fromEntries(
Object.entries(this.#assetsSizes).map(([name]) => [name, 0])
);
async monitorFetch(fetchPromise: Promise<Response>): Promise<Response> {
const response = await fetchPromise;
const onProgress = (event: CustomEvent<DownloadProgress>) => {
this.#notify(response.url, event.detail.loaded, event.detail.total);
};
return cloneResponseMonitorProgress(response, onProgress);
}

/**
Expand Down Expand Up @@ -95,33 +85,6 @@ export class EmscriptenDownloadMonitor extends EventTarget {
};
}

/**
* Creates a `dataFileDownloads` Proxy object that can be passed
* to `startPHP` to monitor the download #progress of the data
* dependencies.
*/
#createDataFileDownloadsProxy() {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self = this;
const dataFileDownloads: Record<string, any> = {};
// Monitor assignments like dataFileDownloads[file] = #progress
return new Proxy(dataFileDownloads, {
set(obj, file: string, progress) {
self.#notify(file, progress.loaded, progress.total);

// Monitor assignments like dataFileDownloads[file].total += delta
obj[file] = new Proxy(JSON.parse(JSON.stringify(progress)), {
set(nestedObj, prop, value) {
nestedObj[prop] = value;
self.#notify(file, nestedObj.loaded, nestedObj.total);
return true;
},
});
return true;
},
});
}

/**
* Notifies about the download #progress of a file.
*
Expand Down
23 changes: 1 addition & 22 deletions packages/php-wasm/universal/src/lib/load-php-runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,22 +115,18 @@ const loadedRuntimes: Map<number, PHPRuntime> = new Map();
* @public
* @param phpLoaderModule - The ESM-wrapped Emscripten module. Consult the Dockerfile for the build process.
* @param phpModuleArgs - The Emscripten module arguments, see https://emscripten.org/docs/api_reference/module.html#affecting-execution.
* @param dataDependenciesModules - A list of the ESM-wrapped Emscripten data dependency modules.
* @returns Loaded runtime id.
*/

export async function loadPHPRuntime(
phpLoaderModule: PHPLoaderModule,
phpModuleArgs: EmscriptenOptions = {},
dataDependenciesModules: DataModule[] = []
phpModuleArgs: EmscriptenOptions = {}
): Promise<number> {
const [phpReady, resolvePHP, rejectPHP] = makePromise();
const [depsReady, resolveDeps] = makePromise();

const PHPRuntime = phpLoaderModule.init(currentJsRuntime, {
onAbort(reason) {
rejectPHP(reason);
resolveDeps();
// This can happen after PHP has been initialized so
// let's just log it.
console.error(reason);
Expand All @@ -148,24 +144,8 @@ export async function loadPHPRuntime(
}
resolvePHP();
},
monitorRunDependencies(nbLeft) {
if (nbLeft === 0) {
delete PHPRuntime.monitorRunDependencies;
resolveDeps();
}
},
});
await Promise.all(
dataDependenciesModules.map(({ default: dataModule }) =>
dataModule(PHPRuntime)
)
);

if (!dataDependenciesModules.length) {
resolveDeps();
}

await depsReady;
await phpReady;

const id = loadedRuntimes.size;
Expand Down Expand Up @@ -245,7 +225,6 @@ export type EmscriptenOptions = {
ENV?: Record<string, string>;
locateFile?: (path: string) => string;
noInitialRun?: boolean;
dataFileDownloads?: Record<string, number>;
print?: (message: string) => void;
printErr?: (message: string) => void;
quit?: (status: number, toThrow: any) => void;
Expand Down
26 changes: 11 additions & 15 deletions packages/php-wasm/web/src/lib/web-php.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,22 +85,18 @@ export class WebPHP extends BasePHP {
const variant = options.loadAllExtensions ? 'kitchen-sink' : 'light';

const doLoad = async () => {
const allModules = await Promise.all([
getPHPLoaderModule(phpVersion, variant),
...(options.dataModules || []),
]);
const [phpLoaderModule, ...dataModules] = allModules;
options.downloadMonitor?.setModules(allModules);

const runtimeId = await loadPHPRuntime(
phpLoaderModule,
{
...(options.emscriptenOptions || {}),
...(options.downloadMonitor?.getEmscriptenOptions() || {}),
...fakeWebsocket(),
},
dataModules
const phpLoaderModule = await getPHPLoaderModule(
phpVersion,
variant
);
options.downloadMonitor?.expectAssets({
[phpLoaderModule.dependencyFilename]:
phpLoaderModule.dependenciesTotalSize,
});
const runtimeId = await loadPHPRuntime(phpLoaderModule, {
...(options.emscriptenOptions || {}),
...fakeWebsocket(),
});
php.initializeRuntime(runtimeId);
};
const asyncData = doLoad();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,15 @@ export interface ImportWordPressFilesStep<ResourceType> {
export const importWordPressFiles: StepHandler<
ImportWordPressFilesStep<File>
> = async (playground, { wordPressFilesZip, pathInZip = '' }) => {
const zipPath = '/import.zip';
await playground.writeFile(
zipPath,
new Uint8Array(await wordPressFilesZip.arrayBuffer())
);

const documentRoot = await playground.documentRoot;

// Unzip
let importPath = joinPaths('/tmp', 'import');
await playground.mkdir(importPath);
await unzip(playground, { zipPath, extractToPath: importPath });
await playground.unlink(zipPath);
await unzip(playground, {
zipFile: wordPressFilesZip,
extractToPath: importPath,
});
importPath = joinPaths(importPath, pathInZip);

// Carry over any Playground-related files, such as the
Expand Down
2 changes: 1 addition & 1 deletion packages/playground/blueprints/src/lib/steps/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export type GenericStep<Resource> =
| RunSqlStep<Resource>
| SetPhpIniEntryStep
| SetSiteOptionsStep
| UnzipStep
| UnzipStep<Resource>
| UpdateUserMetaStep
| WriteFileStep<Resource>;

Expand Down
Loading
Loading