Blur como placeholder em imagens no NextJS 14

🗓️ 16 de junho de 2024📖 3 minutos

Placeholder com blur em imagem no NextJS 14

Este post é um passo a passo de como adicionar blur como placeholder enquanto a aplicação carrega imagens remotas utilizando NextJS 14 e a biblioteca plaiceholder.

Passo a passo

Caso você queira adicionar blur em uma imagem que esteja salva localmente no seu projeto, basta utilizar a propriedade blur conforme recomendado na documentação oficial do NextJS.

Porém, caso você queira adicionar blur em uma imagem que seja dinâmica, alguns passos extras precisam ser seguidos, que é o que veremos neste passo a passo.

Source code

O código fonte deste tutorial pode ser encontrado aqui.

Criar um novo projeto NextJS

Para criar um novo projeto em NextJS, basta rodar o seguinte comando no terminal:

    npx create-next-app@latest <nome-do-projeto>

Instalar a biblioteca plaiceholder

Após finalizar a criação do projeto, é preciso acessar o diretório raíz do projeto e rodar o seguinte comando:

    npm  install plaiceholder

Habilitar imagens remotas nas configurações do NextJS

Para que o NextJS permita imagens remotas na aplicação, é preciso adicionar algumas configurações extras, dizendo ao NextJS qual o domínio que contém as imagens que serão utilizadas, o protocolo (HTTP ou HTTPS) e algumas outras configurações.

Portanto, abra o arquivo next.config.mjs localizado na raíz do projeto e altere seu conteúdo todo com as seguintes informações:

    /** @type  {import('next').NextConfig} */
    const  nextConfig  = {
        images: {
            remotePatterns: [
                {
                    protocol:  "https",
                    // Estou utilizando imagens que estão armazenadas em um repositório do github,
                    // substitua o hostname abaixo de acordo com sua necessidade.
                    hostname:  "raw.githubusercontent.com", 
                    port:  "",
                },
            ],
        },
    };
    export  default  nextConfig;

Plaiceholder

Agora a biblioteca que instalamos entra em ação, ela irá fornecer a imagem no formato base64-encoded, que é utilizada no campo blurDataURL do componente Image do NextJS.

Para imagens estáticas, a propriedade blurDataURL é "automaticamente preenchido" pelo próprio NextJS, mas para imagens dinâmicas é uma propriedade obrigatória.

Dito isso, é preciso criar uma função que irá retornar a imagem no formato base64-encoded. No exemplo criado para este passo a passo, a função foi criada em um arquivo chamado image.ts , que foi criado a parte dentro de um diretório que também foi criado manualmente, chamado lib. A função foi criada baseada na documentação da própria biblioteca plaiceholder, que pode ser acessada clicando aqui.


    // lib/image.ts
    import { getPlaiceholder } from  "plaiceholder";
    
    export  async  function  getBase64(imageUrl:  string) {
        try {
            const  buffer  =  await  fetch(imageUrl).then(async (res) =>
                Buffer.from(await  res.arrayBuffer())
            );
            const { base64 } =  await  getPlaiceholder(buffer);
            return  base64;
        } catch (err) {
            err;
        }
    }

Adicionando blurDataURL do componente Image

Agora que é possível obter a imagem no formato base64-encoded, basta atualizar o arquivo page.tsx da seguinte forma:

    import { getBase64 } from "@/lib/image";
    import Image from "next/image";
    
    // É preciso que o componente Home seja assíncrono para utilizar o await
    export default async function Home() {
        // Chamar a função criada, passando como parâmetro a URL da imagem
        const blur = await getBase64(
            "https://raw.githubusercontent.com/gmcardoso-dev/blog-images/main/2024/05/hoisting.jpg"
        );
        return (
            // As classes CSS do exemplo são do Tailwind, caso não esteja utilizando Tailwind no seu projeto, basta ignorá-las
            <main className="flex min-h-screen flex-col items-center justify-start p-8">
              <h1>Using blur while the image is not ready</h1>
              <div className="flex place-items-center mt-16">
                  <Image
                      className="max-w-screen"
                      src="https://raw.githubusercontent.com/gmcardoso-dev/blog-images/main/2024/05/hoisting.jpg"
                      alt="A random image"
                      width={500}
                      height={500}
                      priority
                      // Adicionar as duas propriedades abaixo
                      placeholder="blur"
                      blurDataURL={blur}
                  />
            </div>
          </main>
      );
  }

Rodando o projeto

Para visualizar o que foi feito, basta rodar o projeto utilizando o seguinte comando no terminal:

    npm run dev

E abrir o navegador na URL que o comando acima retornar, normalmente a URL é: http://localhost:3000/.

Imagem sendo baixada: Imagem borrada sendo baixada

Imagem baixada: Imagem baixada sem blur

Dependendo da sua conexão de internet fica difícil de visualizar o blur, porque a imagem acaba sendo baixada muito rapidamente. Para isso, existe uma opção dentro do navegador Google Chrome (provavelmente existe isso nos outros também, só não saberei dar detalhes de como utilizar) que simula uma conexão de internet ruim.

Bônus: Network throttling no Google Chrome

Vá em View > Developer > Developer Tools. Isso irá exibir uma nova janela na aba do navegador. Clique na aba Network dentro desta nova janela e, no topo desta aba, troque o valor "No throttling" por "Fast 3G" ou "Slow 3G" e tente recarregar a página. Essa opção irá simular uma conexão de internet pior, demorando mais para baixar a imagem e, assim, mais fácil de visualizar o placeholder que foi adicionado enquanto a imagem é baixada.

Referências