Skip to content

[PHP.wasm] Document bundler configuration for the .dat file import in @php-wasm/web - #2776

Merged
mho22 merged 2 commits into
trunkfrom
document-dat-import
Apr 20, 2026
Merged

[PHP.wasm] Document bundler configuration for the .dat file import in @php-wasm/web#2776
mho22 merged 2 commits into
trunkfrom
document-dat-import

Conversation

@adamziel

Copy link
Copy Markdown
Collaborator

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

@adamziel adamziel added [Type] Documentation Improvements or additions to documentation [Type] Enhancement New feature or request labels Oct 13, 2025
@mho22
mho22 self-requested a review October 14, 2025 07:02
Comment thread packages/php-wasm/web/README.md Outdated
Comment on lines 8 to 20
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' });

@mho22 mho22 Oct 14, 2025

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This suggestion has been merged in #2778

Comment thread packages/php-wasm/web/README.md Outdated
Comment on lines +30 to +49
## 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`.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for that, I should have created that section when we struggled with this a few months back with @bgrgicak.

Comment thread packages/php-wasm/web/README.md Outdated
Comment on lines +59 to +62
'.dat': 'file',
'.wasm': 'file',
'.so': 'file',
'.la': 'file',

@mho22 mho22 Oct 14, 2025

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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',
			}
		}
	}
} );

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mho22 what build part are you referring to. I feel like I'm missing something obvious.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I posted this and only then noticed the build key directly below this comment. ✅

@adamziel

Copy link
Copy Markdown
Collaborator Author

Thank you so much for reviewing @mho22!

@mho22 mho22 self-assigned this Apr 15, 2026
… `@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.
@mho22
mho22 force-pushed the document-dat-import branch from ba27985 to 82bcbe6 Compare April 20, 2026 15:04
@mho22
mho22 requested review from a team and ashfame and removed request for ashfame April 20, 2026 15:04
@mho22
mho22 merged commit d73b397 into trunk Apr 20, 2026
48 checks passed
@mho22
mho22 deleted the document-dat-import branch April 20, 2026 15:24
erseco added a commit to erseco/facturascripts-playground that referenced this pull request May 11, 2026
…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.
erseco added a commit to ateeducacion/moodle-playground that referenced this pull request May 11, 2026
)

@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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Type] Documentation Improvements or additions to documentation [Type] Enhancement New feature or request

3 participants