Skip to content

Commit c99f70b

Browse files
committed
chore(ci): blog sync
1 parent b6ea903 commit c99f70b

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed

data/blog/post-35.mdx

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
---
2+
title: tytemd 中如何实现图片懒加载
3+
date: 2024-12-21T11:47:04Z
4+
slug: post-35
5+
author: chaseFunny:https://github.com/chaseFunny
6+
tags: ["AI","React","前端开发"]
7+
---
8+
9+
大家好,我是 luckySnail ,周五正当我和 AI 如胶似漆的时候,后端同事突然和我说有一个地方需要我优化一下,我就问他,什么快和我说,他打开一个项目页面,然后打开控制台和我说,你看,这个网页刚进入就把所有图片都请求了了一次,并且因为请求太多图片导致触发了我们设置的最大限制,导致后面的图片直接请求失败,从而导致左侧图片都是加载失败的样子
10+
11+
![image-20241221181821017](https://blog-1304565468.cos.ap-shanghai.myqcloud.com/work/image-20241221181821017.png)
12+
13+
好家伙,这都是老板白花花的银子呀!赶紧修复上线,可是怎么修复呢?
14+
15+
## 问题分析
16+
17+
解决问题前,我们可以先分析一下问题,就像我们看病一样,我们总得先挂号,让医生看看身体是怎么了。说回正题,问题分析:
18+
19+
- 页面首次加载时就请求所有图片资源
20+
- 大量图片并发请求触发了服务器限制
21+
- 导致部分图片加载失败
22+
- 造成不必要的带宽消耗和性能浪费
23+
24+
知道了问题,我们看下解决方案:使用图片懒加载(Lazy Loading)技术。图片懒加载是一种网页性能优化技术,它可以延迟加载页面中不可见的图片,直到用户滚动到可见区域时才进行加载
25+
26+
其实大厂们也都是这么做的,不信我们看看掘金平台
27+
28+
![image-20241221183028256](https://blog-1304565468.cos.ap-shanghai.myqcloud.com/work/image-20241221183028256.png)
29+
30+
![image-20241221183133520](https://blog-1304565468.cos.ap-shanghai.myqcloud.com/work/image-20241221183133520.png)
31+
32+
我们可以看到当我们页面滚动到下面才加载对应的图片
33+
34+
## 解决问题
35+
36+
下面我们来解决一下我们教程中图片加载问题,由于我们项目使用 bytemd 作为内容渲染器,所以图片的渲染其实在 bytemd 内部完成的,那我们想要自定义渲染图片的逻辑,也就需要借助 bytemd 的自定义插件的能力了,通过查阅源码得知:插件也就是一个函数,用于扩展 Bytemd 编辑器和查看器的功能,返回指定的对象类型,返回对象类型已经定义好了,是 BytemdPlugin 。它包含五个属性:
37+
38+
- remark:自定义 Markdown 解析
39+
- rehype:HTML 解析
40+
- actions:注册操作,也就是定义我们编辑框上面哪些小图标的
41+
- editorEffect :编辑器副作用
42+
- viewerEffect:查看器副作用
43+
44+
我们需要的是 viewerEffect ,然后我们只需要先获取到所有图片,然后为图片添加上懒加载的逻辑,具体的思路:
45+
46+
1. 在 viewerEffect 中,拿到 markdownBody ,也就是 md 的内容,是一个 DOM 元素
47+
2. 通过 querySelectorAll 获取所有 img 标签,然后,我们有两个选择,
48+
3. 第一,使用游览器自带的图片懒加载
49+
4. 第二,使用 IntersectionObserver 来实现懒加载,这种方式可以设置一个占位图,这样体验更加好
50+
51+
最后,我们看一下具体代码:
52+
53+
```ts
54+
import type { BytemdPlugin } from 'bytemd'
55+
56+
export interface ImageLazyLoadOptions {
57+
// 是否使用原生懒加载
58+
useNativeLazy?: boolean;
59+
// 自定义加载占位图
60+
placeholderSrc?: string;
61+
// 自定义类名
62+
className?: string;
63+
}
64+
65+
export default function imageLazyLoad(options: ImageLazyLoadOptions = {}): BytemdPlugin {
66+
const {
67+
useNativeLazy = true,
68+
placeholderSrc = '',
69+
className = ''
70+
} = options;
71+
72+
return {
73+
viewerEffect({ markdownBody }) {
74+
// 获取所有图片元素
75+
const images = markdownBody.querySelectorAll('img');
76+
77+
images.forEach((img) => {
78+
// 保存原始src
79+
const originalSrc = img.getAttribute('src');
80+
81+
if (useNativeLazy) {
82+
// 使用原生懒加载
83+
img.setAttribute('loading', 'lazy');
84+
} else {
85+
// 使用 Intersection Observer 实现懒加载
86+
const observer = new IntersectionObserver((entries) => {
87+
entries.forEach((entry) => {
88+
if (entry.isIntersecting) {
89+
const obImg = entry.target as HTMLImageElement;
90+
if (originalSrc) {
91+
obImg.src = originalSrc;
92+
}
93+
observer.unobserve(obImg);
94+
}
95+
});
96+
});
97+
98+
// 设置占位图
99+
if (placeholderSrc) {
100+
img.src = placeholderSrc;
101+
}
102+
103+
// 将原始图片地址存储在data属性中
104+
img.dataset.src = originalSrc || '';
105+
img.src = placeholderSrc;
106+
107+
// 添加自定义类名
108+
if (className) {
109+
img.classList.add(className);
110+
}
111+
112+
// 开始观察
113+
observer.observe(img);
114+
}
115+
});
116+
}
117+
}
118+
}
119+
```
120+
121+
我们看看效果吧!
122+
123+
![image-20241221184754629](https://blog-1304565468.cos.ap-shanghai.myqcloud.com/work/image-20241221184754629.png)
124+
125+
![image-20241221184841801](https://blog-1304565468.cos.ap-shanghai.myqcloud.com/work/image-20241221184841801.png)
126+
127+
![image-20241221185043728](https://blog-1304565468.cos.ap-shanghai.myqcloud.com/work/image-20241221185043728.png)
128+
129+
完美修复bug,也节省了开销
130+
131+
## 开源 tytemd 的图片懒加载插件
132+
133+
相信肯定也有其他小伙伴有同样的问题,那就开源吧,毕竟谁会拒绝直接拿来使用呢?
134+
135+
地址:https://www.npmjs.com/package/bytemd-plugin-image-lazy
136+
137+
如果你觉得写得不错,对你有帮助,点个赞再走吧!
138+
139+
哦对了,有人好奇如何从 0 发布一个 npm 包吗?
140+
141+
---
142+
此文自动发布于:<a href="https://github.com/coderPerseus/blog/issues/35" target="_blank">github issues</a>

0 commit comments

Comments
 (0)