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

Update docs for conditional loading assets using render_callback #21838

Closed
mkaz opened this issue Apr 23, 2020 · 19 comments · Fixed by #22754
Closed

Update docs for conditional loading assets using render_callback #21838

mkaz opened this issue Apr 23, 2020 · 19 comments · Fixed by #22754
Assignees
Labels
Needs Technical Feedback Needs testing from a developer perspective. [Status] In Progress Tracking issues with work in progress [Type] Developer Documentation Documentation for developers [Type] Performance Related to performance efforts

Comments

@mkaz
Copy link
Member

mkaz commented Apr 23, 2020

Issue: Installing numerous blocks that require client assets (JSS and/or CSS) on the front-end results in many files being loaded regardless of the block being used on the page or not.

Ideally, a block's assets only load on a page that uses that block. The ticket #5445 is an outstanding issue to automatically handling loading of assets, but it is a complicated issue without a clear solution in sight.

In the interim, it is possible for each plugin to use the render_callback function when registering their block to enqueue assets only if the block is used. I wrote a blog post explaining the issue, as well as a test block that illustrates it in use.

I raised this in the Core Editor slack meeting but did not receive much feedback there, so raising as an issue for additional comment.

Question: Should we update our documentation stating placing asset enqueuing in the render_callback function is a best practice for conditionally loading assets?

@mkaz mkaz added [Type] Developer Documentation Documentation for developers Needs Technical Feedback Needs testing from a developer perspective. labels Apr 23, 2020
@gziolo gziolo added the [Type] Performance Related to performance efforts label Apr 26, 2020
@gziolo
Copy link
Member

gziolo commented Apr 26, 2020

@mtias did we explore how to mitigate this issue in the past? Can you think about any drawbacks of the proposed workaround?

@aduth do you think we could optimize it on the register_block_type by not enqueueing scripts on the front-end until they are detected in the parsed content? Am I missing something here?

@aduth
Copy link
Member

aduth commented Apr 28, 2020

I'm inclined to think it should be feasible to wait to enqueue scripts associated with a block's type at the point that the block is rendered.

A few notes:

  • It would require that the block register its script and style by 'script' and 'style' options of the register_block_type settings. I think this is fine, and can be considered encouragement to use these options as a means of opting in to these improvements.
    • Aside: It may have been that this didn't receive much attention in part because all of the core blocks are contained in a single script and style, and as such they would not currently be able to take advantage of this. That's not to say it shouldn't be implemented, nor that we shouldn't also consider to split those blocks to their own scripts (at least for front-end display).
  • Depending on the timing of when blocks are rendered in a page lifecycle, the scripts might be enqueued in the footer.
    • Maybe automatically handled? I know there's at least an internal mechanism for "late styles"
    • Is it an issue if the script was registered for the header but printed in the footer? Maybe not.
    • Again, it depends when this occurs in the page lifecycle, which optionally could be revised to occur very early if script header/footer placement should be respected.

@mtias
Copy link
Member

mtias commented Apr 28, 2020

One point to consider would be infinite-scroll type of sites, where a block might not be present on the initial page load but in a subsequent fetch.

@aduth
Copy link
Member

aduth commented Apr 28, 2020

One point to consider would be infinite-scroll type of sites, where a block might not be present on the initial page load but in a subsequent fetch.

Do they work with block scripts as it exists today?

Maybe the current behavior of loading all scripts and styles for all blocks can be left intact for the blogroll page. I think it would be less of a problem to optimize this on screens which aren't expecting to load additional blocks after load, or where no blocks would ever be rendered anyways (e.g. single template). I think it's also worth pointing out that even if popular, this isn't a core behavior. Which is to say: I'd hate for it to impede any progress here, because the current behavior is pretty untenable.

@mtias
Copy link
Member

mtias commented Apr 28, 2020

Which is to say: I'd hate for it to impede any progress here, because the current behavior is pretty untenable.

Yes, I agree 100%. If anything, it should be possible to disable this behaviour and any plugin implementing infinite-scroll like behaviours needs to handle it.

@gziolo
Copy link
Member

gziolo commented Apr 29, 2020

  • It would require that the block register its script and style by 'script' and 'style' options of the register_block_type settings. I think this is fine, and can be considered encouragement to use these options as a means of opting in to these improvements.

