潜江市网站建设_网站建设公司_悬停效果_seo优化
2026/1/15 22:30:21 网站建设 项目流程

豆包给的生成blurDataURL方案

Posted on 2026-01-01 14:39  kacoro  阅读(0)  评论(0)    收藏  举报

你希望在 Next.js 中为所有图片自动生成对应的 base64 占位符,无需手动逐个配置 blurDataURL,核心思路是通过「批量脚本预处理」(静态图片)或「Next.js 插件自动处理」(动态/静态图片)实现,以下是两种最优方案(按易用性和实用性排序):

方案一:sharp 库 + 批量脚本(推荐,本地静态图片专属)

利用 sharp(Node.js 高性能图片处理库)编写批量脚本,一次性遍历 public 目录下所有图片,自动生成缩略图并转换为 base64,保存为配置文件,后续组件统一读取该配置实现自动注入 blurDataURL,适合图片固定的项目。

步骤 1:安装依赖

# npm
npm install sharp --save-dev# yarn
yarn add sharp --dev# pnpm
pnpm add sharp -D

步骤 2:编写批量生成脚本

在项目根目录新建 scripts/generateImageBase64.js,脚本会自动遍历 public/images 目录(可自定义路径),生成所有图片的 base64 占位符,并保存为 src/utils/imageBase64Map.json 配置文件:

