Skip to content

Commit a01dca8

Browse files
calderbuildclaude
andcommitted
perf(lcp): 优化 LCP 和第三方资源加载性能
关键优化: - LCP 图片直接使用 WebP 格式,添加 fetchpriority=high - 修复 jQuery 回退逻辑避免重复加载 - 移除过时的微信分享 hack 图片 - GA 延迟加载优化为 requestIdleCallback + 用户交互触发 预期影响: - LCP 减少 ~200ms(消除 JPG 到 WebP 的双重请求) - 减少 1 个网络请求(移除 icon_wechat) - 减少 ~90KB 资源(避免 jQuery 重复加载) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent bb07b25 commit a01dca8

File tree

4 files changed

+48
-24
lines changed

4 files changed

+48
-24
lines changed

_includes/footer.html

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,21 @@
1717
</div>
1818
</footer>
1919

20-
<!-- 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>
24-
<script>window.jQuery || document.write('<script src="{{ "/js/jquery.min.js" | prepend: site.baseurl }}"><\/script>')</script>
20+
<!-- Critical JavaScript - Load via CDN with proper fallback -->
21+
<script>
22+
(function() {
23+
var jq = document.createElement('script');
24+
jq.src = 'https://cdn.jsdelivr.net/npm/jquery@3.6.4/dist/jquery.min.js';
25+
jq.integrity = 'sha256-oP6HI9z1XaZNBrJURtCoUT5SUnxFr8s3BzRl+cbzUq8=';
26+
jq.crossOrigin = 'anonymous';
27+
jq.onerror = function() {
28+
var fallback = document.createElement('script');
29+
fallback.src = '{{ "/js/jquery.min.js" | prepend: site.baseurl }}';
30+
document.head.appendChild(fallback);
31+
};
32+
document.head.appendChild(jq);
33+
})();
34+
</script>
2535

2636
<!-- Critical: Language Toggle Event Delegation (Must load before user interaction) -->
2737
<script>
@@ -490,25 +500,36 @@
490500
</script>
491501
<!-- Original work by Jason's Blog -->
492502

493-
<!-- Google Analytics 4 - Deferred Loading -->
503+
<!-- Google Analytics 4 - Load after user interaction or idle time -->
494504
{% if jekyll.environment == 'production' %}
495505
<script>
496-
// Load Google Analytics after page is interactive
497-
window.addEventListener('load', function() {
498-
setTimeout(function() {
499-
var gaScript = document.createElement('script');
500-
gaScript.src = 'https://www.googletagmanager.com/gtag/js?id={{ site.ga_track_id }}';
501-
gaScript.async = true;
502-
document.head.appendChild(gaScript);
503-
506+
// Load GA only when browser is idle or user interacts
507+
(function() {
508+
var gaLoaded = false;
509+
function loadGA() {
510+
if (gaLoaded) return;
511+
gaLoaded = true;
512+
var s = document.createElement('script');
513+
s.src = 'https://www.googletagmanager.com/gtag/js?id={{ site.ga_track_id }}';
514+
s.async = true;
515+
document.head.appendChild(s);
504516
window.dataLayer = window.dataLayer || [];
505517
function gtag(){dataLayer.push(arguments);}
506518
gtag('js', new Date());
507519
gtag('config', '{{ site.ga_track_id }}', {
508520
cookie_flags: 'SameSite=Strict;Secure',
509521
anonymize_ip: true
510522
});
511-
}, 1000); // Delay 1s to prioritize rendering
512-
});
523+
}
524+
// Load on user interaction or after 3s idle
525+
if ('requestIdleCallback' in window) {
526+
requestIdleCallback(loadGA, { timeout: 3000 });
527+
} else {
528+
setTimeout(loadGA, 3000);
529+
}
530+
['scroll', 'click', 'touchstart'].forEach(function(e) {
531+
window.addEventListener(e, loadGA, { once: true, passive: true });
532+
});
533+
})();
513534
</script>
514535
{% endif %}

_includes/head.html

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@
3030
<link rel="preconnect" href="https://pagead2.googlesyndication.com" crossorigin>
3131
<link rel="dns-prefetch" href="//seo-fixer.writesonic.com">
3232
{% if page.url == '/' %}
33-
<!-- Preload hero header image to improve LCP with high priority -->
34-
<link rel="preload" as="image" href="{{ site.baseurl }}/{% if page.header-img %}{{ page.header-img }}{% else %}{{ site.header-img }}{% endif %}" fetchpriority="high" imagesrcset="{{ site.baseurl }}/{% if page.header-img %}{{ page.header-img }}{% else %}{{ site.header-img }}{% endif %} 1x" imagesizes="100vw">
33+
<!-- Preload hero header image (WebP) to improve LCP with highest priority -->
34+
{% assign header_img = page.header-img | default: site.header-img %}
35+
{% assign webp_img = header_img | replace: '.jpg', '.webp' | replace: '.jpeg', '.webp' | replace: '.png', '.webp' %}
36+
<link rel="preload" as="image" href="{{ site.baseurl }}/{{ webp_img }}" fetchpriority="high" type="image/webp">
3537
{% endif %}
3638

3739
<!-- Twitter Card -->

_includes/intro-header.html

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
{% endcomment %}
55

66
{% if include.type == 'post' or include.type == 'page' %}
7+
{% assign post_header_img = page.header-img | default: site.header-img %}
8+
{% assign post_webp_img = post_header_img | replace: '.jpg', '.webp' | replace: '.jpeg', '.webp' | replace: '.png', '.webp' %}
79
<style type="text/css">
810
header.intro-header{
911
position: relative;
10-
background-image: url('{{ site.baseurl }}/{% if page.header-img %}{{ page.header-img }}{% else %}{{ site.header-img }}{% endif %}');
12+
background-image: url('{{ site.baseurl }}/{{ post_webp_img }}');
1113
background: {{ page.header-bg-css }};
1214
}
1315

@@ -127,7 +129,9 @@ <h2 class="subheading">{{ page.subtitle }}</h2>
127129
{% endif %}
128130

129131
{% if include.type == 'page' %}
130-
<header class="intro-header" style="background-image: url('{{ site.baseurl }}/{% if page.header-img %}{{ page.header-img }}{% else %}{{ site.header-img }}{% endif %}'); aspect-ratio: 16/9; min-height: 420px;">
132+
{% assign page_header_img = page.header-img | default: site.header-img %}
133+
{% assign page_webp_img = page_header_img | replace: '.jpg', '.webp' | replace: '.jpeg', '.webp' | replace: '.png', '.webp' %}
134+
<header class="intro-header" style="background-image: url('{{ site.baseurl }}/{{ page_webp_img }}'); aspect-ratio: 16/9; min-height: 420px;">
131135
<div class="header-mask enhanced-header-mask"></div>
132136
<div class="container">
133137
<div class="row">

_layouts/default.html

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,7 @@
4242
</nav>
4343

4444
<!-- Background Switcher will be created dynamically by JavaScript -->
45-
46-
<!-- Image to hack wechat -->
47-
<img src="/img/icon_wechat.png" width="0" height="0" alt="WeChat sharing helper image" title="微信分享优化图片" />
48-
<!-- Migrate from head to bottom, no longer block render and still work -->
45+
<!-- Note: WeChat sharing now uses Open Graph meta tags in head.html -->
4946

5047
</body>
5148

0 commit comments

Comments
 (0)