PluginProbe
BerqWP – All-In-One Optimization for Core Web Vitals, Cache, CDN, Images, CSS & JavaScript / 1.9.3
BerqWP – All-In-One Optimization for Core Web Vitals, Cache, CDN, Images, CSS & JavaScript v1.9.3
4.1.16 4.1.15 4.1.14 4.1.13 4.1.12 4.1.11 4.1.10 4.0.30 4.0.29 4.0.28 4.0.27 4.0.26 4.0.24 4.0.25 4.0.23 4.0.22 4.0.21 4.0.19 4.0.18 4.0.17 4.0.16 1.9.3 1.9.4 1.9.5 1.9.6 All 170 releases
searchpro / inc / photon / class-scriptOptimizer.php

class-scriptOptimizer.php in BerqWP – All-In-One Optimization for Core Web Vitals, Cache, CDN, Images, CSS & JavaScript 1.9.3, at inc/photon/class-scriptOptimizer.php

713 lines 31.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class scriptOptimizer {
4 public $loading = 'delay';
5 public $js_mode = '';
6
7 function set_loading($loading)
8 {
9 $this->loading = $loading;
10 }
11
12 function run_optimization($photonClass, $buffer) {
13
14 /* if ($this->loading == 'default') { */
15 /* return $buffer; */
16 /* } */
17
18 $this->js_mode = $photonClass->js_mode;
19
20 // Combine patterns to extract script src attributes and inline script contents
21 $pattern = '/<script\b[^>]*?(?:src=["\'](.*?)["\']|>(.*?)<\/script>)/is';
22 preg_match_all($pattern, $buffer, $matches, PREG_SET_ORDER);
23
24 // Initialize arrays for script sources and inline scripts
25 $scripts = [];
26
27 // Process the matches
28 foreach ($matches as $match) {
29 if (!empty($match[1])) {
30 // Matched script src attribute
31 if (!str_contains($match[0], 'data-berqwp')) {
32 $src = $match[1];
33 $scripts[] = $src;
34 }
35 } elseif (!empty($match[2])) {
36 // Matched inline script content
37 if (!str_contains($match[0], 'data-berqwp')) {
38 $script = $match[2];
39 $scripts[] = $script;
40 }
41 }
42
43 unset($match);
44 }
45
46 // Define the regular expression pattern for inline and external script tags
47 $pattern = '/(<script\b[^>]*>(.*?)<\/script>)/is';
48 $deffer_js = '';
49
50 // Replace with cdn script urls when they're ready
51 $script_tags_to_replace = [];
52
53 // Remove JavaScript using preg_replace_callback
54 $buffer = preg_replace_callback($pattern, function ($matches) use (&$photonClass, &$script_tags_to_replace) {
55 $tag = $matches[0];
56
57 if (strpos($tag, 'document.write(') !== false) {
58 return $tag; // Keep the script tag with id="berqWP"
59 }
60
61 // Create a Simple HTML DOM object
62 $html = str_get_html($tag);
63
64 // Find all script tags
65 foreach ($html->find('script') as $scriptTag) {
66 if (!empty($scriptTag->type) && $scriptTag->type !== 'text/javascript' && $scriptTag->type !== 'application/javascript' && $scriptTag->type !== 'module') {
67
68 return $tag;
69 }
70
71 }
72
73 $tag = $html->save();
74
75 // Clear Simple HTML DOM object
76 $html->clear();
77 unset($html);
78
79
80 if ($photonClass->use_cdn) {
81
82 // Create a Simple HTML DOM object
83 $html = str_get_html($tag);
84
85 // Find all script tags
86 foreach ($html->find('script') as $scriptTag) {
87 $src = $scriptTag->src;
88
89 $kw_found = false;
90
91 foreach ($photonClass->external_js_excluded_keywords as $keyword) {
92 if (stripos($src, $keyword) !== false) {
93 $kw_found = true;
94 }
95 }
96
97 // Check if the script source contains any excluded keywords
98 if (!$kw_found) {
99 // Use wp_remote_get to fetch the script content
100 $response = wp_remote_get($src);
101
102 if (!is_wp_error($response)) {
103 $scriptContent = wp_remote_retrieve_body($response);
104
105 // Send the file URL to CDN as GET parameters
106 /* $cdnUrl = 'https://cdn.berqwp.com/'; */
107
108 global $berqCDN;
109 $berqCDN->add_file_in_queue($src);
110
111 // $cdnUrl = 'https://boost.berqwp.com/photon/cdn/';
112 // $cdnUrl .= '?url=' . urlencode($src);
113 // $cdnUrl .= '&domain=' . $photonClass->domain;
114
115 // $photonClass->add_into_cdn_queue($cdnUrl, $src);
116
117 }
118 }
119 }
120
121 $tag = $html->save();
122
123 // Clear Simple HTML DOM object
124 $html->clear();
125 unset($html);
126
127 }
128
129 // Return the script tag after optimizing with CDN
130 if (strpos($tag, 'data-berqwp') !== false) {
131 return $tag; // Keep the script tag with id="berqWP"
132 }
133
134 if ($this->loading == 'default') {
135 return $tag;
136 }
137
138 // If tag has a match for exclude url list
139 if (!empty($photonClass->js_css_exclude_urls)) {
140 foreach ($photonClass->js_css_exclude_urls as $js_exclude_keyword) {
141 if (!empty($js_exclude_keyword)) {
142 if (strpos($tag, $js_exclude_keyword) !== false) {
143 return $tag;
144 }
145 }
146 }
147 }
148
149 if ($photonClass->js_mode == 1) {
150 $html = str_get_html($tag);
151
152 // Find all script tags
153 foreach ($html->find('script') as $scriptTag) {
154
155 if (empty($scriptTag->type) || $scriptTag->type == 'text/javascript') {
156 $scriptTag->setAttribute('data-type', 'text/javascript');
157 $scriptTag->type = 'text/bwp-script';
158 } else {
159 $scriptTag->setAttribute('data-type', esc_attr($scriptTag->type));
160 $scriptTag->type = 'text/bwp-script';
161 }
162
163 }
164
165
166 // Clear Simple HTML DOM object
167 $tag = $html->save();
168 $html->clear();
169 unset($html);
170
171 return $tag;
172 }
173
174 if ($photonClass->js_mode == 0) {
175
176 if ($photonClass->cache_js && !$photonClass->use_cdn) {
177 $tag = $photonClass->optimize_external_js($tag);
178 }
179
180 $tag_src = $photonClass->get_src_from_script($tag);
181
182
183 if (!empty($tag_src) && $photonClass->use_cdn) {
184 $script_tags_to_replace[] = $tag;
185 }
186
187 $tag = base64_encode($tag);
188
189
190
191 return '<script data-berqwp-js="' . esc_attr($tag) . '"></script>'; // Remove other script tags
192
193 } elseif ($photonClass->js_mode == 2) {
194
195 if ($photonClass->cache_js && !$photonClass->use_cdn) {
196 return $photonClass->optimize_external_js($tag);
197 } else {
198 return $tag;
199 }
200
201 }
202 }, $buffer);
203
204 // if ($photonClass->use_cdn) {
205
206 // $cdn_file_responses = $photonClass->parallelCurlRequests($photonClass->cdn_upload_queue, [], 'GET');
207 // for ($i = 0; $i < count($cdn_file_responses); $i++) {
208
209 // $original_file = $photonClass->original_files_for_cdn[$i];
210 // $cdnData = json_decode($cdn_file_responses[$i]);
211
212 // if ($cdnData && isset($cdnData->status) && $cdnData->status === 'success' && isset($cdnData->filePath)) {
213 // // Use the CDN file path in your WordPress code
214 // $cdnFilePath = $cdnData->filePath;
215 // /* $cdn_file = 'https://cdn.berqwp.com' . $cdnFilePath; */
216 // $cdn_file = $cdnFilePath;
217
218 // if (($photonClass->js_mode == 1 || $photonClass->js_mode == 0) && strpos($cdn_file, '.js') !== false) {
219
220 // foreach ($script_tags_to_replace as $script_tag) {
221 // if (strpos($script_tag, $original_file) !== false) {
222
223 // $origional_tag_base64 = esc_attr(base64_encode($script_tag));
224 // $script_tag = str_replace($original_file, $cdn_file, $script_tag);
225 // $tag = esc_attr(base64_encode($script_tag));
226
227 // $buffer = str_replace($origional_tag_base64, $tag, $buffer);
228
229 // }
230 // }
231 // // $original_file = base64_encode($original_file);
232 // // $cdn_file = base64_encode($cdn_file);
233 // }
234
235 // $buffer = str_replace($original_file, $cdn_file, $buffer);
236 // }
237
238
239 // }
240 // }
241
242 if ($this->loading !== 'default') {
243 add_filter('berqwp_buffer_before_closing_body', [$this, 'script']);
244
245 }
246
247 unset($photonClass);
248
249 return $buffer;
250 }
251
252 function script($script_html) {
253 $script_html .= "
254 <script id='create-blob'>
255 // Get all script tags in the document
256 var scriptTags = document.getElementsByTagName('script');
257
258 // Loop through each script tag
259 for (let i = 0; i < scriptTags.length; i++) {
260 const scriptTag = scriptTags[i];
261
262 // Check if the script tag contains the data-berqwp-js attribute
263 const berqwpAttribute = scriptTag.getAttribute('data-berqwp-js');
264 if (berqwpAttribute) {
265 // Decode the base64 encoded string
266 const decodedString = atob(berqwpAttribute);
267
268 // Extract the inner content of the decoded string
269 const match = decodedString.match(/<script[^>]*>([\s\S]+)<\/script>/i);
270 if (match && match.length > 1) {
271 const innerContent = match[1];
272
273 // Convert the inner content into a Blob
274 const blob = new Blob([innerContent], { type: 'application/javascript' });
275
276 // Create a new script tag with the blob content
277 const newScriptTag = document.createElement('script');
278 newScriptTag.src = URL.createObjectURL(blob);
279 console.log(URL.createObjectURL(blob))
280
281 // Convert the newScriptTag HTML string to base64
282 const newScriptTagHtml = newScriptTag.outerHTML;
283 const base64Encoded = btoa(newScriptTagHtml);
284
285 // Add the base64 encoded string back to the data-berqwp-js attribute of the original script tag
286 scriptTag.setAttribute('data-berqwp-js', base64Encoded);
287 }
288 }
289 }
290
291 </script>
292 ";
293
294
295 $script_html .= "
296 <script id='optimize-js' defer>
297 let js_execution_mode = '" . $this->js_mode . "';
298 let js_loading = '" . $this->loading . "';
299 let berq_content;
300 let berq_click = null;
301 var total_berq_scripts = 0;
302 var loaded_berq_scripts = 0;
303 let assets_to_cache = [];
304
305 var scriptTags = document.querySelectorAll('script[data-berqwp-js]');
306 scriptTags.forEach(div => {
307 const scriptData = atob(div.getAttribute('data-berqwp-js'));
308 const scriptElement = document.createRange().createContextualFragment(scriptData).children[0];
309
310 if (scriptElement.src) {
311 total_berq_scripts++;
312 }
313
314 });
315
316 let lcpElement = null;
317 const lcp_observer = new PerformanceObserver((list) => {
318 const entries = list.getEntries();
319 for (const entry of entries) {
320 if (entry.entryType === 'largest-contentful-paint') {
321 lcpElement = entry.element;
322
323 // If the LCP element has a background image
324 const backgroundImage = window.getComputedStyle(lcpElement).backgroundImage;
325
326 if (backgroundImage && backgroundImage !== 'none') {
327 // Extract the URL from the background-image CSS property
328 const imageUrl = backgroundImage.slice(5, -2);
329
330 // Create a new Image object to check if the background image is loaded
331 const img = new Image();
332 img.src = imageUrl;
333
334 img.onload = function() {
335 console.log('Background image loaded:', imageUrl);
336 let berqwp_lcp_event = new CustomEvent('berqwpLCPLoaded');
337 window.dispatchEvent(berqwp_lcp_event);
338 };
339
340 img.onerror = function() {
341 console.error('Failed to load background image:', imageUrl);
342 };
343 } else {
344 // If there's no background image or it's already loaded
345 let berqwp_lcp_event = new CustomEvent('berqwpLCPLoaded');
346 window.dispatchEvent(berqwp_lcp_event);
347 }
348 }
349 }
350 });
351
352 lcp_observer.observe({ type: 'largest-contentful-paint', buffered: true });
353
354 // let lcpElement = null;
355 // const lcp_observer = new PerformanceObserver((list) => {
356 // const entries = list.getEntries();
357 // for (const entry of entries) {
358 // if (entry.entryType === 'largest-contentful-paint') {
359 // lcpElement = entry.element;
360
361 // console.log(lcpElement)
362
363 // // Check if LCP element is already loaded
364 // if (lcpElement.complete) {
365 // let berqwp_lcp_event = new CustomEvent('berqwpLCPLoaded');
366 // window.dispatchEvent(berqwp_lcp_event);
367 // }
368 // }
369 // }
370 // });
371
372 // lcp_observer.observe({ type: 'largest-contentful-paint', buffered: true });
373
374 // Preload scrpits right after LCP images
375 window.addEventListener('berqwpLCPLoaded', function () {
376 if (js_execution_mode == '1') {
377
378 var scripts = document.querySelectorAll('script[type=\"text/bwp-script\"]');
379 let assets_to_cache = [];
380
381 // Add all external scripts into browser cache
382 scripts.forEach(scriptElement => {
383 if (scriptElement.src) {
384 assets_to_cache.push(scriptElement.src);
385 }
386 });
387
388 (async () => {
389 await berqwp_add_assets_browser_cache(assets_to_cache);
390 })();
391 }
392 })
393
394
395
396 function berqwp_js_handleUserInteraction(event) {
397
398 if (event.type === 'click' || event.type === 'touchstart') {
399 event.preventDefault();
400 berq_click = event.target;
401 }
402
403 if (js_execution_mode == 0) {
404 // Get all script tags with data-berqwp-js attribute
405 var scriptTags = document.querySelectorAll('script[data-berqwp-js]');
406
407 // Add all external scripts into browser cache
408 scriptTags.forEach(div => {
409 const scriptData = atob(div.getAttribute('data-berqwp-js'));
410 const scriptElement = document.createRange().createContextualFragment(scriptData).children[0];
411
412 if (scriptElement && scriptElement.src) {
413 assets_to_cache.push(scriptElement.src);
414 }
415 });
416
417 (async () => {
418 // Call the function to start fetching all scripts
419 await berqwp_add_assets_browser_cache(assets_to_cache);
420
421 // Function to execute scripts
422 function executeScriptsSequentially(scripts, index) {
423 if (index < scripts.length) {
424 var scriptTag = scripts[index];
425 var berqwpJsCode = scriptTag.getAttribute('data-berqwp-js');
426 berqwpJsCode = atob(berqwpJsCode);
427 var parser = new DOMParser();
428 var parsedHTML = parser.parseFromString(berqwpJsCode, 'text/html');
429 var scriptContent = parsedHTML.querySelector('script');
430
431 if (scriptContent) {
432 if (scriptContent.src) {
433 // External script, append to the body
434 var newScript = document.createElement('script');
435 newScript.onload = function () {
436 // Execute the next script in the sequence
437 executeScriptsSequentially(scripts, index + 1);
438 loaded_berq_scripts++;
439 };
440 newScript.src = scriptContent.src;
441
442 // console.log(newScript.src)
443 // document.body.appendChild(newScript);
444 scriptTag.parentNode.insertBefore(newScript, scriptTag.nextSibling);
445
446 } else {
447 var newScript = document.createElement('script');
448 newScript.innerHTML = scriptContent.innerHTML;
449
450 // console.log(newScript);
451 // document.body.appendChild(newScript);
452 scriptTag.parentNode.insertBefore(newScript, scriptTag.nextSibling);
453
454 // Inline script, execute immediately
455 // eval(scriptContent.innerHTML);
456 // Execute the next script in the sequence
457 executeScriptsSequentially(scripts, index + 1);
458 }
459 }
460 }
461 }
462
463 // Start executing scripts sequentially
464 executeScriptsSequentially(scriptTags, 0);
465
466 berq_content = true;
467
468 })();
469
470
471
472 } else if (js_execution_mode == 1) {
473 let bwp_independent_scripts = ['googletagmanager.com/gtag', 'cdn-cookieyes.com/client_data', 'static.getclicky.com', 'clarity.ms/'];
474 var scripts = document.querySelectorAll('script[type=\"text/bwp-script\"]');
475
476 // Function to dynamically load scripts
477 function loadScript(index) {
478 if (index >= scripts.length) {
479 // After all scripts are loaded, dispatch events
480 let event = new Event('DOMContentLoaded', {
481 bubbles: true,
482 cancelable: true
483 });
484 document.dispatchEvent(event);
485 window.dispatchEvent(new Event('load'));
486
487 // Create a new resize event
488 var resizeEvent = new Event('resize');
489
490 // Dispatch the resize event
491 window.dispatchEvent(resizeEvent);
492
493 console.log('scripts loaded.')
494 return;
495 }
496
497 // Create a new script element
498 var script = scripts[index];
499 var newScript = document.createElement('script');
500 // newScript.type = 'text/javascript';
501 newScript.type = script.getAttribute('data-type');
502
503 // Copy the content or src of the original script
504 if (script.src) {
505 newScript.src = script.src;
506
507 let includesItem = bwp_independent_scripts.some(item => script.src.includes(item));
508
509 if (includesItem) {
510 loadScript(index + 1);
511 } else {
512
513 // Set a timeout to proceed even if onload doesn't fire
514 var scriptTimeout = setTimeout(function() {
515 console.warn('Script load timeout:', script.src);
516 loadScript(index + 1);
517 }, 5000); // 5 seconds timeout
518
519
520 newScript.onload = function() {
521 clearTimeout(scriptTimeout); // Clear timeout if script loads successfully
522 loadScript(index + 1);
523 };
524
525 newScript.onerror = function() {
526 clearTimeout(scriptTimeout); // Clear timeout if there's an error loading the script
527 console.warn('Error loading script:', script.src);
528 loadScript(index + 1); // Proceed to the next script
529 };
530 }
531
532
533 } else {
534 newScript.text = script.textContent;
535 setTimeout(function() {
536 loadScript(index + 1);
537 }, 0); // Delay to simulate async load
538 }
539
540 // Copy other attributes if necessary
541 Array.from(script.attributes).forEach(function(attr) {
542 if (attr.name !== 'type') {
543 newScript.setAttribute(attr.name, attr.value);
544 }
545 });
546
547 // Replace the old script with the new script
548 script.parentNode.replaceChild(newScript, script);
549 }
550
551 // Add all external scripts into browser cache
552 scripts.forEach(scriptElement => {
553 if (scriptElement.src) {
554 let includesItem = bwp_independent_scripts.some(item => scriptElement.src.includes(item));
555
556 if (!includesItem) {
557 assets_to_cache.push(scriptElement.src);
558 }
559 }
560 });
561
562 (async () => {
563 await berqwp_add_assets_browser_cache(assets_to_cache);
564
565 // Start loading scripts from the first one
566 loadScript(0);
567
568 })();
569
570
571 // const divs = document.querySelectorAll('script[data-berqwp-js]');
572
573 // // Add all external scripts into browser cache
574 // divs.forEach(div => {
575 // const scriptData = atob(div.getAttribute('data-berqwp-js'));
576 // const scriptElement = document.createRange().createContextualFragment(scriptData).children[0];
577
578 // if (scriptElement && scriptElement.src) {
579 // assets_to_cache.push(scriptElement.src);
580 // }
581 // });
582
583 // (async () => {
584 // // Call the function to start fetching all scripts
585 // await berqwp_add_assets_browser_cache(assets_to_cache);
586
587 // divs.forEach(div => {
588 // const scriptData = atob(div.getAttribute('data-berqwp-js'));
589 // const scriptElement = document.createRange().createContextualFragment(scriptData).children[0];
590 // if (scriptElement) {
591
592 // // Set the onload event handler for the script element
593 // scriptElement.onload = function() {
594 // loaded_berq_scripts++;
595 // };
596
597 // // document.body.appendChild(scriptElement);
598 // // div.insertAdjacentHTML('afterend', scriptElement);
599 // // scriptElement.setAttribute('async', 'false');
600 // // div.parentNode.insertBefore(scriptElement, div.nextSibling);
601
602 // setTimeout(function() {
603 // div.parentNode.insertBefore(scriptElement, div.nextSibling);
604
605 // }, 100)
606 // }
607 // });
608
609
610 // berq_content = false;
611 // setTimeout(function () {
612
613 // let event = new Event('DOMContentLoaded', {
614 // bubbles: true,
615 // cancelable: true
616 // });
617 // document.dispatchEvent(event);
618 // window.dispatchEvent(new Event('load'));
619
620
621 // // Create a new resize event
622 // var resizeEvent = new Event('resize');
623
624 // // Dispatch the resize event
625 // window.dispatchEvent(resizeEvent);
626
627 // }, 1000);
628
629 // })();
630
631
632
633 }
634
635
636
637 // After running the function, remove all event listeners to ensure it runs only once
638 for (let eventType of berqwp_js_interactionEventTypes) {
639 window.removeEventListener(eventType, berqwp_js_handleUserInteraction);
640 }
641 }
642
643 let berqwp_js_interactionEventTypes = ['click', 'mousemove', 'keydown', 'touchstart', 'scroll', 'berqwpLoadJS', 'berqwp_interaction_event'];
644
645 if (js_loading == 'preload') {
646 berqwp_js_interactionEventTypes = ['berqwpStylesLoaded'];
647
648 // berqwp_js_interactionEventTypes.push('berqwpStylesLoaded');
649 }
650
651 for (let eventType of berqwp_js_interactionEventTypes) {
652 window.addEventListener(eventType, berqwp_js_handleUserInteraction, { passive: false });
653 }
654
655 if (js_loading == 'preload' && !document.getElementById('preload-styles')) {
656 // Trigger event to load JavaScript
657 let berqwp_load_js_event = new CustomEvent('berqwpLoadJS');
658
659 // Dispatch the custom event
660 window.dispatchEvent(berqwp_load_js_event);
661 }
662
663 setInterval(function () {
664
665 if (berq_content == true) {
666 berq_content = false;
667 let event = new Event('DOMContentLoaded', {
668 bubbles: true,
669 cancelable: true
670 });
671 document.dispatchEvent(event);
672 window.dispatchEvent(new Event('load'));
673
674
675 // Create a new resize event
676 var resizeEvent = new Event('resize');
677
678 // Dispatch the resize event
679 window.dispatchEvent(resizeEvent);
680
681
682
683 }
684
685 if (berq_click && total_berq_scripts == loaded_berq_scripts) {
686 setTimeout(function() {
687 console.log(berq_click);
688 const clickEvent = new MouseEvent('click', {
689 bubbles: true,
690 cancelable: true,
691 view: window
692 });
693 berq_click.dispatchEvent(clickEvent);
694 berq_click = null;
695 }, 500)
696 }
697
698 }, 2000);
699
700 var berq_timeo;
701 if (window.screen.width <= 999) {
702 berq_timeo = 3000;
703 } else {
704 berq_timeo = 4000;
705 }
706
707 </script>
708 ";
709
710 return $script_html;
711 }
712 }
713