Allow using self-hosted remote with published Playground client#2750
Allow using self-hosted remote with published Playground client#2750brandonpayton wants to merge 4 commits intotrunkfrom
Conversation
|
There is a big thing that needs fixed before this PR is ready for review. Initially, I started by updating use of virtual Vite modules to reflect a common build version, but using those is awkward because we end up having to declare those virtual modules in packages that are merely dependent upon another package that uses that virtual module. So I switched to using a real module that has a build-time transform to insert the production build version. Unfortunately, this overlooked the fact that dependent package builds still consume the original package source, not the built packages. So many built packages in this PR are still just using the dev-mode build version. In the morning, I will see if we can just solve this issue by marking |
| "$schema": "../../../node_modules/nx/schemas/project-schema.json", | ||
| "sourceRoot": "packages/playground/remote/src", | ||
| "projectType": "library", | ||
| "implicitDependencies": ["playground-wordpress-builds"], |
There was a problem hiding this comment.
This is unrelated to this PR, but I added this after experiencing what appeared to be a timing issue with the Playground remote build (which includes files from playground-wordpress-builds).
It probably does not matter because the build issue was due to something else, but I don't think it hurts to acknowledge the dependency here.
|
I switched this PR back to using a virtual module for build-version. This is now ready for review. |
Every time remote.html is deployed, a new public client.js guaranteed to be compatible with it is also deployed at https://playground.wordpress.net/client/index.js. Importing that client directly in the frontend app is the way to go. Bundling the npm client package is a bad idea. A new remote.html deployment may just make the bundled client obsolete. I sometimes wish we’ve never published the client package. It typically works, which creates a false sense of security. Maybe we should release a new major version that throws an exception with migration instructions when you import it, just to prevent apps from bundling it? A custom telex deployment will also include an up-to-date client library that should have telex domain baked in — importing that client is the way to go. It should just work right now without any changes to the codebase. |
|
To be clear, I mean a direct cross-origin import from the Playground domain. <!DOCTYPE html>
<iframe id="wp-playground" style="width: 1200px; height: 800px"></iframe>
<script type="module">
import { startPlaygroundWeb } from 'https://playground.wordpress.net/client/index.js';
const client = await startPlaygroundWeb({
iframe: document.getElementById('wp-playground'),
remoteUrl: `https://playground.wordpress.net/remote.html`,
blueprint: {
landingPage: '/wp-admin/',
preferredVersions: {
php: '8.0',
wp: 'latest',
},
steps: [
{
step: 'login',
username: 'admin',
password: 'password',
},
{
step: 'installPlugin',
pluginData: {
resource: 'wordpress.org/plugins',
slug: 'friends',
},
},
],
},
});
const response = await client.run({
// wp-load.php is only required if you want to interact with WordPress.
code: '<?php require_once "/wordpress/wp-load.php"; $posts = get_posts(); echo "Post Title: " . $posts[0]->post_title;',
});
console.log(response.text);
</script> |
|
@adamziel, thanks for the clarification here. That makes sense and helps my understanding. The types are even published to https://playground.wordpress.net/client/index.d.ts, so maybe there is a way folks referencing the remote client/index.js can use those as well. I'll close this PR. |
|
@adamziel I forgot to respond to your comments.
I'd need to consider the ramifications a bit more, but that sounds reasonable at the moment. Should we even go further and have new versions throw an error with migration instructions during package install?
This is a good point. Telex currently uses the |
This sounds even better! I also thought about publishing a passthrough package that just imports the remote client, but I don't think it's possible without breaking bc. We can likely "import" it in script modules, but I don't see any way of doing it in non-module scripts. We'd need to fetch() and eval() or append a script tag to body and wait until it's loaded, but no one expects that require() call to return a Promise. Also, bundlers gonna bundle. Even if we got this to work, I'm sure we'd quickly learn a 1000 clever techniques webpack et al use to still inline the remote script. Or a 1000 cryptic error nessages when they fail. |
@adamziel one thing we need is a good way for folks to consume
What do you think? In playing with a local copy of Telex in dev mode, what I've been able to get working is via a dynamic import like: const { startPlaygroundWeb } = await import("https://playground.wordpress.net/client/index.js");
client = await startPlaygroundWeb({
iframe: iframeRef.current,
remoteUrl: "https://playground.wordpress.net/remote.html",
});Vite doesn't seem to like the static imports of remote modules. Based on web searches, it sounds like there are ways to configure Vite to work with such remote imports, but it looked like it required an annoying amount of precise config. The dynamic import worked, and the types were able to be resolved by adding a path mapping to the types in the locally-installed "paths": {
"https://playground.wordpress.net/client/index.js": [
"./node_modules/@wp-playground/client/index.d.ts"
],
}This was pretty straightforward really. But folks need a way to access the types locally. They could add automation to download the remote typedefs (e.g., from https://playground.wordpress.net/client/index.d.ts), but being able to install the types for a specific version from NPM would be easier and much less error-prone. |
Motivation for the change, related issues
Projects like Telex are interested in hosting their own Playground remote.html so they can control when they upgrade to new Playground versions. Unfortunately, the published
@wp-playground/clientbuilds only allows loading/remote.htmlfrom known origins likehttps://playground.wordpress.net.It is possible to build custom versions that allow additional remote origins, but this is an additional burden.
This PR adjusts Playground client to work with any
/remote.htmlif its embedded build version matches the Playground client version.Implementation details
The PR:
remote.html, so the Playground client can fetch theremote.htmland confirm the client and remote versions match.@wp-playground/client'sstartPlaygroundWeb()function to check remote compatibility by fetchingremote.htmland confirming that it contains the same build version as@wp-playground/client.Testing Instructions (or ideally a Blueprint)
npm run devto confirm Playground loads properly in dev mode.