Earlier this month, I debuted a way to try out Drupal core and the Starshot prototype running in the browser using WebAssembly. It started as a passion project and fascination with new web technologies, something I had tried a year before but didn't find a fit for. Now, it's officially part of a Starshot initiative track.
Here, you can access the trial experience: https://wasm-drupal.mglaman.dev/
Trial experience for Starshot track
I am the lead for the Trial experience for Starshot track. The track has three phases:
- Evaluate, compare, and decide on the best approach to implement a trial experience for Starshot.
- Ability to export trial website to local host (e.g. Zip-file + DDEV)
- More seamless transition from trial to one or more hosting providers
The goal is to have Phase 1 beta for DrupalCon Barcelona and Phase 2 by the launch of Starshot.
I consider Phase 1 completed. A recent update implemented a dedicated Worker to handle the initialization and installation of the Drupal core or Starshot trial. This fixed rendering issues which caused the main UI thread to be locked. It also seems to have alleviated some IndexDB issues when handing them off between the browser and the service worker, which serves PHP requests. I also added locks to handle multiple tabs. During a live demo I accidentally exhausted all of my browser's memory by installing the Drupal core and Starshot prototype simultaneously.
The remaining item for Phase 1 is hosting the current trial experience on Drupal.org rather than my infrastructure (AWS S3 and a CloudFront distribution). Given that it's all static files, it's fairly simple. The Drupal Association is fairly busy switching to Cloud-IAM for the single sign-on solution for user login on Drupal.org domains. Once that is complete, I plan to work with them to provide the solution on Drupal.org.
Below is a quick video of the current progress:
Exporting from the browser to local environments
Phase 2 will be interesting. I have opened a few issues to track exporting a trial for local usage with DDEV. My goal is to have a working prototype of exporting a WebAssembly environment for DrupalCon Barcelona. There are a few challenges, though.
The WebAssembly environment uses SQLite in the browser. SQLite can be exported as an SQL dump (WIP example), but the SQL syntax is not the same as MySQL or Postgres. Drupal does have a DbDumpCommand
command that converts a database schema and values into a PHP script. However, it only works on MySQL. I believe we can convert my existing work in progress with the DbDumpCommand
code. Then we can use php core/scripts/db-tools.php import
and import the script within a DDEV environment.
The codebase itself. The composer.json
for the site running in WebAssembly has been patched to remove Fiber usage in Drupal (used in its renderer and the BigPipe module.) We don't want that in the exported codebase. The archive could contain composer.json
, web/sites/default/settings.php
, web/sites/default/files
for uploaded files, and the database export.
Now, how do we allow someone to export? We need a button somewhere. I experimented with an iframe
approach, like the WordPress Playground. I don't like it. I don't like having to render a secondary false browser URL bar that shows what the current URL for the iframe
is. I'd rather have a button within the Drupal site instead of overlaying some actions or another toolbar. My idea is to inject a "trial module" within the WebAssembly environment. This will allow communicating with a worker to perform extra actions on the environment.
This ties into Phase 3, integrating with hosting providers. Phase 3 is more complex. Just about every hosting provider is powered by a VCS code base source. Once we solve running in DDEV we can find a way to package that into a VCS repository. The GitHub and GitLab API are fairly verbose, which makes it possible to write to repositories. However, we have hosting providers like Acquia, which expect the document root to be a docroot
folder, Pantheon assumes web
if web_docroot: true
in their pantheon.yml
. Meanwhile, Platform.sh doesn't care; you define it yourself. I imagine that any supporting hosting provider will need to accept an archive of the export, which means working with them to define a standard format.
Improving php-wasm functionality
One of my initial hurdles was the inability to build a version of php-wasm locally. It turned out to be a runtime issue. My Acquia work laptop uses Colima as a Docker runtime and failed over some permission changes the build tried to do. But on my personal laptop with Docker Desktop, everything went fine. I had to workaround not having docker-compose
(I have migrated to compose
as a plugin.) See https://github.com/seanmorris/php-wasm/issues/47.
The following are items I'd like to work on, but I believe hitting Phase 2 goals is more important.
Safari support
php-wasm does not work in Safari. Follow https://github.com/mglaman/wasm-drupal/issues/28 to track its resolution and updates. I honestly have no idea why this is happening. To troubleshoot, I must build a php-wasm without optimizations to preserve symbols. I made a build, but it had errors that prevented it from even working on Blink-based browsers. With symbols preserved, the stack trace returned will be easier to understand and troubleshoot.
The default optimization level is -03
. There is a good chance it could also be the optimization level. I haven't tried debugging since the introduction of the dedicated worker. The developer tools weren't making life easy for debugging the service worker.
32-bit integers error
WebAssembly uses 32-bit integers. Drupal throws a warning over this since Unix timestamps break after 2038 unless using 64-bit integers. From my reading, the WebAssembly support of BigInt can work around this and is a standard feature. Unfortunately, the build with BigInt broke when opening the SQLite connection in sqlite3_open_v2
with a Cannot convert 0 to a BigInt
error.
There is a Memory64 proposed feature, but all browsers have it under a feature flag. I think we will have to "live with it" for now.
Drupal adds a warning about this. It may need to be silenced within the WebAssembly environment via the trial module discussed earlier.
Enabling OPcache support
php-wasm does not have OPcache support. I think this will be worth chasing after, as it will provide a direct performance improvement and also silence another warning provided by Drupal at runtime.
The php-wasm build process does not include ext/opcache
in the PHP 8.3 source files. I'm hoping it is as easy as:
- Ensure
ext/opcache
is present - Add
--enable-opcache
toCONFIGURE_FLAGS
(which is passed toemconfigure ./configure
)
I am not sure what consequences adding OPcache may cause, either. The documentation for OPcache states it stores bytecode in "shared memory." I have no idea what that will mean once in WebAssembly and running in the browser.
Want more? Sign up for my weekly newsletter