Make WordPress Core

Opened 6 years ago

Last modified 7 weeks ago

#43258 new enhancement

Output buffer template rendering and add filter for post-processing (e.g. caching, optimization)

Reported by: nextendweb's profile nextendweb Owned by:
Milestone: Future Release Priority: normal
Severity: normal Version:
Component: General Keywords:
Focuses: docs, performance Cc:

Description

I see that more and more theme and plugin developers start to use output buffering functions for the whole site as they need to manipulate the site's content. For example:

  • Cache the page
  • Combine JS and CSS files
  • Lad JS and CSS files for widgets only when needed
  • Place SEO related things

As it is not officially available in WordPress, developers need to find their way to buffer the output. Probably the most common action is the 'template_redirect', where they can place ob_start()

Then they have to close their output buffer, probably the best action to do that is 'shutdown'.

It wouldn't be a problem, if this method only used once on your site. When multiple plugin or theme use this technique, they should close only their output buffers. As output buffers are LIFO stacked, it is very important to close in the order they were added.

For example:

Cache plugin:

<?php
add_action('template_redirect', function(){
   ob_start();
});

add_action('shutdown', function(){
  $html = ob_get_clean();
  //Let's cache the html and show it...
});

CSS minify plugin:

<?php
add_action('template_redirect', function(){
   ob_start();
});

add_action('shutdown', function(){
  $html = ob_get_clean();
  //Let's find CSS files, minify them and replace the originals
});

In this case the page will be cached and the CSS files will be minified afterwards which will slow down the site as they should be in reverse order. We can fix that with priority, but both 'template_redirect' and 'shutdown' should get the same priority to make sure we close the related output buffer.

Documentation
What I propose is to have an official documentation which suggests the right way to use output buffering. It would help prevent several conflicts between plugins and themes.

Future
It would be great to see in WordPress core an in-built output buffering system. Then the developers wouldn't need to start and close output buffers on their own. WordPress would do the output buffering and at the end it would allow the filtering of the content.

<?php
echo apply_filters('wp_output', $output);

Attachments (1)

class-wp-output-buffer.php (1.2 KB) - added by nextendweb 3 years ago.
WP_Output_Buffer class

Download all attachments as: .zip

Change History (15)

#1 follow-up: @swissspidy
6 years ago

  • Focuses coding-standards removed

It would be great to see in WordPress core an in-built output buffering system. Then the developers wouldn't need to start and close output buffers on their own. WordPress would do the output buffering and at the end it would allow the filtering of the content.

That sounds a lot like treating the symptoms not the cause.

#2 in reply to: ↑ 1 @nextendweb
6 years ago

Replying to swissspidy:

That sounds a lot like treating the symptoms not the cause.

And what do you think, what is the cause?

#3 @DrewAPicture
6 years ago

  • Keywords 2nd-opinion added

What I propose is to have an official documentation which suggests the right way to use output buffering. It would help prevent several conflicts between plugins and themes.

If we were pursue some kind of "official" mechanism for output buffering, probably the best place for that documentation to live would be in the Theme Developer Handbook here: https://developer.wordpress.org/themes/

#4 @nextendweb
6 years ago

I started to investigate how different plugins and themes use output buffering to modify the output of the page. Here you can check the collection: https://github.com/nextend/wp-ob-plugins-themes/blob/master/README.md

It would be great to hear feedback from other developers to find the preferred usage of output buffering and then create and official documentation on this topic.

@nextendweb
3 years ago

WP_Output_Buffer class

#5 @nextendweb
3 years ago

I propose the attached WP_Output_Buffer class, which would be an optional feature what developers could enable and use when needed. It simply starts an output buffer and runs the 'output_buffer' filter on the content of the buffer which holds the whole output of the site.

Also the class gives suggested priorities for different use cases so developers can hook to the right point.

<?php
<?php
if (class_exists('WP_Output_Buffer')) {
    WP_Output_Buffer::enable();

    add_filter('output_buffer', array(
        $this,
        'prepareOutput'
    ), WP_Output_Buffer::DEFAULT_PRIORITIES['CONTENT']);
} else {
    /**
     * The plugin and theme mechanism for old WordPress version which do not support this feature.
     */
}

Several huge plugins use global output buffers like:

  • Wordfence Security @mmaunder
  • Jetpack
  • Really Simple SSL @rogierlankhorst
  • SG Optimizer @hristo-sg
  • LiteSpeed Cache @litespeedtech
  • WP Fastest Cache @emrevona
  • Autoptimize @optimizingmatters
  • Smush @alexdunae
  • W3 Total Cache @joemoto
  • WP Rocket
  • EWWW Image Optimizer @nosilver4u
  • Smart Slider 3

and much more: wpdirectory.net => ob_start\( ?array and wpdirectory.net => ob_start\(('|")

#6 @OptimizingMatters
3 years ago

Agreed: some standardization around the use of the OB could certainly be helpful.

#7 @DaanvandenBergh
3 years ago

Absolutely!

However, if using an output buffer isn't the recommended method (which is what @swissspidy seems to be suggesting) I'd love to see some documentation on what the preferred way is to manipulate a HTML document in its entirety.

#8 in reply to: ↑ description @SergeyBiryukov
10 months ago

Replying to nextendweb:

Future
It would be great to see in WordPress core an in-built output buffering system. Then the developers wouldn't need to start and close output buffers on their own. WordPress would do the output buffering and at the end it would allow the filtering of the content.

<?php
echo apply_filters('wp_output', $output);

Related: #58285

This ticket was mentioned in Slack in #core by sergey. View the logs.


10 months ago

#10 @westonruter
6 months ago

#58285 was marked as a duplicate.

#11 @westonruter
6 months ago

  • Summary changed from Output buffering to Output buffer template rendering and add filter for post-processing (e.g. caching, optimization)

#12 @westonruter
6 months ago

  • Focuses performance added
  • Keywords 2nd-opinion removed
  • Milestone changed from Awaiting Review to Future Release

In addition to standardizing output buffering for the sake of caching plugins and optimization plugins, core also would benefit from an output buffer to do its own post-processing optimizations for images. See #59331.

#13 @dmsnell
2 months ago

One of the areas I want to explore with the HTML API is adding a new set of filters for final rendered content where we could scan the full HTML document on render and let plugins attach to different events on that scan. For example, one filter to give access to a tag and its attributes, another filter to process #text node content between tags.

I'm optimistic that we'll be able to have something performant enough that if we can eliminate just a few of Core's existing filtering pipelines and replace them with this new single-pass transform that we'll break even on speed or even become faster than how things are today.

There is a heap of code out there doing full parsing of the HTML available to the filter, which often runs slow or stresses the available memory. I'd like to better understand what kinds of needs are out there leading developers to enable output buffering.

#14 @tabrisrp
7 weeks ago

This is something that we would be interested in participating in, as we make usage of this our main plugins to manage optimizations in the front-end output.

We do encounter from time to time issues with output buffering, when other plugins don't use it correctly.

Note: See TracTickets for help on using tickets.