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

Add WordPress Plugin: Playground ES Modules Support #133

Merged
merged 9 commits into from May 22, 2024

Conversation

adamziel
Copy link
Collaborator

Adds a WordPress plugin to expose WordPress scripts like @wordpress/block-editor as ES modules.

This enables block development without transpilation and, thus, unlocks embedding a block code editor on learn.wordpress.org. With this plugin in place, we can:

  1. Put a code editor on a website
  2. Prepopulate it with an ES6 block using imports
  3. Enable the user to update the code in the editor
  4. Render the block in a WordPress Playground instance with this plugin installed

Notably, this is a proof-of-concept, only intended for use in WordPress Playground.

Implementation details

ES Modules are shipped as JS files generated from core scripts. This plugin:

  • Adds a wp-admin page that enqueues a set of core scripts
  • In JS, it terates over the exports provided by those scripts
  • Rewrites those exports as ES modules (export const autop = window.wp.autop etc.)
  • Sends a REST API request to a Playground instance which creates those files in the filesystem.

In addition, it also:

  • Registers @wordpress script handles in WordPress, e.g. wp_register_script( "@wordpress/block-editor", ..., ['wp-block-editor])
  • Registers a esmodules-import-map script and adds it as a dependency to all the core scripts

This enables the developer to register a script as follows:

add_action('init', function () {
    wp_register_script('my-es-module', plugins_url('test-es-module.js', __FILE__), [
        '@wordpress/block-library',
        '@wordpress/element',
    ]);
    wp_enqueue_script('my-es-module');
});
import { createElement } from '@wordpress/element';
import { registerCoreBlocks } from '@wordpress/block-library';

console.log('Here are some imports from ES modules:', {
	registerCoreBlocks,
	createElement,
});

Testing Instructions

  1. Go to /wp-admin
  2. Confirm you can see the following message logged in devtools:
CleanShot 2023-12-13 at 16 16 57@2x

cc @dmsnell @youknowriad @luisherranz @gziolo

Adds a WordPress plugin to expose WordPress scripts like `@wordpress/block-editor` as ES modules.

This enables block development without transpilation and, thus, unlocks
embedding a block code editor on learn.wordpress.org. With this plugin
in place, we can:

1. Put a code editor on a website
2. Prepopulate it with an ES6 block using imports
3. Enable the user to update the code in the editor
4. Render the block in a WordPress Playground instance with this plugin installed

Notably, this is a proof-of-concept, only intended for use in WordPress Playground.

 ## Implementation details

ES Modules are shipped as JS files generated from core scripts.
This plugin:

* Adds a wp-admin page that enqueues a set of core scripts
* In JS, it terates over the exports provided by those scripts
* Rewrites those exports as ES modules (`export const autop = window.wp.autop` etc.)
* Sends a REST API request to a Playground instance which creates those
  files in the filesystem.

In addition, it also:

* Registers `@wordpress` script handles in WordPress, e.g. `wp_register_script( "@wordpress/block-editor", ..., ['wp-block-editor])`
* Registers a `esmodules-import-map` script and adds it as a dependency to all the core scripts

This enables the developer to register a script as follows:

```php
add_action('init', function () {
    wp_register_script('my-es-module', plugins_url('test-es-module.js', __FILE__), [
        '@wordpress/block-library',
        '@wordpress/element',
    ]);
    wp_enqueue_script('my-es-module');
});
```

```js
import { createElement } from '@wordpress/element';
import { registerCoreBlocks } from '@wordpress/block-library';

console.log('Here are some imports from ES modules:', {
	registerCoreBlocks,
	createElement,
});
```
@adamziel adamziel added Enhancement New feature or request ES Modules Plugin labels Dec 13, 2023
@dmsnell
Copy link
Contributor

dmsnell commented May 21, 2024

I can understand getting this in sooner than later in Playground environments, but isn't this @sirreal what you have been pushing in Core itself?

Do we need to run ahead if we can get this through WordPress?

@sirreal
Copy link
Member

sirreal commented May 22, 2024

Isn't this [being worked on] in Core itself?

To some extent, yes. In Trac ticket 60647 we're working on adding more functionality currently available as scripts to modules. The conversation there may be interesting.

The current plan is not to add all scripts as modules, but to add modules progressively as they're needed. The first one will likely be @wordpress/api-fetch.

Do we need to run ahead if we can get this through WordPress?

As I mentioned, there are a lot of things I don't expect to be modules soon and some probably never. Scripts focused on the backend and editor are probably some of the last things we'd tackle, it would be a major overhaul and there are likely to be a lot of backwards compatibility issues and problems with singleton stores and code duplication.


I did a lot of exploration similar to what you've done here, notably WordPress/wordpress-develop#6239. That generates "proxy modules" in the webpack build that export the global wp[ package ][ exportedName ] "exports" from scripts.

@adamziel
Copy link
Collaborator Author

A lot of improvements can be made here, but this plugin already provides real value so I'll go ahead and merge.

@sirreal what's the tl;dr of not exposing packages like @wordpress/element or @wordpress/icons as modules? Just that interactive blocks won't need them? Because regular blocks tend to use them heavily.

@adamziel adamziel merged commit 0e905cd into trunk May 22, 2024
2 checks passed
@adamziel adamziel deleted the wordpress-es-modules-plugin branch May 22, 2024 23:34
@sirreal
Copy link
Member

sirreal commented May 23, 2024

It's the combination of a few factors. I think one big concern is that we don't want to rush shipping a bunch of modules quickly, then be stuck with a bunch of poorly designed or problematic modules forever (backwards compatibility) because we rushed.

It's also trick y because a lot of scripts are problematic because the have singletons or otherwise don't work well when duplicated, which makes it hard to just ship module versions of scripts, that's a big concern.

I think folks want to avoid just shipping module proxies. There's some appeal to that (it's fast and avoids the duplication problems) but it also negates some of the advantages of modules like lazy loading.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement New feature or request ES Modules Plugin
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants