Skip to content

Commit c505e93

Browse files
committed
perf(lighthouse): 第一轮性能优化
- 移除重复的 OG meta 标签(减少 HTML 大小) - 修复 og:image URL 拼接错误 - 移除过时的 FastClick.js(现代浏览器不需要) - 精简 preconnect 指令(移除未使用的资源提示) - 添加 WebP 格式的背景图片
1 parent fbcdc10 commit c505e93

File tree

4 files changed

+208
-240
lines changed

4 files changed

+208
-240
lines changed

_includes/footer.html

Lines changed: 176 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
</footer>
1919

2020
<!-- Critical JavaScript - Load Immediately via CDN with local fallback -->
21-
<script defer src="https://cdn.jsdelivr.net/npm/jquery@3.6.4/dist/jquery.min.js"
22-
integrity="sha256-oP6HI9z1XaZNBrJURtCoUT5SUnxFr8s3BzRl+cbzUq8="
23-
crossorigin="anonymous"></script>
21+
<script defer src="https://cdn.jsdelivr.net/npm/jquery@3.6.4/dist/jquery.min.js"
22+
integrity="sha256-oP6HI9z1XaZNBrJURtCoUT5SUnxFr8s3BzRl+cbzUq8="
23+
crossorigin="anonymous"></script>
2424
<script>window.jQuery || document.write('<script src="{{ "/js/jquery.min.js" | prepend: site.baseurl }}"><\/script>')</script>
2525

2626
<!-- Critical: Language Toggle Event Delegation (Must load before user interaction) -->
@@ -55,182 +55,182 @@
5555
});
5656
</script>
5757

