PluginProbe
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization / 4.2.7
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization v4.2.7
4.2.13 4.2.12 4.2.11 4.2.10 4.2.9 4.2.8 4.2.7 4.2.6 4.2.5 2.5.5 2.5.6 2.5.7 3.0.0 3.0.1 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.11.0 3.11.1 3.11.2 3.11.3 3.12.0 3.12.1 All 134 releases
optimole-wp / assets / js / modules / lcp.js

lcp.js in Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization 4.2.7, at assets/js/modules/lcp.js

108 lines 3.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Optimole LCP (Largest Contentful Paint) Detection Module
3 * Handles LCP element detection and processing
4 */
5
6 import { optmlLogger } from './logger.js';
7 import { optmlDomUtils } from './dom-utils.js';
8
9 /**
10 * LCP detection utilities
11 */
12 export const optmlLcp = {
13 /**
14 * Detect and process LCP element
15 * @returns {Promise<Object>} Promise that resolves with LCP data
16 */
17 detectLcpElement: async function() {
18 // Track LCP element - use a single object to store all LCP data
19 const lcpData = {
20 element: null,
21 imageId: null,
22 bgSelector: null,
23 bgUrls: null
24 };
25
26 // Set up LCP detection - more performant approach
27 if (!PerformanceObserver.supportedEntryTypes.includes('largest-contentful-paint')) {
28 optmlLogger.info('LCP detection not supported in this browser');
29 return lcpData;
30 }
31
32 // Use a pre-existing LCP entry if available instead of waiting
33 const lcpEntries = performance.getEntriesByType('largest-contentful-paint');
34
35 if (lcpEntries && lcpEntries.length > 0) {
36 // Use the most recent LCP entry
37 const lastEntry = lcpEntries[lcpEntries.length - 1];
38 if (lastEntry && lastEntry.element) {
39 lcpData.element = lastEntry.element;
40 optmlLogger.info('LCP element found from existing entries:', lcpData.element);
41 this._processLcpElement(lastEntry.element, lcpData);
42 }
43 } else {
44 // If no existing entries, set up observer with shorter timeout
45 optmlLogger.info('Setting up LCP observer');
46
47 // Create a promise that will resolve when LCP is detected or timeout
48 await new Promise(resolve => {
49 const lcpObserver = new PerformanceObserver(entryList => {
50 const entries = entryList.getEntries();
51 if (entries.length === 0) return;
52
53 // Use the most recent entry
54 const lastEntry = entries[entries.length - 1];
55 if (lastEntry && lastEntry.element) {
56 lcpData.element = lastEntry.element;
57 optmlLogger.info('LCP element detected:', lcpData.element);
58 this._processLcpElement(lastEntry.element, lcpData);
59 }
60
61 lcpObserver.disconnect();
62 resolve();
63 });
64
65 lcpObserver.observe({ type: 'largest-contentful-paint', buffered: true });
66
67 // Use a shorter timeout - most LCP elements are detected within 1-2 seconds
68 setTimeout(() => {
69 lcpObserver.disconnect();
70 resolve();
71 }, 1500);
72 });
73 }
74
75 return lcpData;
76 },
77
78 /**
79 * Process LCP element to extract relevant data
80 * @private
81 * @param {Element} element - LCP element
82 * @param {Object} lcpData - LCP data object to populate
83 */
84 _processLcpElement: function(element, lcpData) {
85 if (!element) return;
86
87 // Check if LCP element is an image with data-opt-id
88 if (element.tagName === 'IMG') {
89 const id = element.getAttribute('data-opt-id');
90 if (id) {
91 lcpData.imageId = parseInt(id, 10);
92 optmlLogger.info('LCP element is an Optimole image with ID:', lcpData.imageId);
93 }
94 }
95 // Check if LCP element has a background image
96 else {
97 const bgImage = optmlDomUtils.hasBackgroundImage(element, true);
98
99 if (bgImage !== false) {
100 lcpData.bgSelector = optmlDomUtils.getUniqueSelector(element);
101 lcpData.bgUrls = optmlDomUtils.extractUrlsFromBgImage(bgImage);
102
103 optmlLogger.info('LCP element has background image:', lcpData.bgSelector, lcpData.bgUrls);
104 }
105 }
106 }
107 };
108