Ленивая загрузка JS (HTML код)
<h1>
Lazy loading JS by visibility
</h1>
<p>
Here’s a neat trick.
</p>
<p>
<a href="https://twitter.com/FredKSchott">Fred K. Schott</a>
gives an impressive presentation of
<a href="https://www.youtube.com/watch?v=mgkwZqVkrwo">Astro</a>,
a framework-agnostic architecture for building web sites and web apps.
</p>
<iframe
title="YouTube video player"
width="560"
height="315"
src="https://www.youtube-nocookie.com/embed/mgkwZqVkrwo?rel=0&controls=0&fs=0&start=2356&end=2373"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
></iframe>
<blockquote>
<p>
We add a script to the end of your page.
It’s inline. It essentially runs almost immediately,
and that is what is going to create that
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API">Intersection Observer</a>.
It’s going to do a dynamic import of the things that you need,
and it’s going to call React render on that component.
</p>
</blockquote>
<p>
During the presentation, Fred demonstrates dynamically loading JS using
<a href="https://jasonformat.com/islands-architecture/">"Islands Architecture"</a>,
a strategy
where small HTML placeholders are progressively upgraded with dynamic or interactive content as-needed.
</p>
<p>
The demonstration involves
waiting on the viewport visibility of a <code>div</code> placeholder before loading some JS.
</p>
<p>
The entire setup contributes less than 200 bytes to the page when gzipped.
</p>
<pre><code><div data-astro-id="3459833264469372"></div>
<script type="module">
<b -com>/* scaffolding put before the code */</b>
<mark>((o=new IntersectionObserver((([{isIntersecting,target}])=>{isIntersecting&&(o.disconnect(),</mark>
<b -com>/* code run when the section is visible */</b>
<b -var>Promise</b>.<b -ent>all</b>([
<b -key>import</b>(<b -str>'https://cdn.skypack.dev/react'</b>),
<b -key>import</b>(<b -str>'https://cdn.skypack.dev/react-dom'</b>),
]).<b -ent>then</b>( ([
{ <b -con>default</b>: <b -var>React</b> },
{ <b -con>default</b>: <b -var>ReactDOM</b> },
]) => <b -var>ReactDOM</b>.<b -ent>render</b>(
<b -var>React</b>.<b -ent>createElement</b>(<b -str>'strong'</b>, {},
<b -str>'This was rendered with React!'</b>,
),
<b -ent>target</b>,
) )
<b -com>/* scaffolding put after the code */</b>
<mark>)})))=>{o.observe(document.querySelector('[data-astro-id="3459833264469372"]'))})()</mark>
</script></code></pre>
<p>
Neat trick, right?
</p>
<p>
It can be used once, or multiple times in different places.
JS can be loaded by <a href="https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/observe">element visibility</a>,
a <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia">media query</a>,
a <a href="https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/observe">container query</a>,
any <a href="https://developer.mozilla.org/en-US/docs/Web/Events">event</a>,
any <a href="https://developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver/observe">asset</a>,
any <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback">idle period</a>,
or any mix of these,
and any other condition that’s helpful.
</p>
<p>
Below is a live demonstration.
</p>
<p style="margin:25vh 0">👇</p>
<div data-astro-id="3459833264469372"> </div>
<script type="module">
((
o = new IntersectionObserver(
([{ isIntersecting, target }]) => {
if (isIntersecting) {
o.disconnect()
Promise.all([
import('https://cdn.skypack.dev/react'),
import('https://cdn.skypack.dev/react-dom')
]).then(
([{ default: React }, { default: ReactDOM }]) => ReactDOM.render(
React.createElement('strong', {},
'This was rendered with React!'
),
target
)
)
}
}
),
f = document.createDocumentFragment(),
) => o.observe(
document.querySelector('[data-astro-id="3459833264469372"]')
))()
</script>
<p style="margin:25vh 0">👆</p>
<p>
Above is a live demonstration.
</p>
<hr />
<p>
That’s all.
</p>
<p>
It just seems like a neat trick.
</p>
Ленивая загрузка JS (CSS код)
* {
box-sizing: border-box;
}
body {
align-items: center;
display: flex;
font: 125%/1.5 system-ui, -apple-system;
flex-flow: column wrap;
margin: 1em 1em 4em;
overflow-wrap: anywhere;
tab-size: 2;
-webkit-text-size-adjust: none;
}
body > * {
max-width: 34rem;
}
blockquote {
box-shadow: inset .75em 0 0 #039be5;
font: italic 125%/1.5 Roboto, serif;
margin-inline-start: 0;
padding-left: 2em;
}
@media (max-width: 640px) {
blockquote {
box-shadow: inset .5em 0 0 #039be5;
}
}
pre, code {
font: 85%/inherit SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
}
pre, p code {
background: #f6f8fa;
border-radius: 6px;
}
p code {
padding: .25em .365em;
}
pre {
display: flex;
padding: 1em;
overflow: scroll;
max-width: 100%;
}
pre > code {
display: block;
min-width: 60em;
}
pre b {
font-weight: normal;
}
iframe {
border: 0;
width: 100%;
}
strong {
background-color: #84ff6f;
border-radius: 1em;
padding: 1em;
}
hr {
background:
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 150 640 80'%3E%3Cpath d='M130 192c6-7 4-18 0-21-9-6-17 6-13 18 4 13 14 21 28 24 29 5 88-27 126-37 27-8 44 3 54 16-19-14-36-9-54-6-41 8-82 40-127 35-21-3-35-24-34-40l1-4c3-10 7-14 12-15 11-3 23 18 7 30z' /%3E%3Cpath d='M120 199c-8-7-16-18-24-23-79-53-120 18-79 39 6 3 19 5 28-8-11 9-24 6-29 1-14-12-9-29 7-36 26-10 49 0 70 15 14 9 18 13 30 18-7 0-3-8-10-13l7 7zM487 190c-6 8-4 19 1 22 9 6 18-6 14-18-5-13-15-22-30-24-31-6-94 27-134 37-29 7-47-4-57-16 20 13 38 9 57 5 43-7 87-39 134-34 22 3 38 24 37 40l-1 4c-3 10-8 14-13 15-12 3-24-18-8-31z' /%3E%3Cpath d='M497 179c9 8 18 19 26 24 83 52 126-18 83-39-7-3-20-5-30 8 12-9 25-6 31-1 14 11 9 28-8 36-27 10-52-1-73-15-15-9-19-13-32-18 7 0 4 8 10 12l-7-7z' /%3E%3C/svg%3E") 0
/ 100% auto no-repeat
;
border: 0;
height: 5em;
margin-block-end: 3em;
margin-block-start: 3em;
width: 100%;
}
[-var] { color: #e36209; }
[-ent] { color: #6f42c1; }
[-key] { color: #d73a49; }
[-str] { color: #136203; }
[-con] { color: #005cc5; }
[-com] { color: #6a737d; }
Ленивая загрузка JS (Результат кода)
Comments