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

Blocks: Re-register core blocks via build copy prefixing #13521

Merged
merged 9 commits into from
Mar 25, 2019

Conversation

aduth
Copy link
Member

@aduth aduth commented Jan 26, 2019

This pull request seeks to try an approach for re-registering the core blocks as a Gutenberg-specific variant, while still allowing core to copy those distributed through the @wordpress/block-library module. The technique is rather primitive: using CopyWebpackPlugin, it copies PHP files from the block-library package, transforming them by looking for function definitions (by pattern) to prefix with gutenberg_. Gutenberg deregisters the core-registered blocks, and registers these instead. Since it's built-in to the Webpack pipeline, it also respects rebuilds on changes during npm run dev.

Testing instructions:

  1. Run npm run dev
  2. Make a change to a block-library PHP file
  3. Observe that changes take effect

@aduth aduth added the [Feature] Blocks Overall functionality of blocks label Jan 26, 2019
@gziolo gziolo added this to the 5.1 (Gutenberg) milestone Feb 7, 2019
@aduth aduth force-pushed the try/reregister-core-block-types branch from 5b5c05c to 9c42ec1 Compare February 8, 2019 20:38
@aduth aduth force-pushed the try/reregister-core-block-types branch from 9c42ec1 to 68a592b Compare February 8, 2019 20:54
@aduth
Copy link
Member Author

aduth commented Feb 8, 2019

In 68a592b, I considered a discovery-based implementation, rather than explicitly listing each of the blocks (doing so after personally neglecting to include the second of two entries for the new "Search" block in a rebase). I'm not totally convinced about it yet, partly because of the magical implications and the possible "trust" implications of discovery-based file loading (though it's something we've done previously in #2014, and later removed in #10147).

lib/load.php Outdated
$registry->unregister( $block_name );
}

require $blocks_dir . $file;
Copy link
Contributor

Choose a reason for hiding this comment

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

So this function is called on the init hook and the files it requires also trigger functions on the init hook. Isn't it too late for the init hooks added in those files to trigger properly?

Copy link
Member Author

Choose a reason for hiding this comment

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

So this function is called on the init hook and the files it requires also trigger functions on the init hook. Isn't it too late for the init hooks added in those files to trigger properly?

Mmm, I'd have sworn I'd seen somewhere we'd used a similar implementation, but in mind of the following, I think it'd be expected to not work. If we handle init here at an earlier priority, it may not be an issue though.

Copy link
Member

Choose a reason for hiding this comment

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

I figured out that my comment is (#13521 (comment)) related to what @youknowriad raised. When I change the code to execute the block's registration immediately then all blocks load properly.

Copy link
Member

Choose a reason for hiding this comment

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

Isn't it too late for the init hooks added in those files to trigger properly?

That should work ever since WP_Hook was introduced.

Copy link
Member Author

Choose a reason for hiding this comment

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

That should work ever since WP_Hook was introduced.

Can you clarify what you mean @swissspidy ? The current issue is that we want to load the blocks implementations at the same priority as the core registration, which based on the aforementioned test cases does not appear to be a supported use-case for hooks.

gziolo
gziolo previously requested changes Feb 11, 2019
Copy link
Member

@gziolo gziolo left a comment

Choose a reason for hiding this comment

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

I see some REST API errors for Archives, RSS and Latest Comments blocks which use SeverSideRender component:

screen shot 2019-02-11 at 09 49 40

lib/load.php Outdated
}

// Derive the assumed block name by file path.
$block_name = 'core/' . $parts['filename'];
Copy link
Member

Choose a reason for hiding this comment

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

It's not always the same, for example:
https://github.com/WordPress/gutenberg/blob/master/packages/block-library/src/classic/index.js#L13

Once JSON file is there, it should fix the issue though.

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's not always the same, for example:
https://github.com/WordPress/gutenberg/blob/master/packages/block-library/src/classic/index.js#L13

Once JSON file is there, it should fix the issue though.

I'm not sure I follow what's meant by "Once JSON file is there", but I think the fact that we can't really rely on the file paths to match the block name could serve as pretty good justification to avoid the newer "discovery"-based approach in favor of an explicit list.

Copy link
Member

Choose a reason for hiding this comment

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

I was referring to #13693 and RFC for server side block registration.

It might be better to hardcode it for now.

lib/load.php Outdated
// Derive the assumed block name by file path.
$block_name = 'core/' . $parts['filename'];

if ( $registry->is_registered( $block_name ) ) {
Copy link
Member

Choose a reason for hiding this comment

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

I was wondering why it isn't using remove_action against add_action( 'init', 'register_block_core_latest_comments' ); and others? Wouldn't be that the most expected behavior?

Copy link
Member Author

Choose a reason for hiding this comment

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

I was wondering why it isn't using remove_action against add_action( 'init', 'register_block_core_latest_comments' ); and others? Wouldn't be that the most expected behavior?

Maybe, but there are a few complications:

  • In the current stable release of WordPress, some blocks are registered immediately, not as part of an init hook (example, addressed as part of the changes of this pull request)
  • As noted in your prior review note, trying to compose these names (i.e. register_) dynamically is prone to being fragile
  • As noted by @youknowriad 's comment, removing a filter would need to occur at an earlier priority than the default for it to work

Copy link
Member

Choose a reason for hiding this comment

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

It's fine as is. I was mostly interested to see whether if this is technically possible without too much hassle.

@aduth
Copy link
Member Author

aduth commented Feb 14, 2019

Rebased to resolve conflicts with the introduction of calendar block (@jorgefilipecosta).

Restored a hard-coded blocks list (a single one at least, this time) in dfc8732.

The init action priority issue is actually a bit more difficult to resolve than I'd anticipated. If Gutenberg's re-registration occurs at an earlier priority, it will be called before core's own block registration handlers. They obviously can't be unregistered at that point, and when they are called, their own registration produces a warning about registering a block by the same name.

Copy link
Member

@gziolo gziolo left a comment

Choose a reason for hiding this comment

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

I will test it again and get back soon :)

