Opened 19 months ago
Closed 15 months ago
#58285 closed feature request (duplicate)
New filter hook for filtering whole HTML before final output
Reported by: | kubiq | Owned by: | |
---|---|---|---|
Milestone: | Priority: | normal | |
Severity: | normal | Version: | 6.2 |
Component: | General | Keywords: | |
Focuses: | performance | Cc: |
Description
Let's say I have 1 cache plugin that is great in cache but has no or bad CSS and JS combining and minification options, so I have another plugin to do that... than I have another plugin that is removing some unnecessary styles and scripts from HTML on some pages and then I have another one that fixes some width, height, loading, alt attributes...
These plugins use their own ob_starts
again and again, flushing, etc... some of them use some preg_match and replaces, some use domdocument parser and then the website is very slow for administrator or on first load before cache are created.
Currently, most cache, optimizing, assets plugins do something like this
<?php add_action( 'init', function(){ ob_start( 'my_magic_function' ); }, -1 ); function my_magic_function( $html ){ // preg_replaces // maybe domdocument parsing return $html; }
and this is done again and again by every such-a-plugin
That's why I think it should be part of the core and I imagine something like this:
<?php add_action( 'init', function(){ if( apply_filters( 'wp_enable_final_html_filtering', false ) ){ ob_start( 'default_wp_ob_handler' ); } }, -1 ); function default_wp_ob_handler( $html ){ $dom = false; if( apply_filters( 'wp_enable_final_html_dom', false ) ){ $dom = new DOMDocument(); $dom->loadHTML( $html ); $dom = apply_filters( 'wp_filter_final_html_dom', $dom ); $html = $dom->saveHTML(); } return apply_filters( 'wp_filter_final_html', $html ); }
so then plugin developers can easily access html or DOM and change it without the need to use ob_starts and flushes and parsers again and again, eg.:
<?php add_filter( 'wp_enable_final_html_filtering', '__return_true' ); add_filter( 'wp_filter_final_html', function( $html ){ // preg_mathces and replacements return $html; }); // or if you need work with DOM structure add_filter( 'wp_enable_final_html_filtering', '__return_true' ); add_filter( 'wp_filter_final_html_dom', function( $dom ){ // xpath searches and replacements return $dom; }, 10, 2 );
This can improve loading performance for admin users, or on the first load of page before cache is created, it will be more consistent and all cache and optimizing plugins can use these hooks easily then.
Change History (5)
This ticket was mentioned in Slack in #core by westonruter. View the logs.
19 months ago
#3
in reply to:
↑ description
;
follow-up:
↓ 4
@
19 months ago
Hi there, welcome back to WordPress Trac! Thanks for the ticket.
Just noting that this seems related to #43258.
Replying to kubiq:
<?php add_action( 'init', function(){ if( apply_filters( 'wp_enable_final_html_filtering', false ) ){ ob_start( 'default_wp_ob_handler' ); } }, -1 ); function default_wp_ob_handler( $html ){ $dom = false; if( apply_filters( 'wp_enable_final_html_dom', false ) ){ $dom = new DOMDocument(); $dom->loadHTML( $html ); $dom = apply_filters( 'wp_filter_final_html_dom', $dom ); $html = $dom->saveHTML(); } return apply_filters( 'wp_filter_final_html', $html ); }
In this example, the wp_enable_*
filters appear to be redundant, I think we could use has_filter()
instead:
<?php add_action( 'init', function(){ if( has_filter( 'wp_filter_final_html' ) || has_filter( 'wp_filter_final_html_dom' ) ){ ob_start( 'default_wp_ob_handler' ); } }, -1 ); function default_wp_ob_handler( $html ){ $dom = false; if( has_filter( 'wp_filter_final_html_dom' ) ){ $dom = new DOMDocument(); $dom->loadHTML( $html ); $dom = apply_filters( 'wp_filter_final_html_dom', $dom ); $html = $dom->saveHTML(); } return apply_filters( 'wp_filter_final_html', $html ); }
That way only one hook would be needed to enable the filtering, instead of two.
#4
in reply to:
↑ 3
@
19 months ago
Thank you SergeyBiryukov, I wasn't able to find anything similar, but you're right, that's the same problem and similar proposed solution.
And you're also right about that has_filter
:)
Note that the topic of output buffering the page output has come up on the May 2nd Performance Chat. See also Slack thread, as well as a thread in core chat. I have on my todo list to research usage of output buffering in plugins, namely premature flushing. But I see there is another issue that @aristath raised regarding error handling and progressive rendering.