使用nextjs image 优化网页CLS

351 阅读1分钟

问题背景

在开发网站时,如果使用原生img标签渲染,会在页面加载后,内容出现偏移抖动的情况,给用户带来不好的体验;如下图(测试文本在上方先出来,待图像加载后又被顶到了下方)

iShot_2023-11-19_16.37.52.gif

解决方式

如果使用nextjs开发的话,可以使用image标签来解决上述问题;

使用Image替换img,

代码如下:

import Image from "next/image";
import test from "./test.jpg";

const Test = (props) => {
  return (
    <div>
      {/* <img src="./test.jpg" style={{ width: "100%", height: "auto" }} /> */}
      <Image
        {...test}
        alt="猩猩图"
        placeholder="blur"
        style={{ width: "100%", height: "auto" }}
      />

      <div>我的测试</div>
    </div>
  );
};

效果如下:

iShot_2023-11-19_20.09.53.gif

可以发现现在文字渲染后到网页load完成过程中,位置没有偏移;并且优化了图片的加载体验;观察nextjs返回的HTML,和网络请求,可以看到src被替换成了一个像素模糊的图片,这个图片体积很小,待大图加载完后再替换它;

image.png

更进一步

到目前为止,我们都是使用的都是本地图片,那么换成远程图片后又该如何做呢?

这就需要我们自己来生成placeholder的图片了,这里可以使用lqip-modern这个库;

用法如下:

const Test = (props) => {
  return (
    <div>
      {/* <img src="./test.jpg" style={{ width: "100%", height: "auto" }} /> */}

      <Image
        {...props}
        alt="猩猩图"
        placeholder="blur"
        style={{ width: "100%", height: "auto", color: "red" }}
      />

      <div>我的测试</div>
    </div>
  );
};

export const getStaticProps = async () => {
  const lqip = require("lqip-modern");
  const url = "https://xxxx.aliyuncs.com/test.jpg";
  const imgData = await fetch(new URL(url));
  const arrayBufferData = await imgData.arrayBuffer();
  const result = await lqip(Buffer.from(arrayBufferData));
  console.log({ result });
  return {
    props: {
      blurDataURL: result.metadata.dataURIBase64,
      blurWidth: 16,
      blurHeight: 4,
      width: result.metadata.originalWidth,
      height: result.metadata.originalHeight,
      src: url,
    },
  };
};

效果如下:

iShot_2023-11-19_20.26.45.gif

名词说明

CLS:Cumulative Layout Shift (CLS)