lib/load.php Outdated
$registry = WP_Block_Type_Registry::get_instance();

foreach ( $block_names as $file => $block_name ) {
if ( ! file_exists( $blocks_dir . $file ) ) {
Copy link
Member

Choose a reason for hiding this comment

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

I wouldn't mind if this would also print some error using some WordPress magic.

lib/load.php Outdated
// Derive the assumed block name by file path.
$block_name = 'core/' . $parts['filename'];

if ( $registry->is_registered( $block_name ) ) {
Copy link
Member

Choose a reason for hiding this comment

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

It's fine as is. I was mostly interested to see whether if this is technically possible without too much hassle.

@gziolo gziolo force-pushed the try/reregister-core-block-types branch from dfc8732 to e69baad Compare February 15, 2019 12:36
@gziolo
Copy link
Member

gziolo commented Feb 15, 2019

I have no idea if this e69baad is the right approach but it fixes the issue I raised.

Let's see what Travis thinks about my hack.

@gziolo gziolo dismissed their stale review February 15, 2019 12:57

Dismissing

@aduth
Copy link
Member Author

aduth commented Feb 15, 2019

I have no idea if this e69baad is the right approach but it fixes the issue I raised.

Let's see what Travis thinks about my hack.

It will resolve the issue of the blocks not being defined, but per #13521 (comment) will be problematic in that the default core blocks will attempt to register themselves at the normal priority and fail (with a warning notice).

Travis doesn't catch it because I haven't yet finished #13452 😄

@gziolo
Copy link
Member

gziolo commented Mar 5, 2019

I stumbled upon the same issue when working on #14238. As a quick workaround, I renamed all methods to be prefixed with gutenberg_ in 625c7e7. However, it doesn't seem to be a good idea in the long run. I noticed that we never expose those PHP files in build and build-module folders when publishing to npm.

@gziolo gziolo force-pushed the try/reregister-core-block-types branch from cb194f1 to 5bad351 Compare March 19, 2019 13:09
@gziolo
Copy link
Member

gziolo commented Mar 19, 2019

I rebased this PR with the latest changes in master. Code wise it looks good. I hope we can make it less fragile in the near future as we introduce JSON block metadata format. Webpack based copy and replace part seems to be very sensitive but it seems like the only way to proceed at the moment.

I will give it another round of testing before adding ✅.

Copy link
Member

@gziolo gziolo left a comment

Choose a reason for hiding this comment

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

I think it is finally sorted out 🎉

I tested it extensively and it works properly, Travis tends to agree with me :shipit:

@aduth
Copy link
Member Author

aduth commented Mar 19, 2019

Might need one more change, with the block PHP now being considered as part of build output:

build_files=$(ls build/*/*.{js,css})

Related: #14289 (comment)

Should be an easy fix. I'll plan to make it, and give the ZIP a try.

@aduth
Copy link
Member Author

aduth commented Mar 20, 2019

I was able to reproduce it being an issue, but I had a bit more trouble fixing it than I'd anticipated. Just expanding the build_files to cover build/**/*.{js,css,php} yielded some unexpected errors ls: build/**/*.php: No such file or directory (despite working fine when run directly in the terminal). Inlining it into the zip command similarly produced "name not matched" warning. I'll plan to revisit tomorrow.

(Part of me also wonders whether we ought to even both whitelisting specific file extensions, especially when the git clean earlier in the packaging script will ensure that the build folder is completely reset and wouldn't contain extraneous files)

@gziolo
Copy link
Member

gziolo commented Mar 25, 2019

It blocks #14533 from landing. I will have a look at the issue myself to unblock my other PR.

@aduth aduth requested review from nerrad and ntwb as code owners March 25, 2019 13:47
@gziolo
Copy link
Member

gziolo commented Mar 25, 2019

38537a6 should do the trick:

Screen Shot 2019-03-25 at 14 46 25
Screen Shot 2019-03-25 at 14 46 30

@aduth
Copy link
Member Author

aduth commented Mar 25, 2019

@gziolo That seems to work well in my testing 👍 Also confirmed that with some local revisions to a block, they were respected when packaging the plugin and uploading it to a test site.

Generally I'm wondering why build_files is necessary as a separate variable vs. having each build/*/*.{js,css} and build/block-library/blocks/*.php as part of the zip command, though perhaps zip doesn't expand/glob in the same way as ls. In any case, I'd not want it to block moving forward here.

@aduth
Copy link
Member Author

aduth commented Mar 25, 2019

Thinking out loud: I was double-checking whether this would have any impact on the core tooling for bringing block implementations into WordPress. As I see it, the primary purpose for this pull request to exist is the fact that we explicitly do not want to change the process, at least as far as implementations of blocks PHP within packages/block-library to register themselves upon init default priority, without prefixed functions. The changes here are Gutenberg's workaround to have the plugin override those defaults.

@aduth aduth merged commit bd381c4 into master Mar 25, 2019
@aduth aduth deleted the try/reregister-core-block-types branch March 25, 2019 15:22
@youknowriad youknowriad added this to the 5.4 (Gutenberg) milestone Mar 29, 2019
@aduth aduth mentioned this pull request Apr 24, 2019
14 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Blocks Overall functionality of blocks
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants