perf(core): replace lazysizes
with browser-level lazy loading (#1267)
This commit is contained in:
parent
5015fdecf3
commit
bf3a34d054
19 changed files with 171 additions and 226 deletions
|
@ -35,8 +35,9 @@ magnific-popup:
|
|||
css: /assets/lib/magnific-popup/magnific-popup.css
|
||||
js: /assets/lib/magnific-popup/jquery.magnific-popup.min.js
|
||||
|
||||
lazysizes:
|
||||
js: /assets/lib/lazysizes/lazysizes.min.js
|
||||
lazy-polyfill:
|
||||
css: /assets/lib/loading-attribute-polyfill/loading-attribute-polyfill.min.css
|
||||
js: /assets/lib/loading-attribute-polyfill/loading-attribute-polyfill.umd.min.js
|
||||
|
||||
clipboard:
|
||||
js: /assets/lib/clipboard/clipboard.min.js
|
||||
|
|
|
@ -46,8 +46,9 @@ magnific-popup:
|
|||
css: https://cdn.jsdelivr.net/npm/magnific-popup@1.1.0/dist/magnific-popup.min.css
|
||||
js: https://cdn.jsdelivr.net/npm/magnific-popup@1.1.0/dist/jquery.magnific-popup.min.js
|
||||
|
||||
lazysizes:
|
||||
js: https://cdn.jsdelivr.net/npm/lazysizes@5.3.2/lazysizes.min.js
|
||||
lazy-polyfill:
|
||||
css: https://cdn.jsdelivr.net/npm/loading-attribute-polyfill@2.1.1/dist/loading-attribute-polyfill.min.css
|
||||
js: https://cdn.jsdelivr.net/npm/loading-attribute-polyfill@2.1.1/dist/loading-attribute-polyfill.umd.min.js
|
||||
|
||||
clipboard:
|
||||
js: https://cdn.jsdelivr.net/npm/clipboard@2.0.11/dist/clipboard.min.js
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
<iframe class="embed-video twitch lazyload"
|
||||
<iframe
|
||||
class="embed-video twitch"
|
||||
src="https://player.twitch.tv/?video={{ include.id }}&parent={{ site.url | split: '://' | last | remove: '/' }}"
|
||||
frameborder="0" allowfullscreen="true"
|
||||
scrolling="no"></iframe>
|
||||
frameborder="0"
|
||||
allowfullscreen="true"
|
||||
scrolling="no"
|
||||
></iframe>
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
<iframe class="embed-video youtube lazyload"
|
||||
<iframe
|
||||
class="embed-video youtube"
|
||||
loading="lazy"
|
||||
src="https://www.youtube.com/embed/{{ include.id }}"
|
||||
title="YouTube video player"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowfullscreen></iframe>
|
||||
allowfullscreen
|
||||
></iframe>
|
||||
|
|
|
@ -80,6 +80,10 @@
|
|||
<link rel="stylesheet" href="{{ site.data.origin[type].toc.css | relative_url }}">
|
||||
{% endif %}
|
||||
|
||||
{% if page.layout == 'post' or page.layout == 'page' or page.layout == 'home' %}
|
||||
<link rel="stylesheet" href="{{ site.data.origin[type]['lazy-polyfill'].css | relative_url }}">
|
||||
{% endif %}
|
||||
|
||||
{% if page.layout == 'page' or page.layout == 'post' %}
|
||||
<!-- Manific Popup -->
|
||||
<link rel="stylesheet" href="{{ site.data.origin[type].magnific-popup.css | relative_url }}">
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<!-- layout specified -->
|
||||
|
||||
{% if page.layout == 'post' or page.layout == 'page' or page.layout == 'home' %}
|
||||
{% assign urls = urls | append: ',' | append: site.data.origin[type].lazysizes.js %}
|
||||
{% assign urls = urls | append: ',' | append: site.data.origin[type]['lazy-polyfill'].js %}
|
||||
|
||||
{% unless page.layout == 'home' %}
|
||||
<!-- image lazy-loading & popup & clipboard -->
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
{% endif %}
|
||||
|
||||
<!-- Change the icon of checkbox -->
|
||||
|
||||
{% if _content contains '<input type="checkbox"' %}
|
||||
{% assign _content = _content
|
||||
| replace: '<input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />',
|
||||
|
@ -39,7 +40,8 @@
|
|||
%}
|
||||
{% endif %}
|
||||
|
||||
<!-- images -->
|
||||
<!-- Handle images -->
|
||||
|
||||
{% assign IMG_TAG = '<img ' %}
|
||||
|
||||
{% if _content contains IMG_TAG %}
|
||||
|
@ -79,8 +81,6 @@
|
|||
{% assign _left = _left | remove: ' /' | replace: ' w=', ' width=' | replace: ' h=', ' height=' %}
|
||||
{% assign _attrs = _left | split: '" ' %}
|
||||
|
||||
{% assign _width = null %}
|
||||
{% assign _height = null %}
|
||||
{% assign _lqip = null %}
|
||||
{% assign _class = null %}
|
||||
|
||||
|
@ -94,10 +94,6 @@
|
|||
{% capture _value %}{{ _pair | last | remove: '"' }}{% endcapture %}
|
||||
|
||||
{% case _key %}
|
||||
{% when 'width' %}
|
||||
{% assign _width = _value %}
|
||||
{% when 'height' %}
|
||||
{% assign _height = _value %}
|
||||
{% when 'src' %}
|
||||
{% assign _src = _value %}
|
||||
{% when 'lqip' %}
|
||||
|
@ -114,47 +110,33 @@
|
|||
{% endif %}
|
||||
|
||||
{% assign _final_src = null %}
|
||||
{% assign _lazyload = true %}
|
||||
|
||||
{% unless _src contains '//' %}
|
||||
{% assign _final_src = _path_prefix | append: _src %}
|
||||
{% capture _src_from %}"{{ _src }}"{% endcapture %}
|
||||
{% capture _src_to %}"{{ _final_src }}"{% endcapture %}
|
||||
{% assign _left = _left | replace: _src_from, _src_to %}
|
||||
{% assign _src_alt = 'src="' | append: _path_prefix %}
|
||||
{% assign _left = _left | replace: 'src="', _src_alt %}
|
||||
{% endunless %}
|
||||
|
||||
{% if _lqip %}
|
||||
{% unless _lqip contains ':' %}
|
||||
{% assign _final_lqip = _path_prefix | append: _lqip %}
|
||||
{% capture _lqip_from %}"{{ _lqip }}"{% endcapture %}
|
||||
{% capture _lqip_to %}"{{ _final_lqip }}"{% endcapture %}
|
||||
{% assign _left = _left | replace: _lqip_from, _lqip_to %}
|
||||
{% endunless %}
|
||||
{% endif %}
|
||||
|
||||
<!-- lazy-load images <https://github.com/aFarkas/lazysizes#readme> -->
|
||||
{% assign _left = _left | replace: 'src=', 'data-src=' %}
|
||||
{% if _left contains 'class=' %}
|
||||
{% assign _left = _left | replace: 'class="', 'class="lazyload ' %}
|
||||
{% if _lqip contains ':' %}
|
||||
{% assign _lazyload = false %}
|
||||
{% else %}
|
||||
{% assign _left = _left | append: ' class="lazyload"' %}
|
||||
{% assign _lqip_alt = 'lqip="' | append: _path_prefix %}
|
||||
{% assign _left = _left | replace: 'lqip="', _lqip_alt %}
|
||||
{% endif %}
|
||||
|
||||
<!-- add image placeholder -->
|
||||
{% if _lqip %}
|
||||
{% assign _left = _left | replace: ' lqip=', ' data-lqip="true" src=' %}
|
||||
{% assign _left = _left | replace: 'src=', 'data-src=' | replace: ' lqip=', ' data-lqip="true" src=' %}
|
||||
|
||||
{% else %}
|
||||
{% if _width and _height %}
|
||||
<!-- add SVG placehoder -->
|
||||
{%- capture _svg -%}
|
||||
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 {{ _width }} {{ _height }}'%3E%3C/svg%3E"
|
||||
{%- endcapture -%}
|
||||
{% assign _left = _svg | append: ' ' | append: _left %}
|
||||
{% assign _class = _class | append: ' shimmer' %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<!-- Bypass the HTML-proofer test -->
|
||||
{% assign _left = _left | append: ' data-proofer-ignore' %}
|
||||
<!-- lazy-load images -->
|
||||
{% if _lazyload %}
|
||||
{% assign _left = _left | append: ' loading="lazy"' %}
|
||||
{% endif %}
|
||||
|
||||
{% if page.layout == 'home' %}
|
||||
<!-- create the image wrapper -->
|
||||
|
@ -174,6 +156,7 @@
|
|||
class="img-link{% unless _lqip %} shimmer{% endunless %}"
|
||||
{% endcapture %}
|
||||
{% assign _img_content = _img_content | slice: 0, _size | append: _class | append: '>' %}
|
||||
|
||||
{% else %}
|
||||
<!-- create the image wrapper -->
|
||||
{% assign _wrapper_start = _final_src
|
||||
|
@ -185,12 +168,12 @@
|
|||
%}
|
||||
|
||||
{% assign _img_content = _img_content | append: _wrapper_start %}
|
||||
{% assign _right = _right | prepend: '></a' %}
|
||||
{% assign _right = '></a' | append: _right %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<!-- combine -->
|
||||
{% assign _img_content = _img_content | append: debug | append: IMG_TAG | append: _left | append: _right %}
|
||||
{% assign _img_content = _img_content | append: IMG_TAG | append: _left | append: _right %}
|
||||
{% endfor %}
|
||||
|
||||
{% if _img_content %}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { basic, initSidebar, initTopbar } from './modules/layouts';
|
||||
import { initLocaleDatetime, imgLazy } from './modules/plugins';
|
||||
import { initLocaleDatetime, loadImg } from './modules/plugins';
|
||||
|
||||
basic();
|
||||
initSidebar();
|
||||
initTopbar();
|
||||
initLocaleDatetime();
|
||||
imgLazy();
|
||||
loadImg();
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
/**
|
||||
* Set up image lazy-load
|
||||
*/
|
||||
|
||||
function stopShimmer($node) {
|
||||
$node.parent().removeClass('shimmer');
|
||||
}
|
||||
|
||||
export function imgLazy() {
|
||||
const $images = $('main img[data-src]');
|
||||
|
||||
if ($images.length <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Stop shimmer when image loaded */
|
||||
document.addEventListener('lazyloaded', function (e) {
|
||||
stopShimmer($(e.target));
|
||||
});
|
||||
|
||||
/* Stop shimmer from cached images */
|
||||
$images.each(function () {
|
||||
if ($(this).hasClass('ls-is-cached')) {
|
||||
stopShimmer($(this));
|
||||
}
|
||||
});
|
||||
}
|
31
_javascript/modules/components/img-loading.js
Normal file
31
_javascript/modules/components/img-loading.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* Setting up image lazy loading and LQIP switching
|
||||
*/
|
||||
|
||||
export function loadImg() {
|
||||
const $images = $('main img[loading="lazy"]');
|
||||
const $lqip = $('main img[data-lqip="true"]');
|
||||
|
||||
if ($images.length > 0) {
|
||||
$images.on('load', function () {
|
||||
/* Stop shimmer when image loaded */
|
||||
$(this).parent().removeClass('shimmer');
|
||||
});
|
||||
|
||||
$images.each(function () {
|
||||
/* Images loaded from the browser cache do not trigger the 'load' event */
|
||||
if ($(this).prop('complete')) {
|
||||
$(this).parent().removeClass('shimmer');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if ($lqip.length > 0) {
|
||||
$lqip.each(function () {
|
||||
/* Switch LQIP with real image url */
|
||||
const dataSrc = $(this).attr('data-src');
|
||||
$(this).attr('src', encodeURI(dataSrc));
|
||||
$(this).removeAttr('data-src data-lqip');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
export { categoryCollapse } from './components/category-collapse';
|
||||
export { initClipboard } from './components/clipboard';
|
||||
export { imgLazy } from './components/img-lazyload';
|
||||
export { loadImg } from './components/img-loading';
|
||||
export { imgPopup } from './components/img-popup';
|
||||
export { initLocaleDatetime } from './components/locale-datetime';
|
||||
export { toc } from './components/toc';
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { basic, initSidebar, initTopbar } from './modules/layouts';
|
||||
import { imgLazy, imgPopup, initClipboard } from './modules/plugins';
|
||||
import { loadImg, imgPopup, initClipboard } from './modules/plugins';
|
||||
|
||||
basic();
|
||||
initSidebar();
|
||||
initTopbar();
|
||||
imgLazy();
|
||||
loadImg();
|
||||
imgPopup();
|
||||
initClipboard();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { basic, initSidebar, initTopbar } from './modules/layouts';
|
||||
import {
|
||||
imgLazy,
|
||||
loadImg,
|
||||
imgPopup,
|
||||
initLocaleDatetime,
|
||||
initClipboard,
|
||||
|
@ -10,7 +10,7 @@ import {
|
|||
basic();
|
||||
initSidebar();
|
||||
initTopbar();
|
||||
imgLazy();
|
||||
loadImg();
|
||||
imgPopup();
|
||||
initLocaleDatetime();
|
||||
initClipboard();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
---
|
||||
layout: compress
|
||||
# Default layout
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
|
|
|
@ -39,10 +39,13 @@ layout: default
|
|||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% capture content %}
|
||||
{% capture _content %}
|
||||
<div id="post-list" class="flex-grow-1 pe-xl-2">
|
||||
{% for post in posts %}
|
||||
<article class="card-wrapper">
|
||||
<a href="{{ post.url | relative_url }}" class="card post-preview flex-md-row-reverse">
|
||||
<article class="card-wrapper card">
|
||||
<a href="{{ post.url | relative_url }}" class="post-preview row g-0 flex-md-row-reverse">
|
||||
{% assign card_body_col = '12' %}
|
||||
|
||||
{% if post.image %}
|
||||
{% if post.image.lqip %}
|
||||
{% capture lqip %}lqip="{{ post.image.lqip }}"{% endcapture %}
|
||||
|
@ -55,13 +58,18 @@ layout: default
|
|||
|
||||
{% assign alt = post.image.alt | xml_escape | default: 'Preview Image' %}
|
||||
|
||||
<img src="{{ src }}" w="17" h="10" alt="{{ alt }}" {{ lqip }}>
|
||||
<div class="col-md-5">
|
||||
<img src="{{ src }}" alt="{{ alt }}" {{ lqip }}>
|
||||
</div>
|
||||
|
||||
{% assign card_body_col = '7' %}
|
||||
{% endif %}
|
||||
|
||||
<div class="col-md-{{ card_body_col }}">
|
||||
<div class="card-body d-flex flex-column">
|
||||
<h1 class="card-title my-2 mt-md-0">{{ post.title }}</h1>
|
||||
|
||||
<div class="card-text content mt-0 mb-2">
|
||||
<div class="card-text content mt-0 mb-3">
|
||||
<p>
|
||||
{% include no-linenos.html content=post.content %}
|
||||
{{ content | markdownify | strip_html | truncate: 200 | escape }}
|
||||
|
@ -96,15 +104,15 @@ layout: default
|
|||
<!-- .post-meta -->
|
||||
</div>
|
||||
<!-- .card-body -->
|
||||
</div>
|
||||
</a>
|
||||
</article>
|
||||
{% endfor %}
|
||||
{% endcapture %}
|
||||
|
||||
<div id="post-list" class="flex-grow-1 pe-xl-2">
|
||||
{% include refactor-content.html content=content lang=lang %}
|
||||
</div>
|
||||
<!-- #post-list -->
|
||||
{% endcapture %}
|
||||
|
||||
{% include refactor-content.html content=_content lang=lang %}
|
||||
|
||||
{% if paginator.total_pages > 1 %}
|
||||
{% include post-paginator.html %}
|
||||
|
|
|
@ -71,54 +71,13 @@ a {
|
|||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
transition: all 0.35s ease-in-out;
|
||||
transition: all 0.7s ease-in-out;
|
||||
|
||||
&[data-src] {
|
||||
&[data-lqip='true'] {
|
||||
&.lazyload,
|
||||
&.lazyloading {
|
||||
-webkit-filter: blur(20px);
|
||||
filter: blur(20px);
|
||||
}
|
||||
}
|
||||
$blur: 20px;
|
||||
|
||||
&:not([data-lqip='true']) {
|
||||
&.lazyload,
|
||||
&.lazyloading {
|
||||
background: var(--img-bg);
|
||||
}
|
||||
|
||||
&.lazyloaded {
|
||||
-webkit-animation: fade-in 0.35s ease-in;
|
||||
animation: fade-in 0.35s ease-in;
|
||||
}
|
||||
}
|
||||
|
||||
&.shadow {
|
||||
-webkit-filter: drop-shadow(2px 4px 6px rgba(0, 0, 0, 0.08));
|
||||
filter: drop-shadow(2px 4px 6px rgba(0, 0, 0, 0.08));
|
||||
box-shadow: none !important; /* cover the Bootstrap 4.6.1 styles */
|
||||
}
|
||||
|
||||
@extend %img-caption;
|
||||
}
|
||||
|
||||
@-webkit-keyframes fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
-webkit-filter: blur($blur);
|
||||
filter: blur($blur);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -349,6 +308,29 @@ sup {
|
|||
|
||||
/* --- post --- */
|
||||
|
||||
.preview-img {
|
||||
aspect-ratio: 40 / 21;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
@extend %rounded;
|
||||
|
||||
&:not(.no-bg) {
|
||||
img {
|
||||
background: var(--img-bg);
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
height: 100%;
|
||||
-o-object-fit: cover;
|
||||
object-fit: cover;
|
||||
|
||||
@extend %rounded;
|
||||
}
|
||||
}
|
||||
|
||||
.post-preview {
|
||||
@extend %rounded;
|
||||
|
||||
|
@ -384,7 +366,6 @@ main {
|
|||
}
|
||||
|
||||
p {
|
||||
> img[data-src],
|
||||
> a.popup {
|
||||
&:not(.normal):not(.left):not(.right) {
|
||||
@include align-center;
|
||||
|
@ -538,8 +519,8 @@ main {
|
|||
background: var(--shimmer-bg);
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
-webkit-animation: shimmer 1s infinite;
|
||||
animation: shimmer 1s infinite;
|
||||
-webkit-animation: shimmer 1.3s infinite;
|
||||
animation: shimmer 1.3s infinite;
|
||||
}
|
||||
|
||||
@-webkit-keyframes shimmer {
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
margin-top: 2rem;
|
||||
|
||||
.card-wrapper {
|
||||
display: block;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
@ -18,27 +16,23 @@
|
|||
}
|
||||
|
||||
.card {
|
||||
border: 0;
|
||||
background: none;
|
||||
|
||||
%img-radius {
|
||||
border-radius: $base-radius $base-radius 0 0;
|
||||
}
|
||||
|
||||
.preview-img {
|
||||
height: 10rem;
|
||||
|
||||
@extend %img-radius;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
-o-object-fit: cover;
|
||||
object-fit: cover;
|
||||
|
||||
@extend %img-radius;
|
||||
}
|
||||
}
|
||||
|
||||
.card-body {
|
||||
min-height: 10.5rem;
|
||||
height: 100%;
|
||||
padding: 1rem;
|
||||
|
||||
.card-title {
|
||||
|
@ -136,20 +130,13 @@
|
|||
|
||||
/* Tablet */
|
||||
@media all and (min-width: 768px) {
|
||||
#post-list {
|
||||
%img-radius {
|
||||
border-radius: 0 $base-radius $base-radius 0;
|
||||
}
|
||||
|
||||
#post-list {
|
||||
.card {
|
||||
.preview-img {
|
||||
width: 20rem;
|
||||
height: 11.55rem; // can hold 2 lines each for title and content
|
||||
}
|
||||
|
||||
.card-body {
|
||||
min-height: 10.75rem;
|
||||
width: 60%;
|
||||
padding: 1.75rem 1.75rem 1.25rem 1.75rem;
|
||||
|
||||
.card-text {
|
||||
|
|
|
@ -26,26 +26,6 @@
|
|||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.preview-img {
|
||||
overflow: hidden;
|
||||
aspect-ratio: 40 / 21;
|
||||
|
||||
@extend %rounded;
|
||||
|
||||
&:not(.no-bg) {
|
||||
img.lazyloaded {
|
||||
background: var(--img-bg);
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
-o-object-fit: cover;
|
||||
object-fit: cover;
|
||||
|
||||
@extend %rounded;
|
||||
}
|
||||
}
|
||||
|
||||
h1 + .post-meta {
|
||||
> span + span::before {
|
||||
@include dot;
|
||||
|
@ -368,10 +348,6 @@ h1 + .post-meta {
|
|||
}
|
||||
|
||||
@media all and (max-width: 576px) {
|
||||
.preview-img[data-src] {
|
||||
margin-top: 2.2rem;
|
||||
}
|
||||
|
||||
.post-tail-bottom {
|
||||
flex-wrap: wrap-reverse !important;
|
||||
|
||||
|
@ -396,9 +372,4 @@ h1 + .post-meta {
|
|||
margin-left: -0.5rem;
|
||||
margin-right: -0.5rem;
|
||||
}
|
||||
|
||||
.preview-img[data-src] {
|
||||
max-width: 100vw;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 6737eab720e4cdd8330d32053053356f200d8819
|
||||
Subproject commit f80ba2f1616496cba34f3fd3eef1564d8fa843cd
|
Loading…
Reference in a new issue