58-
<!-- Non-Critical JavaScript - Load Asynchronously -->
59-
<script>
60-
function loadScript(src, callback) {
61-
var script = document.createElement('script');
62-
script.src = src;
63-
script.async = true;
64-
if (callback) script.onload = callback;
65-
document.head.appendChild(script);
66-
}
67-
68-
window.addEventListener('load', function() {
69-
// Defer non-critical bundles
70-
loadScript('{{ "/js/bootstrap.min.js" | prepend: site.baseurl }}');
71-
loadScript('{{ "/js/jason-blog.min.js" | prepend: site.baseurl }}');
72-
73-
// Optional AdSense (disabled by default via site.ads_enabled)
74-
{% if site.ads_enabled and jekyll.environment == 'production' %}
75-
setTimeout(function() {
76-
var adScript = document.createElement('script');
77-
adScript.src = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js';
78-
adScript.async = true;
79-
document.head.appendChild(adScript);
80-
}, 3000);
81-
{% endif %}
82-
83-
initLazyLoading();
84-
initReadingProgress();
85-
initBackToTop();
86-
initSocialShare();
87-
});
88-
89-
function initReadingProgress() {
90-
const progressBar = document.getElementById('reading-progress');
91-
if (!progressBar) return;
92-
function updateProgress() {
93-
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
94-
const scrollHeight = document.documentElement.scrollHeight - window.innerHeight;
95-
const progress = (scrollTop / scrollHeight) * 100;
96-
progressBar.style.width = Math.min(progress, 100) + '%';
97-
}
98-
window.addEventListener('scroll', updateProgress);
99-
window.addEventListener('resize', updateProgress);
100-
updateProgress();
101-
}
102-
103-
function initBackToTop() {
104-
const backToTopBtn = document.getElementById('back-to-top');
105-
if (!backToTopBtn) return;
106-
window.addEventListener('scroll', function() {
107-
if (window.pageYOffset > 300) {
108-
backToTopBtn.classList.add('show');
109-
} else {
110-
backToTopBtn.classList.remove('show');
111-
}
112-
});
113-
}
114-
115-
function scrollToTop() {
116-
window.scrollTo({ top: 0, behavior: 'smooth' });
117-
}
118-
119-
function toggleFloatingMenu() {
120-
const menu = document.getElementById('floating-menu');
121-
if (menu) menu.classList.toggle('active');
122-
}
123-
124-
function openSearch() {
125-
const searchPage = document.querySelector('.search-page');
126-
if (searchPage) {
127-
searchPage.classList.add('show');
128-
const searchInput = document.getElementById('search-input');
129-
if (searchInput) setTimeout(() => searchInput.focus(), 300);
130-
}
131-
toggleFloatingMenu();
132-
}
133-
134-
function toggleDarkMode() {
135-
if (window.DarkModeManager) {
136-
window.DarkModeManager.toggle();
137-
} else {
138-
document.body.classList.toggle('dark-mode');
139-
localStorage.setItem('darkMode', document.body.classList.contains('dark-mode'));
140-
}
141-
toggleFloatingMenu();
142-
}
143-
144-
function printPage() {
145-
window.print();
146-
toggleFloatingMenu();
147-
}
148-
149-
function initSocialShare() {
150-
document.addEventListener('click', function(e) {
151-
const searchPage = document.querySelector('.search-page');
152-
const floatingMenu = document.getElementById('floating-menu');
153-
if (searchPage && searchPage.classList.contains('show') && !e.target.closest('.search-main') && !e.target.closest('.search-icon-close')) {
154-
searchPage.classList.remove('show');
155-
}
156-
if (floatingMenu && floatingMenu.classList.contains('active') && !e.target.closest('.floating-menu')) {
157-
floatingMenu.classList.remove('active');
158-
}
159-
});
160-
const closeBtn = document.querySelector('.search-icon-close');
161-
if (closeBtn) {
162-
closeBtn.addEventListener('click', function() {
163-
const searchPage = document.querySelector('.search-page');
164-
if (searchPage) searchPage.classList.remove('show');
165-
});
166-
}
167-
}
168-
169-
function shareToTwitter() {
170-
const url = encodeURIComponent(window.location.href);
171-
const text = encodeURIComponent(document.title);
172-
window.open(`https://twitter.com/intent/tweet?url=${url}&text=${text}`, '_blank', 'width=600,height=400');
173-
}
174-
function shareToFacebook() {
175-
const url = encodeURIComponent(window.location.href);
176-
window.open(`https://www.facebook.com/sharer/sharer.php?u=${url}`, '_blank', 'width=600,height=400');
177-
}
178-
function shareToLinkedIn() {
179-
const url = encodeURIComponent(window.location.href);
180-
const title = encodeURIComponent(document.title);
181-
window.open(`https://www.linkedin.com/sharing/share-offsite/?url=${url}&title=${title}`, '_blank', 'width=600,height=400');
182-
}
183-
function shareToWechat() {
184-
navigator.clipboard.writeText(window.location.href).then(function() {
185-
alert('链接已复制到剪贴板,请在微信中粘贴分享!');
186-
}).catch(function() {
187-
prompt('请复制以下链接在微信中分享:', window.location.href);
188-
});
189-
}
190-
function shareToWeibo() {
191-
const url = encodeURIComponent(window.location.href);
192-
const title = encodeURIComponent(document.title);
193-
window.open(`https://service.weibo.com/share/share.php?url=${url}&title=${title}`, '_blank', 'width=600,height=400');
194-
}
195-
196-
function initLazyLoading() {
197-
const images = document.querySelectorAll('img[data-src]');
198-
if (!('IntersectionObserver' in window)) {
199-
images.forEach(img => { img.src = img.dataset.src; img.classList.remove('lazy'); });
200-
return;
201-
}
202-
const imageObserver = new IntersectionObserver((entries, observer) => {
203-
entries.forEach(entry => {
204-
if (entry.isIntersecting) {
205-
const img = entry.target;
206-
img.src = img.dataset.src;
207-
img.classList.remove('lazy');
208-
observer.unobserve(img);
209-
}
210-
});
211-
});
212-
images.forEach(img => imageObserver.observe(img));
213-
}
214-
</script>
58+
<!-- Non-Critical JavaScript - Load Asynchronously -->
59+
<script>
60+
function loadScript(src, callback) {
61+
var script = document.createElement('script');
62+
script.src = src;
63+
script.async = true;
64+
if (callback) script.onload = callback;
65+
document.head.appendChild(script);
66+
}
67+
68+
window.addEventListener('load', function() {
69+
// Defer non-critical bundles
70+
loadScript('{{ "/js/bootstrap.min.js" | prepend: site.baseurl }}');
71+
loadScript('{{ "/js/jason-blog.min.js" | prepend: site.baseurl }}');
72+
73+
// Optional AdSense (disabled by default via site.ads_enabled)
74+
{% if site.ads_enabled and jekyll.environment == 'production' %}
75+
setTimeout(function() {
76+
var adScript = document.createElement('script');
77+
adScript.src = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js';
78+
adScript.async = true;
79+
document.head.appendChild(adScript);
80+
}, 3000);
81+
{% endif %}
82+
83+
initLazyLoading();
84+
initReadingProgress();
85+
initBackToTop();
86+
initSocialShare();
87+
});
88+
89+
function initReadingProgress() {
90+
const progressBar = document.getElementById('reading-progress');
91+
if (!progressBar) return;
92+
function updateProgress() {
93+
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
94+
const scrollHeight = document.documentElement.scrollHeight - window.innerHeight;
95+
const progress = (scrollTop / scrollHeight) * 100;
96+
progressBar.style.width = Math.min(progress, 100) + '%';
97+
}
98+
window.addEventListener('scroll', updateProgress);
99+
window.addEventListener('resize', updateProgress);
100+
updateProgress();
101+
}
102+
103+
function initBackToTop() {
104+
const backToTopBtn = document.getElementById('back-to-top');
105+
if (!backToTopBtn) return;
106+
window.addEventListener('scroll', function() {
107+
if (window.pageYOffset > 300) {
108+
backToTopBtn.classList.add('show');
109+
} else {
110+
backToTopBtn.classList.remove('show');
111+
}
112+
});
113+
}
114+
115+
function scrollToTop() {
116+
window.scrollTo({ top: 0, behavior: 'smooth' });
117+
}
118+
119+
function toggleFloatingMenu() {
120+
const menu = document.getElementById('floating-menu');
121+
if (menu) menu.classList.toggle('active');
122+
}
123+
124+
function openSearch() {
125+
const searchPage = document.querySelector('.search-page');
126+
if (searchPage) {
127+
searchPage.classList.add('show');
128+
const searchInput = document.getElementById('search-input');
129+
if (searchInput) setTimeout(() => searchInput.focus(), 300);
130+
}
131+
toggleFloatingMenu();
132+
}
133+
134+
function toggleDarkMode() {
135+
if (window.DarkModeManager) {
136+
window.DarkModeManager.toggle();
137+
} else {
138+
document.body.classList.toggle('dark-mode');
139+
localStorage.setItem('darkMode', document.body.classList.contains('dark-mode'));
140+
}
141+
toggleFloatingMenu();
142+
}
143+
144+
function printPage() {
145+
window.print();
146+
toggleFloatingMenu();
147+
}
148+
149+
function initSocialShare() {
150+
document.addEventListener('click', function(e) {
151+
const searchPage = document.querySelector('.search-page');
152+
const floatingMenu = document.getElementById('floating-menu');
153+
if (searchPage && searchPage.classList.contains('show') && !e.target.closest('.search-main') && !e.target.closest('.search-icon-close')) {
154+
searchPage.classList.remove('show');
155+
}
156+
if (floatingMenu && floatingMenu.classList.contains('active') && !e.target.closest('.floating-menu')) {
157+
floatingMenu.classList.remove('active');
158+
}
159+
});
160+
const closeBtn = document.querySelector('.search-icon-close');
161+
if (closeBtn) {
162+
closeBtn.addEventListener('click', function() {
163+
const searchPage = document.querySelector('.search-page');
164+
if (searchPage) searchPage.classList.remove('show');
165+
});
166+
}
167+
}
168+
169+
function shareToTwitter() {
170+
const url = encodeURIComponent(window.location.href);
171+
const text = encodeURIComponent(document.title);
172+
window.open(`https://twitter.com/intent/tweet?url=${url}&text=${text}`, '_blank', 'width=600,height=400');
173+
}
174+
function shareToFacebook() {
175+
const url = encodeURIComponent(window.location.href);
176+
window.open(`https://www.facebook.com/sharer/sharer.php?u=${url}`, '_blank', 'width=600,height=400');
177+
}
178+
function shareToLinkedIn() {
179+
const url = encodeURIComponent(window.location.href);
180+
const title = encodeURIComponent(document.title);
181+
window.open(`https://www.linkedin.com/sharing/share-offsite/?url=${url}&title=${title}`, '_blank', 'width=600,height=400');
182+
}
183+
function shareToWechat() {
184+
navigator.clipboard.writeText(window.location.href).then(function() {
185+
alert('链接已复制到剪贴板,请在微信中粘贴分享!');
186+
}).catch(function() {
187+
prompt('请复制以下链接在微信中分享:', window.location.href);
188+
});
189+
}
190+
function shareToWeibo() {
191+
const url = encodeURIComponent(window.location.href);
192+
const title = encodeURIComponent(document.title);
193+
window.open(`https://service.weibo.com/share/share.php?url=${url}&title=${title}`, '_blank', 'width=600,height=400');
194+
}
195+
196+
function initLazyLoading() {
197+
const images = document.querySelectorAll('img[data-src]');
198+
if (!('IntersectionObserver' in window)) {
199+
images.forEach(img => { img.src = img.dataset.src; img.classList.remove('lazy'); });
200+
return;
201+
}
202+
const imageObserver = new IntersectionObserver((entries, observer) => {
203+
entries.forEach(entry => {
204+
if (entry.isIntersecting) {
205+
const img = entry.target;
206+
img.src = img.dataset.src;
207+
img.classList.remove('lazy');
208+
observer.unobserve(img);
209+
}
210+
});
211+
});
212+
images.forEach(img => imageObserver.observe(img));
213+
}
214+
</script>
215215

