From 7b54b603b71b6521735f67acb9df43c6473cd849 Mon Sep 17 00:00:00 2001 From: QIU SHENGMING Date: Mon, 12 Jan 2026 23:33:14 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20rehype-image-optimization.?= =?UTF-8?q?mjs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rehype-image-optimization.mjs | 37 +++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/rehype-image-optimization.mjs b/rehype-image-optimization.mjs index d751c7c..128e02a 100644 --- a/rehype-image-optimization.mjs +++ b/rehype-image-optimization.mjs @@ -4,29 +4,31 @@ export function rehypeImageOptimization() { return (tree) => { visit(tree, 'element', (node) => { - // 1. 基础防御 + // 1. 基础防御:只处理 img 标签且有属性的 if (node.tagName !== 'img' || !node.properties) return; const src = node.properties.src; + // 没有 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 + // 2. 业务逻辑:只处理 img.mckero.com (你的橱窗) if (urlObj.hostname !== 'img.mckero.com') { node.properties.loading = 'lazy'; node.properties.decoding = 'async'; return; } - // 3. 业务逻辑:跳过 WebP/AVIF + // 3. 业务逻辑:跳过 WebP/AVIF (Worker 处理不了) const pathname = urlObj.pathname.toLowerCase(); if (pathname.endsWith('.webp') || pathname.endsWith('.avif')) { node.properties.loading = 'lazy'; @@ -34,33 +36,44 @@ export function rehypeImageOptimization() { return; } - // 4. 构造 Worker 链接 - const generateWorkerUrl = (originalSrc, width) => { + // ============================================================ + // 🚨 核心修正:适配 Photon 的 action 参数 🚨 + // 格式:action=resize!宽,高,模式 + // 高度设为 0 代表自适应,模式 2 代表缩放 + // ============================================================ + const generateWorkerUrl = (originalSrc, targetWidth) => { const workerUrl = new URL('https://opt.mckero.com/'); + + // 1. 设置 url 参数 (原图地址) workerUrl.searchParams.set('url', originalSrc); - if (width) workerUrl.searchParams.set('width', width); + + // 2. 设置 action 参数 (这才是 Worker 能看懂的指令!) + if (targetWidth) { + // 例如:resize!800,0,2 + workerUrl.searchParams.set('action', `resize!${targetWidth},0,2`); + } + return workerUrl.toString(); }; // ============================================================ - // 最终版配置:四大金刚 (500, 800, 1200, 1600) + // 生成四档 srcset (500, 800, 1200, 1600) // ============================================================ - // 默认 src: 给 800w (兼容性最好) + // 默认 src: 给 800w (兼容性兜底) node.properties.src = generateWorkerUrl(src, 800); - // 生成 srcset const s500 = generateWorkerUrl(src, 500); const s800 = generateWorkerUrl(src, 800); const s1200 = generateWorkerUrl(src, 1200); - const s1600 = generateWorkerUrl(src, 1600); // 新增:MacBook/4K 专用 + const s1600 = generateWorkerUrl(src, 1600); node.properties.srcset = `${s500} 500w, ${s800} 800w, ${s1200} 1200w, ${s1600} 1600w`; - // sizes 逻辑 (保持不变) - // 手机端占满屏,电脑端最大 800px + // sizes 逻辑 (手机满屏,电脑最大800) node.properties.sizes = '(max-width: 600px) 100vw, 800px'; + // 标准优化属性 node.properties.loading = 'lazy'; node.properties.decoding = 'async'; });