From d493f36749a90dc02a5406a95cc1ef327b5d9304 Mon Sep 17 00:00:00 2001 From: bc-marco <109162781+bc-marco@users.noreply.github.com> Date: Tue, 7 Mar 2023 12:45:08 -0600 Subject: [PATCH] feat: implement lazy loading in app (#152) * feat: implement lazy loading in app * fix: remove unnecesary x at the end * fix: move polyfill functions outside validation * fix: cancel request inmediatly an event ocurrs * fix: simplify lazy loading approach * fix: define function type --- apps/storefront/index.html | 2 +- apps/storefront/src/index.d.ts | 1 + apps/storefront/src/load-functions.ts | 56 +++++++++++++++++++ apps/storefront/src/main.ts | 19 +++++++ .../src/{main.tsx => react-setup.tsx} | 0 packages/hooks/useB3AppOpen.ts | 1 + 6 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 apps/storefront/src/load-functions.ts create mode 100644 apps/storefront/src/main.ts rename apps/storefront/src/{main.tsx => react-setup.tsx} (100%) diff --git a/apps/storefront/index.html b/apps/storefront/index.html index b1c8af70..a151fbfb 100644 --- a/apps/storefront/index.html +++ b/apps/storefront/index.html @@ -628,6 +628,6 @@

Ugly Cornerstone Store Theme with Weird CSS

Vue.createApp(Headless).mount('#headless-container') - + diff --git a/apps/storefront/src/index.d.ts b/apps/storefront/src/index.d.ts index 33383437..16dd101f 100644 --- a/apps/storefront/src/index.d.ts +++ b/apps/storefront/src/index.d.ts @@ -10,4 +10,5 @@ declare interface CustomFieldStringItems { declare interface Window { tipDispatch: DispatchProps b3Tipmessage: any + b2bStorefrontApp: any } diff --git a/apps/storefront/src/load-functions.ts b/apps/storefront/src/load-functions.ts new file mode 100644 index 00000000..a3f706b5 --- /dev/null +++ b/apps/storefront/src/load-functions.ts @@ -0,0 +1,56 @@ +import globalB3 from '@b3/global-b3' + +export const requestIdleCallbackFunction: typeof window.requestIdleCallback = window.requestIdleCallback ? window.requestIdleCallback : (cb: IdleRequestCallback) => { + const start = Date.now() + return window.setTimeout(() => { + cb({ + didTimeout: false, + timeRemaining() { + return Math.max(0, 50 - (Date.now() - start)) + }, + }) + }, 1) +} + +window.b2bStorefrontApp = { + /* init flag listener */ + __isInitVariable: false, + __isInitListener: () => {}, + set __isInit(value: boolean) { + this.__isInitVariable = value + this.__isInitListener(value) + }, + get __isInit() { + return this.__isInitVariable + }, + registerIsInitListener(listener: Function) { + this.__isInitListener = listener + }, + + // helper variable to save clicked link + clickedLinkElement: undefined, +} + +export const initApp = async () => { + if (window.b2bStorefrontApp.__isInit) return + + await import('./react-setup') +} + +const clickLink = async (e: MouseEvent) => { + window.b2bStorefrontApp.clickedLinkElement = e.target + e.preventDefault() + e.stopPropagation() + await initApp() +} + +export const bindLinks = () => { + const links:NodeListOf = document.querySelectorAll(`${globalB3['dom.registerElement']}, ${globalB3['dom.allOtherElement']}`) + + links.forEach((accessLink) => accessLink.addEventListener('click', clickLink)) +} +export const unbindLinks = () => { + const links:NodeListOf = document.querySelectorAll(`${globalB3['dom.registerElement']}, ${globalB3['dom.allOtherElement']}`) + + links.forEach((accessLink) => accessLink.removeEventListener('click', clickLink)) +} diff --git a/apps/storefront/src/main.ts b/apps/storefront/src/main.ts new file mode 100644 index 00000000..e5db858c --- /dev/null +++ b/apps/storefront/src/main.ts @@ -0,0 +1,19 @@ +import { + bindLinks, initApp, requestIdleCallbackFunction, unbindLinks, +} from './load-functions' + +// check if the accesed url contains a hashtag +if (window.location.hash.startsWith('#/')) { + initApp() +} else { + // load the app when the browser is free + requestIdleCallbackFunction(initApp) + // and bind links to load the app + bindLinks() + window.addEventListener('beforeunload', unbindLinks) + // and observe global flag to simulate click + window.b2bStorefrontApp.registerIsInitListener(() => { + unbindLinks() + setTimeout(() => window.b2bStorefrontApp.clickedLinkElement?.click(), 0) + }) +} diff --git a/apps/storefront/src/main.tsx b/apps/storefront/src/react-setup.tsx similarity index 100% rename from apps/storefront/src/main.tsx rename to apps/storefront/src/react-setup.tsx diff --git a/packages/hooks/useB3AppOpen.ts b/packages/hooks/useB3AppOpen.ts index 61e8459d..d8355e8e 100644 --- a/packages/hooks/useB3AppOpen.ts +++ b/packages/hooks/useB3AppOpen.ts @@ -64,6 +64,7 @@ export const useB3AppOpen = (initOpenState: OpenPageState) => { } return false } + window.b2bStorefrontApp.__isInit = true window.addEventListener('click', handleTriggerClick, { capture: true, })