Files
fuwari/rehype-image-optimization.mjs
T
mckero 6c141d0b93 更新 rehype-image-optimization.mjs
主要改动:
1.  
增加了 1200w 的档位。
2.  
把 sizes 从写死的 500px 改成了 100vw (移动端占满屏),这样计算更准确。
2026-01-12 23:02:19 +08:00

73 lines
2.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { visit } from 'unist-util-visit';
export function rehypeImageOptimization() {
return (tree) => {
visit(tree, 'element', (node) => {
// 1. 基础防御检查
if (node.tagName !== 'img' || !node.properties) return;
const src = node.properties.src;
if (!src) return;
let urlObj;
try {
urlObj = new URL(src);
} catch (e) {
// 相对路径兜底
node.properties.loading = 'lazy';
node.properties.decoding = 'async';
return;
}
// 2. 业务逻辑:只处理 img.mckero.com
if (urlObj.hostname !== 'img.mckero.com') {
node.properties.loading = 'lazy';
node.properties.decoding = 'async';
return;
}
// 3. 业务逻辑:跳过 WebP/AVIF
const pathname = urlObj.pathname.toLowerCase();
if (pathname.endsWith('.webp') || pathname.endsWith('.avif')) {
node.properties.loading = 'lazy';
node.properties.decoding = 'async';
return;
}
// 4. 构造 Worker 链接函数
const generateWorkerUrl = (originalSrc, width) => {
const workerUrl = new URL('https://opt.mckero.com/');
workerUrl.searchParams.set('url', originalSrc);
if (width) workerUrl.searchParams.set('width', width);
return workerUrl.toString();
};
// ============================================================
// 核心升级区域
// ============================================================
// 默认 src (回落地址): 给 800w,保证兼容性
node.properties.src = generateWorkerUrl(src, 800);
// 生成三档 srcset:
// 500w: 省流/小屏
// 800w: 标准/PC
// 1200w: 高清/Retina
const s500 = generateWorkerUrl(src, 500);
const s800 = generateWorkerUrl(src, 800);
const s1200 = generateWorkerUrl(src, 1200);
node.properties.srcset = `${s500} 500w, ${s800} 800w, ${s1200} 1200w`;
// 升级 sizes 逻辑:
// (max-width: 600px) 100vw -> 手机端:图片宽度 = 屏幕宽度 (更符合实际)
// 800px -> 电脑端:图片最大就是 800px (文章容器宽度)
node.properties.sizes = '(max-width: 600px) 100vw, 800px';
// 标准优化属性
node.properties.loading = 'lazy';
node.properties.decoding = 'async';
});
};
}