const sharp = require('sharp');
const fs = require('fs');
const path = require('path');// 配置项
const SOURCE_DIR = path.join(__dirname, '../public/images'); // 本地图片目录
const OUTPUT_JSON = path.join(__dirname, '../src/utils/imageBase64Map.json'); // 输出的base64配置文件
const THUMBNAIL_SIZE = 16; // 缩略图尺寸(越小base64体积越小,建议16x16)// 递归遍历目录下所有图片
function getAllImagePaths(dir) {const imagePaths = [];const files = fs.readdirSync(dir, { withFileTypes: true });for (const file of files) {const fullPath = path.join(dir, file.name);if (file.isDirectory()) {// 递归处理子目录imagePaths.push(...getAllImagePaths(fullPath));} else {// 过滤支持的图片格式const ext = path.extname(file.name).toLowerCase();if (['.jpg', '.jpeg', '.png', '.webp', '.avif'].includes(ext)) {imagePaths.push(fullPath);}}}return imagePaths;
}// 生成单张图片的base64占位符
async function generateImageBase64(imagePath) {try {// 压缩为缩略图并转为webp格式(体积最小)const buffer = await sharp(imagePath).resize(THUMBNAIL_SIZE, THUMBNAIL_SIZE, { fit: 'cover' }).webp({ quality: 20 }) // 低质量,确保模糊效果和小体积.toBuffer();// 转为base64字符串return `data:image/webp;base64,${buffer.toString('base64')}`;} catch (err) {console.error(`处理图片失败:${imagePath}`, err);return '';}
}// 主流程
async function main() {try {// 1. 获取所有图片路径const imagePaths = getAllImagePaths(SOURCE_DIR);if (imagePaths.length === 0) {console.log('未找到任何图片');return;}// 2. 批量生成base64const imageBase64Map = {};for (const imagePath of imagePaths) {// 获取相对public目录的路径(如 /images/banner1.webp)const relativePath = path.relative(path.join(__dirname, '../public'), imagePath);const publicPath = `/${relativePath.replace(/\\/g, '/')}`; // 兼容Windows路径分隔符// 生成base64const base64 = await generateImageBase64(imagePath);if (base64) {imageBase64Map[publicPath] = base64;console.log(`已处理:${publicPath}`);}}// 3. 确保输出目录存在const outputDir = path.dirname(OUTPUT_JSON);if (!fs.existsSync(outputDir)) {fs.mkdirSync(outputDir, { recursive: true });}// 4. 保存为JSON文件fs.writeFileSync(OUTPUT_JSON, JSON.stringify(imageBase64Map, null, 2), 'utf-8');console.log(`\n所有图片base64生成完成!配置文件路径:${OUTPUT_JSON}`);} catch (err) {console.error('批量生成base64失败', err);}
}// 执行脚本
main();

步骤 3:运行脚本生成配置

package.json 中添加脚本命令,方便运行:

{"scripts": {"generate:image-base64": "node scripts/generateImageBase64.js"}
}

执行脚本:

npm run generate:image-base64

执行成功后,会在 src/utils/imageBase64Map.json 生成如下配置(键为图片 public 路径,值为对应的 base64):

{"/images/banner1.webp": "data:image/webp;base64,UklGRkoAAABXRUJQVlA4WAoAAAAQAAAADwAABwAAQUxQSDIAAAARL0AmbZurmr57yyIiqE8oiG0bejIYEQTgqiDA9vqnsUSI6H+oAERp2HZ65qP/VIAWAFZQOCBCAAAA8AEAnQEqEAAIAAVAfCWkAALp8sF8rgRgAP7o9FDvMCkMde9PK7euH5M1m6VWoDXf2FkP3BqV0ZYbO6NA/VFIAAAA","/images/product/1.webp": "data:image/webp;base64,UklGRlQAAABXRUJQVlA4WAoAAAAQAAAADwAABwAAQUxQSDIAAAARL0AmbZurmr57yyIiqE8oiG0bejIYEQTgqiDA9vqnsUSI6H+oAERp2HZ65qP/VIAWAFZQOCBCAAAA8AEAnQEqEAAIAAVAfCWkAALp8sF8rgRgAP7o9FDvMCkMde9PK7euH5M1m6VWoDXf2FkP3BqV0ZYbO6NA/VFIAAAA"
}

步骤 4:封装全局 Image 组件(自动注入 base64)

src/components/GlobalImage.tsx 封装通用 Image 组件,自动读取 imageBase64Map.json,为所有图片注入对应的 blurDataURL,无需手动配置:

import Image, { ImageProps } from 'next/image';
import imageBase64Map from '@/utils/imageBase64Map.json';// 全局 Image 组件,自动注入 blurDataURL
export default function GlobalImage(props: ImageProps) {const { src, placeholder = 'blur', ...restProps } = props;// 仅对静态图片(public目录,字符串格式src)自动注入 base64let blurDataURL = '';if (typeof src === 'string' && src.startsWith('/')) {// 从配置中获取对应 base64blurDataURL = imageBase64Map[src] || '';}return (<Imagesrc={src}placeholder={blurDataURL ? 'blur' : placeholder} // 有base64则启用模糊占位blurDataURL={blurDataURL || props.blurDataURL} // 自动注入base64{...restProps}/>);
}

步骤 5:使用全局 Image 组件(所有图片自动带 base64 占位)

替换项目中所有 next/imageGlobalImage,无需手动添加 blurDataURL,自动生效:

import GlobalImage from '@/components/GlobalImage';
import AspectRatio from '@/components/AspectRatio';export default function YourComponent({ _ }) {return (<AspectRatio ratio={32 / 15} className="bg-muted">{/* 无需手动配置 blurDataURL,自动注入对应 base64 */}<GlobalImagesrc="/images/banner1.webp"alt={_.alt}fillpriority={true}className="object-cover"/></AspectRatio>);
}

方案二:Next.js 插件(next-blurhash,自动按需生成,支持动态图片)

如果你的项目有动态新增图片的需求(无需手动运行脚本),可使用 next-blurhash 插件,它会在 Next.js 构建/开发时,自动为 Image 组件生成 blurhash(可转为 base64 占位符),无需手动处理,更便捷。

步骤 1:安装依赖

# npm
npm install next-blurhash blurhash --save# yarn
yarn add next-blurhash blurhash# pnpm
pnpm add next-blurhash blurhash

步骤 2:配置 next.config.js

import type { NextConfig } from "next";
import createNextIntlPlugin from "next-intl/plugin";
import withBlurHash from "next-blurhash";const withNextIntl = createNextIntlPlugin({experimental: {createMessagesDeclaration: "./messages/en.json",},
});const nextConfig: NextConfig = {// 你的原有配置...output: process.env.NEXT_OUTPUT_STANDALONE === 'true' ? "standalone" : undefined,allowedDevOrigins: ["local-origin.dev", "*.local-origin.dev", "https://static.areaflysolar.com"],images: {formats: ["image/webp"],deviceSizes: [375, 640, 750, 828, 1080, 1200, 1920],imageSizes: [64, 128, 256, 375, 512, 1024],},
};// 组合插件
export default withBlurHash(withNextIntl(nextConfig));

步骤 3:封装全局 Image 组件(自动生成 base64 占位)

import Image, { ImageProps } from 'next/image';
import { getBlurHashBase64 } from 'next-blurhash';export default function GlobalImage(props: ImageProps) {const { src, placeholder = 'blur', ...restProps } = props;// 自动生成 blurhash base64 占位符let blurDataURL = '';if (typeof src === 'string' && src.startsWith('/')) {// getBlurHashBase64 自动为静态图片生成 base64 模糊占位blurDataURL = getBlurHashBase64(src) || '';}return (<Imagesrc={src}placeholder={blurDataURL ? 'blur' : placeholder}blurDataURL={blurDataURL || props.blurDataURL}{...restProps}/>);
}

步骤 4:使用组件

与方案一一致,直接替换 next/image 即可,所有图片自动生成 base64 占位符:

<AspectRatio ratio={32 / 15} className="bg-muted"><GlobalImagesrc="/images/banner1.webp"alt={_.alt}fillpriority={true}className="object-cover"/>
</AspectRatio>

关键补充说明

1. 两种方案对比

方案 优点 缺点 适用场景
sharp 批量脚本 完全可控(base64 尺寸/质量)、无运行时依赖、性能优 新增图片需重新运行脚本、仅支持本地静态图片 图片固定的项目、追求极致性能
next-blurhash 插件 自动按需生成、支持动态图片、无需手动脚本 有额外依赖、base64 效果不可自定义 图片动态新增的项目、追求便捷性

2. 兼容远程图片

  • 方案一:不支持远程图片(仅本地 public 目录)。
  • 方案二:可通过 getBlurHashBase64 传入远程图片 URL(需配置 images.domains 允许跨域),自动生成 base64 占位。
  • 额外方案:远程图片可通过后端接口返回缩略图 base64,前端组件接收后注入 blurDataURL

3. 性能优化

  • base64 体积控制:缩略图尺寸建议 16x16,格式优先 WebP/AVIF,质量 20 左右,确保单个 base64 < 1KB。
  • 避免重复生成:脚本方案可在 package.jsonbuild 命令前添加 npm run generate:image-base64,实现构建前自动更新配置。
  • 兼容现有优化:两种方案均兼容 priorityfillCDN缓存 等原有配置,不影响 LCP 优化。

4. 新增图片处理

  • 方案一:新增本地图片后,重新运行 npm run generate:image-base64 即可更新配置。
  • 方案二:新增图片无需额外操作,插件会自动在构建/开发时生成 base64 占位。

总结

  1. 若图片固定,优先选择 sharp 批量脚本方案,可控性强、性能优,无需额外依赖。
  2. 若图片动态新增,选择 next-blurhash 插件方案,便捷高效,自动按需生成。
  3. 核心关键:封装全局 GlobalImage 组件,统一处理 base64 占位注入,实现所有图片无需手动配置,自动生效。
  4. 兼容性:两种方案均完全保留你的 AspectRatio + Image 组件结构,兼容原有 LCP 优化、CDN 配置等功能。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询