💯

  • Aside: It may have been that this didn't receive much attention in part because all of the core blocks are contained in a single script and style, and as such they would not currently be able to take advantage of this. That's not to say it shouldn't be implemented, nor that we shouldn't also consider to split those blocks to their own scripts (at least for front-end display).

We also don't enqueue any JS code on the front so that's another reason why we didn't work on it so far. It could be still beneficial to apply this technique to styles though.

  • Depending on the timing of when blocks are rendered in a page lifecycle, the scripts might be enqueued in the footer.

It looks like do_blocks doesn't render automatically:

https://github.com/WordPress/wordpress-develop/blob/ac6cb23470ecd49d0eec4b3a16b921194cc5a4d1/src/wp-includes/blocks.php#L532-L548

@senadir
Copy link
Contributor

senadir commented Apr 29, 2020

Two patterns I've seen:
1- Loading assets on the render function, WooCommerce blocks uses this pattern (along with other data needs). https://github.com/woocommerce/woocommerce-gutenberg-products-block/blob/master/src/BlockTypes/Checkout.php#L51-L64
2- Using has_block to decide if we should load or not, Meeting calendar block uses this
https://github.com/Automattic/meeting-calendar/blob/master/plugin.php#L108-L117

@mkaz
Copy link
Member Author

mkaz commented Apr 29, 2020

@mtias @aduth This technique does work with infinite scroll 👍

@iandunn
Copy link
Member

iandunn commented May 15, 2020

render_callback() gets unexpectedly executed in the editor, maybe because of #18394.

Because of that, plugins that have separate back end and front end builds may want to check is_admin() in their render_callback(), and only enqueue the front end assets if it's not.

@aduth
Copy link
Member

aduth commented May 29, 2020

A pull request exploring to make this the default behavior: #22754

@github-actions github-actions bot added the [Status] In Progress Tracking issues with work in progress label May 29, 2020
@westonruter
Copy link
Member

westonruter commented Jun 13, 2020

I just saw this issue and it's great to see. However, I have a concern about FOUC.

Has it been considered to not just enqueue the scripts and styles but rather print them instead? This will reduce the risk of a flash of unstyled content, as otherwise enqueued assets will get printed at wp_footer, correct?

I took this approach in the Syntax-highlighting Code Block plugin. It's definitely not as clean as just deferring to enqueue in #22754, but it did address FOUC.

@westonruter
Copy link
Member

See also studiopress/atomic-blocks#294 & studiopress/atomic-blocks#297 which do this for Atomic Blocks, to conditionally print the Font Awesome stylesheet before the first dependent block in the page.

@spacedmonkey
Copy link
Member

There is currently a bug in core with loading CSS assets in the footer. See #30579. I think that this would need to be fixed before this goes into core.

@westonruter
Copy link
Member

This is actually not a bug (anymore). See the comment I just posted on that issue.

@gziolo
Copy link
Member

gziolo commented Jun 16, 2020

See also studiopress/atomic-blocks#294 & studiopress/atomic-blocks#297 which do this for Atomic Blocks, to conditionally print the Font Awesome stylesheet before the first dependent block in the page.

It interesting approach. What about all dependencies that scripts define, will they be printed at the same time when rendering script tags for the block? Could it create any issues this way? I'd be curious to explore it regardless. I don't know if it can have some impact on the front-end code.

@westonruter
Copy link
Member

Yes, any dependencies will get printed as well (if they haven't been printed already). Once the assets and their dependencies are printed, then any subsequent blocks will print nothing (since the assets are then marked as done).

@gziolo
Copy link
Member

gziolo commented Jul 1, 2020

I'm exploring the approach @westonruter suggested as a direct change in WordPress core. I made some progress but there is one edge case as noted in https://core.trac.wordpress.org/ticket/50328#comment:3.

@westonruter
Copy link
Member

That edge case is actually accounted for (mostly) in the the second Atomic Blocks PR I linked to above: studiopress/atomic-blocks#297

And you've come up with the same solution!

@gziolo
Copy link
Member

gziolo commented Jul 4, 2020

It looks like #22754 doesn’t work in some cases as expected and it needs to be reverted. I still don’t quite know why this technique might not wotk for CSS on the front-end. Maybe CSS is printed only once in the head for some themes?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Technical Feedback Needs testing from a developer perspective. [Status] In Progress Tracking issues with work in progress [Type] Developer Documentation Documentation for developers [Type] Performance Related to performance efforts
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants