# 第2步:JS按需加载优化 - 最终实施方案 ## 📊 优化策略总结 ### 核心原则 1. **UIkit始终加载** - 作为基础框架,不按需加载 2. **核心功能始终加载** - 导航、搜索、主题切换等 3. **页面特定功能按需加载** - 评论、打赏、无限滚动等 4. **延迟加载非关键功能** - Toast、懒加载等 --- ## 🔧 实施代码 ### 修改footer.html(第50-133行) **删除原有代码,替换为:** ```gohtml {{/* ====== 优化后的JS加载策略 ====== */}} {{/* ====== 1. 核心JS Bundle - 始终加载 ====== */}} {{ $iconfont := resources.Get "js/libs/iconfont.js" }} {{ $uikit := resources.Get "js/libs/uikit.min.js" }} {{ $viewimage := resources.Get "js/libs/view-image.min.js" }} {{ $utils := resources.Get "js/modules/utils.js" }} {{ $loader := resources.Get "js/modules/loader.js" }} {{ $cache := resources.Get "js/modules/cache.js" }} {{ $search := resources.Get "js/modules/search.js" }} {{ $floatingTools := resources.Get "js/modules/floating-tools.js" }} {{ $nprogress := resources.Get "js/libs/nprogress.js" }} {{ $pjaxLib := resources.Get "js/libs/pjax.js" }} {{ $mypjax := resources.Get "js/modules/mypjax.js" }} {{ $pangu := resources.Get "js/modules/pangu.js" }} {{ $linkify := resources.Get "js/modules/linkify.js" }} {{ $main := resources.Get "js/main.js" }} {{ $coreScripts := slice $iconfont $uikit $viewimage $utils $loader $cache $search $floatingTools $nprogress $pjaxLib $mypjax $pangu $linkify $main | resources.Concat "js/core.js" | resources.Minify | resources.Fingerprint }} {{/* ====== 2. 配置变量 - 必须在核心JS之前或同时 ====== */}} {{/* ====== 3. 远程数据获取 - 构建时 ====== */}} {{/* Fetch friend data at build time — no runtime network requests */}} {{ $linkHosts := slice }} {{ $linkNames := slice }} {{ with resources.GetRemote "https://api.usj.cc/api/links?all=1" }} {{ with .Err }} {{ warnf "Links API fetch failed: %s" . }} {{ else }} {{ with .Content | transform.Unmarshal }} {{ range .links }} {{ $host := "" }} {{ with .url | urls.Parse }} {{ $host = .Host | strings.TrimPrefix "www." }} {{ end }} {{ $title := .name | default "" }} {{ if $host }} {{ $linkHosts = $linkHosts | append (dict "host" $host "title" $title) }} {{ end }} {{ if $title }} {{ $linkNames = $linkNames | append (dict "lower" (lower $title) "title" $title) }} {{ end }} {{ end }} {{ end }} {{ end }} {{ end }} {{ $feedHosts := slice }} {{ $feedNames := slice }} {{ with resources.GetRemote "https://api.usj.cc/api/feeds" }} {{ with .Err }} {{ warnf "Feeds API fetch failed: %s" . }} {{ else }} {{ with .Content | transform.Unmarshal }} {{ range .feeds }} {{ $host := "" }} {{ with .url | urls.Parse }} {{ $host = .Host | strings.TrimPrefix "www." }} {{ end }} {{ $title := .feedTitle | default "" }} {{ if $host }} {{ $feedHosts = $feedHosts | append (dict "host" $host "title" $title) }} {{ end }} {{ if $title }} {{ $feedNames = $feedNames | append (dict "lower" (lower $title) "title" $title) }} {{ end }} {{ end }} {{ end }} {{ end }} {{ end }} {{/* ====== 4. 页面特定JS - 按需加载 ====== */}} {{/* 文章详情页专用JS */}} {{ if .IsPage }} {{ $artalkModule := resources.Get "js/modules/artalk.js" }} {{ $paragraphComments := resources.Get "js/modules/paragraph-comments.js" }} {{ $reward := resources.Get "js/modules/reward.js" }} {{ $pageScripts := slice $artalkModule $paragraphComments $reward | resources.Concat "js/page-only.js" | resources.Minify | resources.Fingerprint }} {{ end }} {{/* 首页专用JS */}} {{ if .IsHome }} {{ if .Site.Params.infiniteScroll.enable }} {{ $infiniteScroll := resources.Get "js/modules/infinite-scroll.js" }} {{ end }} {{ end }} {{/* 特定页面专用JS */}} {{ if or (eq .Type "links") (eq .Type "circles") }} {{ $tiaozhuan := resources.Get "js/modules/tiaozhuan.js" }} {{ end }} {{/* ====== 5. 延迟加载的非关键JS ====== */}} {{ $toast := resources.Get "js/modules/toast.js" }} {{ $easylazyload := resources.Get "js/modules/lazyload.js" }} {{ $deferredScripts := slice $toast $easylazyload | resources.Concat "js/deferred.js" | resources.Minify | resources.Fingerprint }} {{/* ====== 6. 第三方脚本 ====== */}} ``` --- ## 📦 Bundle拆分详情 ### Core.js(核心bundle) **包含:** ~14个文件 **大小:** ~200KB(压缩后) **加载策略:** defer(DOM解析完成后立即执行) **包含模块:** - UIkit框架 - 图标字体 - 图片灯箱 - 工具函数 - 加载器 - 缓存 - 搜索 - 浮动工具 - 进度条 - PJAX - 中英文空格处理 - 链接处理 - 主题主逻辑 ### Page-only.js(文章详情页专用) **包含:** 3个文件 **大小:** ~180KB(压缩后) **加载策略:** defer(仅在文章详情页加载) **包含模块:** - Artalk评论系统 - 段落评论 - 打赏功能 ### Deferred.js(延迟加载) **包含:** 2个文件 **大小:** ~25KB(压缩后) **加载策略:** requestIdleCallback(浏览器空闲时加载) **包含模块:** - Toast消息 - 图片懒加载 ### 独立加载的JS - infinite-scroll.js - 仅首页(如果启用) - tiaozhuan.js - 仅links/circles页面 - bsz.js - 异步加载(不蒜子计数) --- ## 🎯 优化效果预估 ### 首页加载 ``` 优化前: HTML ████████░░░░░░░░░░ CSS ██████░░░░░░░░░░░░ (内联) JS ██████████████████ (800KB,全部加载) 渲染 ████████████░░░░░░ 优化后: HTML ████████░░░░░░░░░░ CSS ██████░░░░░░░░░░░░ (内联) JS ██████████░░░░░░░░ (350KB,核心+条件) 空闲 ░░░░░░░░░░████░░░░ (25KB,延迟加载) 渲染 ████████████████░░ (提前!) ``` ### 文章详情页加载 ``` 优化前: JS ██████████████████ (800KB) 渲染 ████████████░░░░░░ 优化后: JS ████████████░░░░░░ (450KB) 渲染 ████████████████░░ (提前!) 评论 ░░░░░░░░░░████████ (Artalk按需加载) ``` --- ## 🧪 功能测试清单 ### 必测项目 #### 1. 首页功能 - [ ] 导航菜单点击正常 - [ ] 搜索框打开/关闭正常 - [ ] 搜索结果显示正常 - [ ] 主题切换(深色/浅色)正常 - [ ] 文章列表正常显示 - [ ] 无限滚动加载正常(如果启用) - [ ] 浮动工具栏正常(搜索、主题、返回顶部) #### 2. 文章详情页功能 - [ ] 文章内容正常显示 - [ ] 图片灯箱正常(点击查看大图) - [ ] Artalk评论区正常加载 - [ ] 评论功能正常(发布、回复) - [ ] 打赏按钮功能正常 - [ ] 段落评论功能正常(如果启用) - [ ] 返回顶部按钮正常 #### 3. 其他页面功能 - [ ] 友链页面跳转正常 - [ ] circles页面功能正常 - [ ] 归档页面正常 - [ ] 搜索结果页正常 #### 4. 跨页面功能 - [ ] PJAX导航正常(页面无刷新切换) - [ ] 浏览器前进/后退正常 - [ ] 书签/分享链接正常 ### 性能测试 #### Chrome DevTools测试 **Network面板:** 1. 打开DevTools → Network 2. 刷新页面 3. 检查: - [ ] core.js首先加载 - [ ] page-only.js仅在文章页加载 - [ ] deferred.js最后加载 - [ ] 总体JS大小减少 **Performance面板:** 1. 记录页面加载 2. 检查: - [ ] TBT(Total Blocking Time)减少 - [ ] 长任务数量减少 - [ ] 交互响应更快 **Lighthouse:** 1. 运行Performance审计 2. 预期指标: - [ ] Performance得分:90+ - [ ] TTI:改善20-30% - [ ] TBT:改善40-50% - [ ] Speed Index:改善20-30% --- ## 🐛 故障排除 ### 问题1:评论区未加载 **症状:** 文章详情页看不到评论区 **可能原因:** 1. page-only.js加载失败 2. Artalk初始化时机不对 3. JavaScript错误 **解决方案:** 1. 打开Console查看错误 2. 检查Network面板,确认page-only.js加载成功 3. 确认artalkConfig存在(head.html中定义) ### 问题2:功能延迟初始化 **症状:** 点击某些按钮无响应,过一会儿才正常 **原因:** 模块还未加载完成就尝试调用 **解决方案:** - 这是预期行为,用户可能会感觉到轻微延迟 - 如果延迟明显,考虑将该模块移到core.js中 ### 问题3:无限滚动失效 **症状:** 首页无法加载更多文章 **可能原因:** 1. infinite-scroll.js未加载 2. window.enableInfiniteScroll未定义 **解决方案:** 1. 确认Site.Params.infiniteScroll.enable为true 2. 检查Console是否有错误 3. 确认infinite-scroll.js加载成功 --- ## 🔄 回滚方案 如果优化后出现严重问题,快速回滚: ```gohtml {{/* 恢复原始JS加载方式 */}} {{ $iconfont := resources.Get "js/libs/iconfont.js" }} {{ $uikit := resources.Get "js/libs/uikit.min.js" }} {{ $easylazyload := resources.Get "js/modules/lazyload.js" }} {{ $viewimage := resources.Get "js/libs/view-image.min.js" }} {{ $main := resources.Get "js/main.js" }} {{ $mypjax := resources.Get "js/modules/mypjax.js" }} {{ $nprogress := resources.Get "js/libs/nprogress.js" }} {{ $tiaozhuan := resources.Get "js/modules/tiaozhuan.js" }} {{ $toast := resources.Get "js/modules/toast.js" }} {{ $reward := resources.Get "js/modules/reward.js" }} {{/* Modules */}} {{ $utils := resources.Get "js/modules/utils.js" }} {{ $loader := resources.Get "js/modules/loader.js" }} {{ $cache := resources.Get "js/modules/cache.js" }} {{ $search := resources.Get "js/modules/search.js" }} {{ $floatingTools := resources.Get "js/modules/floating-tools.js" }} {{ $paragraphComments := resources.Get "js/modules/paragraph-comments.js" }} {{ $infiniteScroll := resources.Get "js/modules/infinite-scroll.js" }} {{ $artalkModule := resources.Get "js/modules/artalk.js" }} {{ $pjaxLib := resources.Get "js/libs/pjax.js" }} {{ $linkify := resources.Get "js/modules/linkify.js" }} {{ $pangu := resources.Get "js/modules/pangu.js" }} {{ $scripts := slice $iconfont $uikit $easylazyload $viewimage $utils $loader $cache $search $floatingTools $paragraphComments $infiniteScroll $artalkModule $nprogress $pjaxLib $pangu $linkify $main $mypjax $toast $tiaozhuan $reward | resources.Concat "js/bundle.js" | resources.Minify | resources.Fingerprint }} ``` --- ## ✅ 完成确认 测试通过后,第2步即完成。继续第3步:**字体子集化优化** --- **文档版本:** v2.0 **最后更新:** 2026-06-03