216216
<!-- Service Worker -->
217-
{% if site.service-worker %}
218-
<script defer src="{{ "/js/snackbar.js " | prepend: site.baseurl }}"></script>
219-
<script defer src="{{ "/js/sw-registration.js " | prepend: site.baseurl }}"></script>
220-
{% endif %}
217+
{% if site.service-worker %}
218+
<script defer src="{{ "/js/snackbar.js " | prepend: site.baseurl }}"></script>
219+
<script defer src="{{ "/js/sw-registration.js " | prepend: site.baseurl }}"></script>
220+
{% endif %}
221221

222222
<!-- async load function -->
223223
<script>
224-
function async(u, c) {
225-
var d = document, t = 'script',
226-
o = d.createElement(t),
227-
s = d.getElementsByTagName(t)[0];
228-
o.src = u;
229-
if (c) { o.addEventListener('load', function (e) { c(null, e); }, false); }
230-
s.parentNode.insertBefore(o, s);
231-
}
232-
</script>
233-
<script src="{{ "/js/async-init.js" | prepend: site.baseurl }}" defer></script>
224+
function async(u, c) {
225+
var d = document, t = 'script',
226+
o = d.createElement(t),
227+
s = d.getElementsByTagName(t)[0];
228+
o.src = u;
229+
if (c) { o.addEventListener('load', function (e) { c(null, e); }, false); }
230+
s.parentNode.insertBefore(o, s);
231+
}
232+
</script>
233+
<script src="{{ "/js/async-init.js" | prepend: site.baseurl }}" defer></script>
234234

235235
<!--
236236
Because of the native support for backtick-style fenced code blocks
@@ -287,13 +287,7 @@
287287
<script src='{{ "/js/archive.js" | prepend: site.baseurl }}'></script>
288288
{% endif %}
289289

290-
<!--fastClick.js -->
291-
<script>
292-
async("//cdnjs.cloudflare.com/ajax/libs/fastclick/1.0.6/fastclick.min.js", function () {
293-
var $nav = document.querySelector("nav");
294-
if ($nav) FastClick.attach($nav);
295-
})
296-
</script>
290+
<!-- FastClick.js removed - no longer needed for modern browsers (touch-action: manipulation handles it) -->
297291

298292

299293

@@ -494,4 +488,4 @@
494488
});
495489
});
496490
</script>
497-
<!-- Original work by Jason's Blog -->
491+
<!-- Original work by Jason's Blog -->

0 commit comments

Comments
 (0)