cirry

cirry

我的原生博客地址:https://cirry.cn

在Astro中實現圖片懶加載

思考#

關於圖片懶加載的方法,基於Intersection Observer API實現起來很簡單。

但是在 Astro 中實現起來卻不同,因為這裡要實現的不是網站上的圖片懶加載,而是部落格中圖片的懶加載。

Astro 中的部落格是使用 Markdown 寫的,在 Frontmatter 中添加layout來指定渲染的組件,我們在打開部落格時,組件已經加載。部落格中的 image 標籤都有了 src 屬性,已經去發送請求獲取數據了。

我一開始的想法是,在打開頁面之後,圖片發送請求之前,找到一個鉤子函數,把 image 的 src 屬性刪除,存到 data-src 中。一個比window.onload更早的鉤子函數,但是沒有這樣的方法。

所以我就想在把 markdown 渲染成 html 的時候,把 image 標籤進行處理。這個思路應該是可行的,我就去翻看 Astro 的文檔,還真找到了配置方法markdown.remarkPlugins

順著官網的線索在 github 中找,我找到了這個包:remarkjs/remark,裡面介紹了一段代碼示例可以將 h 標籤的層級縮小一級,即 h2 標籤會變成 h3 標籤。

import { visit } from 'unist-util-visit'

function myRemarkPluginToIncreaseHeadings() {
  return (tree) => {
    visit(tree, (node) => {
      if (node.type === 'heading') {
        node.depth++
      }
    })
  }
}

原始 md 文檔:

# Hi, Saturn!

頁面 html 為:

<h1>Hi, Saturn</h1>

格式化後,頁面 html 為:

<h2>Hi, Saturn</h2>

從上面的示例中,我感覺到這個插件能夠滿足需求,於是開始動手實現。

實現#

astro.config.mjs中添加如下代碼:

import { visit } from 'unist-util-visit'

function myRemarkPluginToLazyLoadImage() {
  return (tree) => {
    visit(tree, (node) => {
      if (node.type === 'image') {
        // 將url屬性給alt,另外清空url,這樣頁面加載的時候,圖片沒有url屬性就不會加載
        node.alt = node.url 
        node.url = ''
      }
    })
  }
}

export default defineConfig({
  ..., // 其他配置
  markdown: {
    remarkPlugins: [myRemarkPluginToLazyLoadImage],
    // 一定要加上這個,否則不會把md處理為html,而只處理插件內的代碼
    extendDefaultPlugins: true, 
  }
})

在引入 md 的 astro 組件中,添加如下代碼:

<script>
/* 查找到部落格中的所有img標籤 */
var markdownBody = document.querySelector(".markdown-body");
let images = markdownBody.querySelectorAll("img");

const callback = (entries) => {
  entries.forEach((entry) => {
    if (entry.isIntersecting) {
      const image = entry.target;
      const data_src = image.getAttribute("alt");
      image.setAttribute("src", data_src);
      observer.unobserve(image);
      }
    });
  };
/* 給每個img標籤添加監聽方法 */
  const observer = new IntersectionObserver(callback);
  images.forEach((image) => {
    observer.observe(image);
  });
}
</script>

到這裡,我們的圖片懶加載就完成啦!

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。