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

feat: Third-party block support #22

Merged
merged 30 commits into from
Sep 13, 2024
Merged

feat: Third-party block support #22

merged 30 commits into from
Sep 13, 2024

Conversation

dcalhoun
Copy link
Member

@dcalhoun dcalhoun commented Sep 6, 2024

Description

Add experimental editor relying upon editor assets fetched from the remote WordPress site, enabling the ability to utilize third-party blocks. This experimental approach serves as a prototype and relies upon a new endpoint provided by a plugin, as landing the required endpoint in Gutenberg/core may require a fair amount of effort and time.

Screen recording
RPReplay_Final1725989947.MP4

Relates to:

Testing Instructions

Tip

Use the prototype build from the sibling WP-iOS PR.

Important

This remote editor currently only supports self-hosted sites when authenticating with a site's admin username and application password. It also requires installing and activating the block-editor-assets-endpoint plugin for your self-hosted site.

Third-party blocks function for self-hosted sites

  1. Install and activate the block-editor-assets-endpoint plugin on your self-hosted site.
  2. In the app, enable the "Experimental Block Editor" and "Experimental Block Editor Plugins" feature flags.
  3. Open a self-hosed site's post containing third-party blocks.
  4. The blocks should render as expected, editing the blocks should also succeed.

WPCOM-authenticated sites utilize the local editor

  1. Enable the "Experimental Block Editor" and "Experimental Block Editor Plugins" feature flags.
  2. Open a WPCOM-authenticated site's post containing third-party blocks.
  3. The blocks should render "unsupported" messages.

Source which modules should be externalized.
This custom header causes CORS errors. Although settings the mode to
'cors' should prevent this header, incorrect middleware order results in
setting the header.
`@wordpress/api-fetch` supports fetching both a `path` and `url`. When
passing the former, we need to guard against an undefined `path.`
Enable fetching remote editor assets from a site.
It appears a race condition results in the content briefly displaying
before these lines reset out the content entirely.
The second parameter (edits) appears to expect and object. The third
parameter is optional.
Align with core code and improve readability.
Rely upon plugin-provided remote editor for simplify proof-of-concept
testing.
It is possible to fetch relative paths, we should support this to avoid
cryptic errors.
Ensure the correct path is fetched.
This plugin-provided endpoint cannot be retrieved via WPCOM REST API
URLs. We must rely upon the core REST API path.
Without unique hashes, it is near impossible to invalidate cached
assets.
A prior change to support paths without a preceding forward slash
introduced a bug where an extra forward slash was inserted into the
middle of the string replacement.
Without this, only the first of the target two path segments are
captured.
It was unnecessary to have multiple commands to build or preview
production builds.
The default is `/`, which should suffice.
This already occurs in core logic. This line duplicated the logic and
resulted in unexpected clearing of editor content.
The default of `/` incorrectly sources from the root of the project,
rather than the nested build directory.
Without disabling the sub-registry, a separate, duplicative registry was
utilized, which caused certain block selectors to return empty results.
receiveEntityRecords('postType', post.type, post);

setupEditor(post, [], []);
setupEditor(post, {});
Copy link
Member Author

Choose a reason for hiding this comment

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

Updated to mirror the argument types found in core. Second parameter is an object, third is optional.

@@ -174,6 +171,7 @@ function Editor({ post }) {
onInput={onBlockEditorInput}
onChange={onBlockEditorChange}
settings={settings}
useSubRegistry={false}
Copy link
Member Author

Choose a reason for hiding this comment

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

Required to ensure a singleton store is used for the block editor. Otherwise, plugins querying for blocks will find a new, empty store.

return next(options);
}

function apiPathModifierMiddleware(options, next) {
const { siteApiNamespace } = getGBKit();

if (siteApiNamespace && !options.path.includes(siteApiNamespace)) {
if (
options.path &&
Copy link
Member Author

Choose a reason for hiding this comment

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

It is possible to query with options.url rather than options.path, so we need to guard for that scenario.

Comment on lines +27 to +30
// Utilize remote-loaded globals rather than importing local modules
const { dispatch } = window.wp.data;
const { store: editorStore } = window.wp.editor;
const { store: preferencesStore } = window.wp.preferences;
Copy link
Member Author

Choose a reason for hiding this comment

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

Referencing global rather than imports simplifies the Vite build config, avoiding the need to externalize this libraries, but somehow not reference them until after the editor assets load.

Comment on lines +79 to +80
// Discard remote copies of localy-sourced Gutenberg packages to avoid conflicts
const localGutenbergPackages = ['api-fetch'];
Copy link
Member Author

Choose a reason for hiding this comment

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

We load the @wordpress/api-fetch package locally to configure its options, therefore we do not load the remote copy.

Comment on lines -8 to -15
// Removes hashes from the filenames
rollupOptions: {
output: {
entryFileNames: `assets/[name].js`,
chunkFileNames: `assets/[name].js`,
assetFileNames: `assets/[name].[ext]`,
},
},
Copy link
Member Author

Choose a reason for hiding this comment

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

Without filename hashes, it is near impossible to invalidate the asset cache.

Comment on lines +17 to +26
function externalize(id) {
const externalDefinition = defaultRequestToExternal(id);
return (
!!externalDefinition &&
!id.endsWith('.css') &&
!['apiFetch', 'i18n', 'url', 'hooks'].includes(
externalDefinition[externalDefinition.length - 1]
)
);
}
Copy link
Member Author

Choose a reason for hiding this comment

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

Externalizes all WordPress package imports that have external definitions, are not CSS, and are not the packages we use locally in our editor setup.

@dcalhoun dcalhoun marked this pull request as ready for review September 10, 2024 18:21
@dcalhoun dcalhoun requested a review from geriux September 10, 2024 18:22
@dcalhoun
Copy link
Member Author

I discovered that if a Jetpack account connection is not active on the site, this prototype fails. It appears the edit-post script is not enqueued by default in the API endpoint, but declared as a dependency by Jetpack.

So, to see the prototype work currently, one has to:

  1. Install and activate the Jetpack plugin.
  2. Connect Jetpack to a WPCOM account.
  3. Not use the WPCOM account to add the site to the mobile, but rely upon the site's username and application password instead.

I'll seek a solution to this issue.

@dcalhoun
Copy link
Member Author

dcalhoun commented Sep 11, 2024

I discovered that if a Jetpack account connection is not active on the site, this prototype fails. It appears the edit-post script is not enqueued by default in the API endpoint, but declared as a dependency by Jetpack.

I resolved this in [email protected]. Installing the latest release should allow remote editor loading with or without a Jetpack connection.

@dcalhoun dcalhoun added the enhancement New feature or request label Sep 11, 2024
Previously, a remote copy of `remote.html` existing on the targeted site
was utilized to avoid CORS errors when requesting the editor assets
endpoint. However, those CORS errors do not appear to occur now, which
may mean they were unrelated.
@dcalhoun dcalhoun changed the title feat: Remote editor feat: Third-party block support Sep 13, 2024
Copy link

@geriux geriux left a comment

Choose a reason for hiding this comment

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

LGTM! Great work, David! 👏

I couldn’t get it to run locally, but I was able to use the testing build. ✅

Just noting that it sometimes takes a bit to load, but I know that caching or reducing loading time isn't the focus of this PR.

Once this lands we could add the new functionality in #23

@dcalhoun dcalhoun merged commit 0987aa0 into trunk Sep 13, 2024
4 checks passed
@dcalhoun dcalhoun deleted the feat/remote-editor branch September 13, 2024 23:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants