From 3d5d0e1d597cfac8cd9d6516fbe0cb590f732296 Mon Sep 17 00:00:00 2001 From: Xinyi Feng Date: Mon, 10 Feb 2025 14:07:58 -0800 Subject: [PATCH 1/6] support incoming MFE --- src/index.js | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/index.js b/src/index.js index 5ec3f1d..1dc4d39 100644 --- a/src/index.js +++ b/src/index.js @@ -723,6 +723,10 @@ export async function loadEager(document, options, context) { onPageActivation(() => { adjustRumSampligRate(document, options, context); }); + + // Only take audience keys for MFE to pick up + window.hlx.audieneLibrary = Object.keys(options.audiences); + let res = await runCampaign(document, options, context); if (!res) { res = await runExperiment(document, options, context); @@ -733,10 +737,10 @@ export async function loadEager(document, options, context) { } export async function loadLazy(document, options, context) { - const pluginOptions = { - ...DEFAULT_OPTIONS, - ...(options || {}), - }; + // const pluginOptions = { + // ...DEFAULT_OPTIONS, + // ...(options || {}), + // }; // do not show the experimentation pill on prod domains if (window.location.hostname.endsWith('.live') || (typeof options.isProd === 'function' && options.isProd()) @@ -746,7 +750,25 @@ export async function loadLazy(document, options, context) { || options.prodHost === window.location.origin))) { return; } + + // Send the config to the MFE + window.addEventListener('message', (event) => { + if (event.data?.type === 'hlx:experimentation-get-config') { + try { + const safeClone = JSON.parse(JSON.stringify(window.hlx)); + + event.source.postMessage({ + type: 'hlx:experimentation-config', + config: safeClone, + source: 'index-js' + }, '*'); + } catch (e) { + console.error('Error sending hlx config:', e); + } + } + }); + // eslint-disable-next-line import/no-cycle - const preview = await import('./preview.js'); - preview.default(document, pluginOptions, { ...context, getResolvedAudiences }); + // const preview = await import('./preview.js'); + // preview.default(document, pluginOptions, { ...context, getResolvedAudiences }); } From 0fdbfab51baf266b7fdb906e90bbf62b4395bdf5 Mon Sep 17 00:00:00 2001 From: Xinyi Feng Date: Tue, 25 Mar 2025 08:30:24 -0700 Subject: [PATCH 2/6] add event listener for page reload --- src/index.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 1dc4d39..3a6b131 100644 --- a/src/index.js +++ b/src/index.js @@ -751,7 +751,6 @@ export async function loadLazy(document, options, context) { return; } - // Send the config to the MFE window.addEventListener('message', (event) => { if (event.data?.type === 'hlx:experimentation-get-config') { try { @@ -768,6 +767,12 @@ export async function loadLazy(document, options, context) { } }); + window.addEventListener('message', function(event) { + if (event.data && event.data.type === 'hlx:experimentation-window-reload' && event.data.action === 'reload') { + window.location.reload(); + } + }); + // eslint-disable-next-line import/no-cycle // const preview = await import('./preview.js'); // preview.default(document, pluginOptions, { ...context, getResolvedAudiences }); From fb6f1a462555061ff68f4a68b5690ce0b31a8194 Mon Sep 17 00:00:00 2001 From: Xinyi Feng Date: Tue, 25 Mar 2025 17:09:35 -0700 Subject: [PATCH 3/6] prevent the split number mismatch with variants number issue --- src/index.js | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/index.js b/src/index.js index 3a6b131..260169e 100644 --- a/src/index.js +++ b/src/index.js @@ -263,10 +263,29 @@ function getConfigForInstantExperiment( const splitString = context.getMetadata(`${pluginOptions.experimentsMetaTag}-split`); const splits = splitString - // custom split - ? splitString.split(',').map((i) => parseFloat(i) / 100) - // even split fallback - : [...new Array(pages.length)].map(() => 1 / (pages.length + 1)); + ? // custom split + (() => { + const splitValues = stringToArray(metadata.split).map( + (i) => parseFloat(i) / 100 + ); + + // If fewer splits than pages, pad with zeros + if (splitValues.length < pages.length) { + return [ + ...splitValues, + ...Array(pages.length - splitValues.length).fill(0), + ]; + } + + // If more splits than needed, truncate + if (splitValues.length > pages.length) { + return splitValues.slice(0, pages.length); + } + + return splitValues; + })() + : // even split + [...new Array(pages.length)].map(() => 1 / (pages.length + 1)); config.variantNames.push('control'); config.variants.control = { From f11d78cbb968e0687313c7a08e35682dd2342cf5 Mon Sep 17 00:00:00 2001 From: Xinyi Feng Date: Tue, 25 Mar 2025 17:32:46 -0700 Subject: [PATCH 4/6] update reload event listner --- src/index.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/index.js b/src/index.js index 260169e..99e5989 100644 --- a/src/index.js +++ b/src/index.js @@ -783,16 +783,12 @@ export async function loadLazy(document, options, context) { } catch (e) { console.error('Error sending hlx config:', e); } + } else if (event.data?.type === 'hlx:experimentation-window-reload' && event.data?.action === 'reload') { + window.location.reload(); } }); - window.addEventListener('message', function(event) { - if (event.data && event.data.type === 'hlx:experimentation-window-reload' && event.data.action === 'reload') { - window.location.reload(); - } - }); - - // eslint-disable-next-line import/no-cycle - // const preview = await import('./preview.js'); - // preview.default(document, pluginOptions, { ...context, getResolvedAudiences }); + // eslint-disable-next-line import/no-cycle + // const preview = await import('./preview.js'); + // preview.default(document, pluginOptions, { ...context, getResolvedAudiences }); } From 57d7a6d04431e1cfae3c073958a6261649ccbb25 Mon Sep 17 00:00:00 2001 From: Xinyi Feng Date: Mon, 31 Mar 2025 10:01:15 -0700 Subject: [PATCH 5/6] add event listener for polling header --- src/index.js | 55 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/src/index.js b/src/index.js index 99e5989..7bd5188 100644 --- a/src/index.js +++ b/src/index.js @@ -770,20 +770,57 @@ export async function loadLazy(document, options, context) { return; } - window.addEventListener('message', (event) => { - if (event.data?.type === 'hlx:experimentation-get-config') { + window.addEventListener('message', async (event) => { + // Handle Last-Modified request + if (event.data && event.data.type === 'hlx:last-modified-request') { + const url = event.data.url; + + try { + const response = await fetch(url, { + method: 'HEAD', + cache: 'no-store', + headers: { + 'Cache-Control': 'no-cache', + }, + }); + + const lastModified = response.headers.get('Last-Modified'); + + event.source.postMessage( + { + type: 'hlx:last-modified-response', + url: url, + lastModified: lastModified, + status: response.status, + }, + event.origin + ); + } catch (error) { + console.error('Error fetching Last-Modified header:', error); + } + } + // Handle experimentation config request + else if (event.data?.type === 'hlx:experimentation-get-config') { try { const safeClone = JSON.parse(JSON.stringify(window.hlx)); - - event.source.postMessage({ - type: 'hlx:experimentation-config', - config: safeClone, - source: 'index-js' - }, '*'); + + event.source.postMessage( + { + type: 'hlx:experimentation-config', + config: safeClone, + source: 'index-js', + }, + '*' + ); } catch (e) { console.error('Error sending hlx config:', e); } - } else if (event.data?.type === 'hlx:experimentation-window-reload' && event.data?.action === 'reload') { + } + // Handle window reload request + else if ( + event.data?.type === 'hlx:experimentation-window-reload' && + event.data?.action === 'reload' + ) { window.location.reload(); } }); From b4ab4b5bdbd1f8ca96d0920689910977daca81a2 Mon Sep 17 00:00:00 2001 From: Xinyi Feng Date: Mon, 31 Mar 2025 17:27:00 -0700 Subject: [PATCH 6/6] fix lint and event listener --- src/index.js | 58 +++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/src/index.js b/src/index.js index 7bd5188..b5819b5 100644 --- a/src/index.js +++ b/src/index.js @@ -31,6 +31,18 @@ export const DEFAULT_OPTIONS = { experimentsQueryParameter: 'experiment', }; +/** + * Converts a given comma-seperate string to an array. + * @param {String|String[]} str The string to convert + * @returns an array representing the converted string + */ +export function stringToArray(str) { + if (Array.isArray(str)) { + return str; + } + return str ? str.split(/[,\n]/).filter((s) => s.trim()) : []; +} + /** * Triggers the callback when the page is actually activated, * This is to properly handle speculative page prerendering and marketing events. @@ -263,10 +275,9 @@ function getConfigForInstantExperiment( const splitString = context.getMetadata(`${pluginOptions.experimentsMetaTag}-split`); const splits = splitString - ? // custom split - (() => { - const splitValues = stringToArray(metadata.split).map( - (i) => parseFloat(i) / 100 + ? (() => { + const splitValues = stringToArray(splitString).map( + (i) => parseFloat(i) / 100, ); // If fewer splits than pages, pad with zeros @@ -283,9 +294,7 @@ function getConfigForInstantExperiment( } return splitValues; - })() - : // even split - [...new Array(pages.length)].map(() => 1 / (pages.length + 1)); + })() : [...new Array(pages.length)].map(() => 1 / (pages.length + 1)); config.variantNames.push('control'); config.variants.control = { @@ -755,11 +764,7 @@ export async function loadEager(document, options, context) { } } -export async function loadLazy(document, options, context) { - // const pluginOptions = { - // ...DEFAULT_OPTIONS, - // ...(options || {}), - // }; +export async function loadLazy(options) { // do not show the experimentation pill on prod domains if (window.location.hostname.endsWith('.live') || (typeof options.isProd === 'function' && options.isProd()) @@ -771,9 +776,8 @@ export async function loadLazy(document, options, context) { } window.addEventListener('message', async (event) => { - // Handle Last-Modified request if (event.data && event.data.type === 'hlx:last-modified-request') { - const url = event.data.url; + const { url } = event.data; try { const response = await fetch(url, { @@ -789,18 +793,17 @@ export async function loadLazy(document, options, context) { event.source.postMessage( { type: 'hlx:last-modified-response', - url: url, - lastModified: lastModified, + url, + lastModified, status: response.status, }, - event.origin + event.origin, ); } catch (error) { + // eslint-disable-next-line no-console console.error('Error fetching Last-Modified header:', error); } - } - // Handle experimentation config request - else if (event.data?.type === 'hlx:experimentation-get-config') { + } else if (event.data?.type === 'hlx:experimentation-get-config') { try { const safeClone = JSON.parse(JSON.stringify(window.hlx)); @@ -810,22 +813,17 @@ export async function loadLazy(document, options, context) { config: safeClone, source: 'index-js', }, - '*' + '*', ); } catch (e) { + // eslint-disable-next-line no-console console.error('Error sending hlx config:', e); } - } - // Handle window reload request - else if ( - event.data?.type === 'hlx:experimentation-window-reload' && - event.data?.action === 'reload' + } else if ( + event.data?.type === 'hlx:experimentation-window-reload' + && event.data?.action === 'reload' ) { window.location.reload(); } }); - - // eslint-disable-next-line import/no-cycle - // const preview = await import('./preview.js'); - // preview.default(document, pluginOptions, { ...context, getResolvedAudiences }); }