將Hexo Light主題的Fancybox v3升級至v5並移除jQuery依賴
注意
本文由 Gemini 3.1 Pro 語言模型產生。
為了提升部落格的載入效能與行動裝置的瀏覽體驗,本次將 hexo-theme-light 主題預設的 Fancybox v3 升級至新版的 Fancybox v5(@fancyapps/ui)。
Fancybox v5 最大的優勢在於完全移除了 jQuery 依賴,並且在手機端支援非常順暢的原生手勢(包含雙指捏合與雙擊放大)。趁著這次升級,我們也將主題內依賴 jQuery 的 gallery.js 改寫為純原生 JavaScript(Vanilla JS),進一步達成網站瘦身。
步驟一:下載 Fancybox v5 檔案(本地託管)
為了不依賴外部 CDN,我們將所需的 JS 與 CSS 檔案下載並放置於主題目錄內。
- 從以下網址下載最新的 minified 檔案:
- 在主題資料夾下建立新目錄並放入檔案:
themes/light/source/fancybox5/。
檔案結構如下:
└── themes
└── light
└── source
└── fancybox5
├── fancybox.min.css
└── fancybox.umd.min.js
步驟二:改寫 gallery.js 為純原生 JavaScript
原本的 gallery.js 依賴 jQuery 和 imagesLoaded 套件。我們將其完全使用原生 JS 改寫,並將 Fancybox 的觸發屬性改為 v5 支援的 data-fancybox 與 data-caption。
開啟 themes/light/source/js/gallery.js,清空原內容並替換為以下程式碼:
document.addEventListener('DOMContentLoaded', function() {
// === 1. 處理圖說 (Caption) 與 Fancybox 5 的包裝 ===
const entries = document.querySelectorAll('.entry');
entries.forEach((entry, i) => {
const images = entry.querySelectorAll('img');
images.forEach(img => {
// 排除帶有 nofancybox class 的圖片
if (!img.classList.contains('nofancybox')) {
const alt = img.alt;
// 建立並插入 Caption
if (alt) {
const caption = document.createElement('span');
caption.className = 'caption';
caption.textContent = alt;
img.parentNode.insertBefore(caption, img.nextSibling);
}
// 建立 <a> 標籤來包裝圖片 (使用 data-fancybox)
const wrapper = document.createElement('a');
wrapper.href = img.src;
wrapper.setAttribute('data-fancybox', 'gallery' + i);
if (alt) {
wrapper.setAttribute('data-caption', alt);
}
img.parentNode.insertBefore(wrapper, img);
wrapper.appendChild(img);
}
});
});
// === 2. 處理畫廊 (Gallery) 的播放與原生動畫 ===
const play = (parent, item, callback) => {
const width = parent.clientWidth;
const imgElement = item.tagName.toLowerCase() === 'img' ? item : item.querySelector('img');
if (!imgElement) return;
const executeAnimation = () => {
const nWidth = imgElement.naturalWidth || imgElement.width;
const nHeight = imgElement.naturalHeight || imgElement.height;
callback();
item.style.transition = 'opacity 0.5s ease';
item.style.opacity = '1';
parent.style.transition = 'height 0.5s ease';
parent.style.height = (width * nHeight / nWidth) + 'px';
};
// 原生判斷圖片是否已載入
if (imgElement.complete) {
executeAnimation();
} else {
imgElement.addEventListener('load', executeAnimation);
}
};
const galleries = document.querySelectorAll('.gallery');
galleries.forEach(gallery => {
let current = 0;
const photosetContainer = gallery.querySelector('.photoset');
if (!photosetContainer) return;
const photoset = Array.from(photosetContainer.children);
const all = photoset.length;
let loading = true;
if (all === 0) return;
play(gallery, photoset[0], () => {
loading = false;
});
gallery.addEventListener('click', function(e) {
if (e.target.closest('.prev')) {
if (!loading) {
const next = (current - 1 + all) % all;
loading = true;
play(gallery, photoset[next], () => {
photoset[current].style.transition = 'opacity 0.5s ease';
photoset[current].style.opacity = '0';
loading = false;
current = next;
});
}
} else if (e.target.closest('.next')) {
if (!loading) {
const next = (current + 1) % all;
loading = true;
play(gallery, photoset[next], () => {
photoset[current].style.transition = 'opacity 0.5s ease';
photoset[current].style.opacity = '0';
loading = false;
current = next;
});
}
}
});
});
});
步驟三:更新頁尾載入邏輯(after_footer.ejs)
現在我們不再需要 jQuery 和舊版的 Fancybox,可以將它們從頁面載入區塊中移除,並補上 Fancybox v5 的初始化設定。
開啟 themes/light/layout/_partial/after_footer.ejs,修改為以下內容:
<%- js('js/gallery.js') %>
<%- js('js/highlight.min.js') %>
<script>hljs.highlightAll();</script>
<%- js('js/clipboard.min.js') %>
<%- js('js/clipboard.use.js') %>
<% if (theme.fancybox5){ %>
<%- css('fancybox5/fancybox.min.css') %>
<%- js('fancybox5/fancybox.umd.min.js') %>
<script>
document.addEventListener("DOMContentLoaded", function() {
Fancybox.bind("[data-fancybox]", {
Hash: false,
Toolbar: {
display: {
left: ["infobar"],
middle: [
"zoomIn",
"zoomOut",
"toggle1to1",
"rotateCCW",
"rotateCW",
"flipX",
"flipY",
],
right: ["slideshow", "thumbs", "close"],
},
},
});
});
</script>
<% } %>
步驟四:修改主題配置檔(_config.yml)
開啟 themes/light/_config.yml,啟用新的 fancybox5 變數並停用舊版:
# Lightbox
fancybox5: true
# fancybox: false
步驟五:刪除冗餘檔案與重新生成
確保環境乾淨,將以下不再使用的歷史檔案與資料夾直接刪除:
- 刪除目錄:
themes/light/source/fancybox/(舊版燈箱) - 刪除檔案:
themes/light/source/js/jquery-3.7.1.min.js - 刪除檔案:
themes/light/source/js/jquery.imagesloaded.min.js
最後,在終端機執行清除快取與重新生成指令:
hexo clean
hexo g
hexo s
升級完成!現在部落格不僅載入速度更快,行動裝置的圖片瀏覽體驗也獲得了大幅度的提升。