perf(core): replace `lazysizes` with browser-level lazy loading (#1267)

This commit is contained in:
Cotes Chung 2023-09-27 04:44:32 +08:00 committed by GitHub
parent 5015fdecf3
commit bf3a34d054
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 171 additions and 226 deletions

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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 }}">

View File

@ -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 -->

View File

@ -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 ' %}
{% else %}
{% assign _left = _left | append: ' class="lazyload"' %}
{% endif %}
<!-- add image placeholder -->
{% if _lqip %}
{% assign _left = _left | 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' %}
{% if _lqip contains ':' %}
{% assign _lazyload = false %}
{% else %}
{% assign _lqip_alt = 'lqip="' | append: _path_prefix %}
{% assign _left = _left | replace: 'lqip="', _lqip_alt %}
{% endif %}
<!-- add image placeholder -->
{% assign _left = _left | replace: 'src=', 'data-src=' | replace: ' lqip=', ' data-lqip="true" src=' %}
{% else %}
{% assign _class = _class | append: ' shimmer' %}
{% 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 %}

View File

@ -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();

View File

@ -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));
}
});
}

View 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');
});
}
}

View File

@ -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';

View File

@ -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();

View File

@ -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();

View File

@ -1,6 +1,5 @@
---
layout: compress
# Default layout
---
<!doctype html>

View File

@ -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,56 +58,61 @@ 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="card-body d-flex flex-column">
<h1 class="card-title my-2 mt-md-0">{{ post.title }}</h1>
<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">
<p>
{% include no-linenos.html content=post.content %}
{{ content | markdownify | strip_html | truncate: 200 | escape }}
</p>
</div>
<div class="post-meta flex-grow-1 d-flex align-items-end">
<div class="me-auto">
<!-- posted date -->
<i class="far fa-calendar fa-fw me-1"></i>
{% include datetime.html date=post.date lang=lang %}
<!-- categories -->
{% if post.categories.size > 0 %}
<i class="far fa-folder-open fa-fw me-1"></i>
<span class="categories">
{% for category in post.categories %}
{{ category }}
{%- unless forloop.last -%},{%- endunless -%}
{% endfor %}
</span>
{% endif %}
<div class="card-text content mt-0 mb-3">
<p>
{% include no-linenos.html content=post.content %}
{{ content | markdownify | strip_html | truncate: 200 | escape }}
</p>
</div>
{% if post.pin %}
<div class="pin ms-1">
<i class="fas fa-thumbtack fa-fw"></i>
<span>{{ site.data.locales[lang].post.pin_prompt }}</span>
<div class="post-meta flex-grow-1 d-flex align-items-end">
<div class="me-auto">
<!-- posted date -->
<i class="far fa-calendar fa-fw me-1"></i>
{% include datetime.html date=post.date lang=lang %}
<!-- categories -->
{% if post.categories.size > 0 %}
<i class="far fa-folder-open fa-fw me-1"></i>
<span class="categories">
{% for category in post.categories %}
{{ category }}
{%- unless forloop.last -%},{%- endunless -%}
{% endfor %}
</span>
{% endif %}
</div>
{% endif %}
{% if post.pin %}
<div class="pin ms-1">
<i class="fas fa-thumbtack fa-fw"></i>
<span>{{ site.data.locales[lang].post.pin_prompt }}</span>
</div>
{% endif %}
</div>
<!-- .post-meta -->
</div>
<!-- .post-meta -->
<!-- .card-body -->
</div>
<!-- .card-body -->
</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 %}

View File

@ -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);
}
}
&[data-lqip='true'] {
$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 {

View File

@ -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) {
%img-radius {
border-radius: 0 $base-radius $base-radius 0;
}
#post-list {
%img-radius {
border-radius: 0 $base-radius $base-radius 0;
}
.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 {

View File

@ -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