[PHP.wasm] Document bundler configuration for the .dat file import in @php-wasm/web - #2776
Conversation
| import { PHP } from '@php-wasm/web'; | ||
| import { loadWebRuntime } from '@php-wasm/web' | ||
|
|
||
| // PHP.load() calls import('php.wasm') internally | ||
| // loadWebRuntime() calls import('php.wasm') and import('icudt74l.dat') internally. | ||
| // Your bundler must resolve import('php.wasm') as a static file URL. | ||
| // If you use Webpack, you can use the file-loader to do so. | ||
| const php = await PHP.load('8.0', { | ||
| requestHandler: { | ||
| documentRoot: '/www', | ||
| }, | ||
| }); | ||
| const php = new PHP(await loadWebRuntime('8.3')) | ||
|
|
||
| // Create and run a script directly | ||
| php.mkdirTree('/www'); | ||
| php.mkdir('/www'); | ||
| php.writeFile('/www/index.php', `<?php echo "Hello " . $_POST['name']; ?>`); | ||
| await php.run({ scriptPath: './index.php' }); | ||
|
|
There was a problem hiding this comment.
I tried to reproduce this in a separate project and lots of things have been deprecated, like php.run or php.request. scriptPath had to be /www/index.php and it returned an error since we do not inject name. The second use case is in favor of a PHPRequestHandler instead of php.request.
So here is an updated version that will run a simple script first, and then a HTTP request in the console :
import { PHP, PHPRequestHandler } from '@php-wasm/universal';
import { loadWebRuntime } from '@php-wasm/web';
// loadWebRuntime() calls import('php.wasm') and import('icudt74l.dat') internally.
// Your bundler must resolve import('php.wasm') as a static file URL.
// If you use Webpack, you can use the file-loader to do so.
const php = new PHP(await loadWebRuntime('8.3'));
let response;
php.writeFile('/test.php', `<?php echo "Hello, World!"; ?>`);
// Run a script directly:
response = await php.runStream( {
scriptPath: '/test.php',
} );
console.log(await response.stdoutText);
php.mkdir('/www');
php.writeFile('/www/index.php', `<?php echo "Hello " . $_POST['name']; ?>`);
// Or use the familiar HTTP concepts:
const handler = new PHPRequestHandler({ phpFactory: async () => php });
response = await handler.request({
method: 'POST',
url: 'index.php',
body: { name: 'John' },
});
console.log(response.text);| ## Usage with bundlers | ||
|
|
||
| If you use `@php-wasm/web` with a bundler such as Vite, you may see the following errors: | ||
|
|
||
| ``` | ||
| 01:31:50 [vite] (client) error while updating dependencies: | ||
| Error: Error during dependency optimization: | ||
|
|
||
| ✘ [ERROR] No loader is configured for ".dat" files: app/node_modules/@php-wasm/web/shared/icudt74l.dat | ||
|
|
||
| app/node_modules/@php-wasm/web/shared/icudt74l.js:1:25: | ||
| 1 │ import dataFilename from './icudt74l.dat'; | ||
| ``` | ||
|
|
||
| The `@php-wasm/web` package imports a few non-JavaScript assets file using the import syntax. This ensures | ||
| all the required dependencies may be tracked statically, but it creates an inconvenience for apps relying | ||
| on bundlers. | ||
|
|
||
| To resolve that error, you'll need to configure your bundler to resolve the import above to the URL | ||
| of the `icudt74l.dat` in your app, e.g. `https://playground.wordpress.net/assets/icudt74l.dat`. |
There was a problem hiding this comment.
Thanks for that, I should have created that section when we struggled with this a few months back with @bgrgicak.
| '.dat': 'file', | ||
| '.wasm': 'file', | ||
| '.so': 'file', | ||
| '.la': 'file', |
There was a problem hiding this comment.
I replaced file with text and the build part was no more needed. I don't know if that matters.
import { defineConfig } from 'vite';
export default defineConfig( {
assetsInclude: [/\.dat$/, /\.wasm$/, /\.so$/, /\.la$/],
optimizeDeps : {
esbuildOptions : {
loader : {
'.dat': 'text',
'.wasm': 'text',
'.so': 'text',
'.la': 'text',
}
}
}
} );There was a problem hiding this comment.
@mho22 what build part are you referring to. I feel like I'm missing something obvious.
There was a problem hiding this comment.
I posted this and only then noticed the build key directly below this comment. ✅
|
Thank you so much for reviewing @mho22! |
… `@php-wasm/web` Added instructions for using `@php-wasm/web` with bundlers like Vite. The `import dataFilename from './icudt741.dat';` like published in the package will typically trip up bundlers with their default configuration. cc @fellyph @mho22 @brandonpayton
Updated README to reflect changes in PHP loading and bundler configurations.
ba27985 to
82bcbe6
Compare
…3.1.30 (#37) @php-wasm/web 3.1.22+ ships index.js with a bundler-relative `await import("../intl/shared/icu.dat")`, but the published tarball places the file at `./shared/icu.dat` and there is no sibling `@php-wasm/intl` package on npm. Without a resolver hook, esbuild fails with "Could not resolve ../intl/shared/icu.dat" while bundling the worker (WordPress/wordpress-playground#2776). Add an esbuild plugin that maps the broken path to the real `icu.dat` inside `@php-wasm/web`. The ICU module is loaded lazily and only when the `intl` extension is requested — we never enable it — so the import remains dead at runtime but esbuild now resolves it successfully. Also bump `@php-wasm/web` and `@php-wasm/universal` to ^3.1.30 in lockstep. Bumping only one of the two caused the runtime registry to split across two bundled copies of `@php-wasm/universal`, surfacing as "Runtime with id 1 not found" inside `popLoadedRuntime` whenever `new PHP(runtimeId)` ran after `loadWebRuntime`. Closes #34, closes #36.
) @php-wasm/web 3.1.22+ ships index.js with a bundler-relative `await import("../intl/shared/icu.dat")`, but the published tarball places the file at `./shared/icu.dat` and there is no sibling `@php-wasm/intl` package on npm. Without a resolver hook, esbuild fails with "Could not resolve ../intl/shared/icu.dat" while bundling the worker (WordPress/wordpress-playground#2776). Add an esbuild plugin that maps the broken path to the real `icu.dat` inside `@php-wasm/web`. The ICU module is loaded lazily and only when the `intl` extension is requested — we never enable it — so the import remains dead at runtime but esbuild now resolves it successfully. Also bump `@php-wasm/web`, `@php-wasm/universal`, and `@php-wasm/stream-compression` to ^3.1.30 in lockstep. Bumping the web and universal packages independently splits `loadedRuntimes` across two bundled copies of `@php-wasm/universal`, surfacing as "Runtime with id 1 not found" inside `popLoadedRuntime` whenever `new PHP(runtimeId)` runs after `loadWebRuntime`. Closes #82, closes #84, closes #85.
Added instructions for using
@php-wasm/webwith bundlers like Vite. Theimport dataFilename from './icudt741.dat';like published in the package will typically trip up bundlers with their default configuration.cc @fellyph @mho22 @brandonpayton