PluginProbe
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder / trunk
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder vtrunk
2.12.0 2.11.1 2.11.0 2.10.0 2.9.0 2.7.4 2.7.5 2.7.6 2.7.7 2.8.0 2.8.1 2.9.1 trunk 1.0 1.0-beta1 1.0-beta2 1.0-beta3 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.2.0 1.2.1 All 78 releases
ablocks / includes / performance / delay-js.php

delay-js.php in aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder trunk, at includes/performance/delay-js.php

106 lines 3.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace ABlocks\Performance;
3
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit;
6 }
7
8 use ABlocks\Helper;
9
10 /**
11 * Performance Suite — delay JavaScript until the first user interaction.
12 *
13 * The aBlocks combined frontend script is emitted in a non-executing form and
14 * swapped in on the first interaction (scroll/key/pointer/touch) or after a
15 * fallback timeout, cutting main-thread work during initial load (INP/TBT).
16 *
17 * Opt-in via `perf_delay_js`. The handles affected are filterable so it stays
18 * scoped to aBlocks scripts (third-party JS is never touched).
19 */
20 class DelayJs {
21
22 public static function init() {
23 if ( is_admin() ) {
24 return;
25 }
26 $enabled = (bool) apply_filters(
27 'ablocks/perf/perf_delay_js',
28 (bool) Helper::get_settings( 'perf_delay_js', false )
29 );
30 if ( ! $enabled ) {
31 return;
32 }
33 // Never delay scripts for a logged-in editor viewing the frontend, so
34 // building/previewing the site is unaffected; real visitors still get it.
35 if ( is_user_logged_in() && current_user_can( 'edit_posts' )
36 && (bool) apply_filters( 'ablocks/perf/bypass_optimizations_for_editors', true ) ) {
37 return;
38 }
39 $self = new self();
40 // The tag rewriting is shared with consent gating; see ScriptGate.
41 ( new ScriptGate(
42 'ablocks/delayed',
43 function ( $handle ) use ( $self ) {
44 return $self->should_delay( $handle );
45 },
46 null,
47 true
48 ) )->hook( 20 );
49 add_action( 'wp_footer', [ $self, 'print_loader' ], 99 );
50 }
51
52 private function handles() {
53 return (array) apply_filters(
54 'ablocks/perf/delay_js_handles',
55 [ 'ablocks-blocks-combine-script' ]
56 );
57 }
58
59 /**
60 * Whether a script handle should be delayed. Covers the combined per-page
61 * script (assets-generation on) and the per-block frontend scripts
62 * (assets-generation off), so delay works in both modes.
63 *
64 * @param string $handle Script handle.
65 * @return bool
66 */
67 public function should_delay( $handle ) {
68 if ( in_array( $handle, $this->handles(), true ) ) {
69 return true;
70 }
71 return (bool) preg_match( '/^ablocks-.+-block-static-script$/', (string) $handle );
72 }
73
74 /**
75 * Print the tiny vanilla loader that activates delayed scripts on interaction.
76 */
77 public function print_loader() {
78 $timeout = (int) Helper::get_settings( 'perf_delay_js_timeout', 5000 );
79 $timeout = max( 0, $timeout );
80 ?>
81 <script id="ablocks-delay-js-loader">
82 ( function () {
83 var loaded = false;
84 var events = [ 'scroll', 'keydown', 'pointerdown', 'touchstart', 'mousemove' ];
85 function load() {
86 if ( loaded ) { return; }
87 loaded = true;
88 events.forEach( function ( e ) { window.removeEventListener( e, load ); } );
89 document.querySelectorAll( 'script[type="ablocks/delayed"]' ).forEach( function ( s ) {
90 var n = document.createElement( 'script' );
91 var src = s.getAttribute( 'data-ablocks-src' );
92 if ( src ) { n.src = src; }
93 if ( s.id ) { n.id = s.id + '-delayed'; }
94 document.body.appendChild( n );
95 } );
96 }
97 events.forEach( function ( e ) { window.addEventListener( e, load, { passive: true, once: true } ); } );
98 <?php if ( $timeout > 0 ) : ?>
99 setTimeout( load, <?php echo (int) $timeout; ?> );
100 <?php endif; ?>
101 } )();
102 </script>
103 <?php
104 }
105 }
106