alpine-lazy-load-assets
Version:
Alpine.js directive to lazy load css and js assets
2 lines (1 loc) • 2.57 kB
JavaScript
(()=>{function m(c){c.store("lazyLoadedAssets",{loaded:new Set,check(e){return Array.isArray(e)?e.every(t=>this.loaded.has(t)):this.loaded.has(e)},markLoaded(e){Array.isArray(e)?e.forEach(t=>this.loaded.add(t)):this.loaded.add(e)}});let u=e=>new CustomEvent(e,{bubbles:!0,composed:!0,cancelable:!0}),b=(e,t={},s,n)=>{let a=document.createElement(e);return Object.entries(t).forEach(([o,r])=>a[o]=r),s&&(n?s.insertBefore(a,n):s.appendChild(a)),a},f=(e,t,s={},n=null,a=null)=>{let o=e==="link"?`link[href="${t}"]`:`script[src="${t}"]`;if(document.querySelector(o)||c.store("lazyLoadedAssets").check(t))return Promise.resolve();let r=e==="link"?{...s,href:t}:{...s,src:t},d=b(e,r,n,a);return new Promise((l,i)=>{d.onload=()=>{c.store("lazyLoadedAssets").markLoaded(t),l()},d.onerror=()=>{i(new Error(`Failed to load ${e}: ${t}`))}})},h=async(e,t,s=null,n=null)=>{let a={type:"text/css",rel:"stylesheet"};t&&(a.media=t);let o=document.head,r=null;if(s&&n){let d=document.querySelector(`link[href*="${n}"]`);d?(o=d.parentElement,r=s==="before"?d:d.nextSibling):(console.warn(`Target (${n}) not found for ${e}. Appending to head.`),o=document.head,r=null)}await f("link",e,a,o,r)},y=async(e,t,s=null,n=null,a=null)=>{let o=document.head,r=null;if(s&&n){let l=document.querySelector(`script[src*="${n}"]`);l?(o=l.parentElement,r=s==="before"?l:l.nextSibling):(console.warn(`Target (${n}) not found for ${e}. Falling back to head or body.`),o=document.head,r=null)}else(t.has("body-start")||t.has("body-end"))&&(o=document.body,t.has("body-start")&&(r=document.body.firstChild));let d={};a&&(d.type="module"),await f("script",e,d,o,r)};c.directive("load-css",(e,{expression:t},{evaluate:s})=>{let n=s(t),a=e.media,o=e.getAttribute("data-dispatch"),r=e.getAttribute("data-css-before")?"before":e.getAttribute("data-css-after")?"after":null,d=e.getAttribute("data-css-before")||e.getAttribute("data-css-after")||null;Promise.all(n.map(l=>h(l,a,r,d))).then(()=>{o&&window.dispatchEvent(u(`${o}-css`))}).catch(console.error)}),c.directive("load-js",(e,{expression:t,modifiers:s},{evaluate:n})=>{let a=n(t),o=new Set(s),r=e.getAttribute("data-js-before")?"before":e.getAttribute("data-js-after")?"after":null,d=e.getAttribute("data-js-before")||e.getAttribute("data-js-after")||null,l=e.getAttribute("data-js-as-module")||e.getAttribute("data-as-module")||!1,i=e.getAttribute("data-dispatch");Promise.all(a.map(A=>y(A,o,r,d,l))).then(()=>{i&&window.dispatchEvent(u(`${i}-js`))}).catch(console.error)})}document.addEventListener("alpine:initializing",()=>{m(window.Alpine)});})();