Como usar o Redis para contar acessos em páginas estáticas

Como usar o Redis para contar acessos em páginas estáticas

Redis

Leitura de 5 minutos

Redis

Iniciante

Publicado em 29 de Maio de 2024

Recentemente me deparei com o seguinte cenário no Onigiri Hardcore. Como posso mostrar para patrocinadores ou até mesmo para gestão de evento que o portal de notícias é um possível sucesso e que posso me cadastrar como imprensa ou algo do tipo? Sem depender de Analytics, sem depender de serviços prontos.

Para quem não sabe, o Onigiri Hardcore é um portal de notícias e já participou de diversos eventos em Campinas como imprensa, fazendo cobertura sobre o evento e tudo mais. Só que evoluímos de lá para cá e começamos a nos tornar independentes.

E como a gente faz essa métrica?

Existem diversas soluções para fazermos isso, como o Onigiri Hardcore utiliza de markdown - assim como esse blog - para criar as notícias, não temos um banco de dados. Então não faria sentido criar um banco só para isso. Mas, caso tivesse, era só criar uma collection ou referenciar e fazer o mesmo esquema, mas ao invés de ser uma publicação, só adicionaria +1 no banco utilizando um campo de visualizações ou algo do tipo.

Podemos utilizar do Github API para fazermos alterações no README, sempre que alguém acessar a página.

Podemos utilizar de outras APIs ou até mesmo APIs próprias para isso.

E uma das alternativas que me chegou é, utilize o Redis.

Eu já trabalhei com ele anteriormente em um projeto da Rocketseat, assim como já vi vários exemplos utilizando ele para fazer estilo de contador sem ficar sobrecarregando banco de dados e coisas do tipo, e eu pensei. Porque não?

Como usar o Redis para contar acessos em páginas estáticas

Inicialmente, se você não tiver um projeto em Next.js, crie um novo.

npx create-next-app@latest visit-counter
cd visit-counter

Por exemplo.

Instale o Redis nele e instale também - de forma global - a CLI do Redis - no caso, estou usando Ubuntu, então verifique a documentação oficial para entender como funciona a instalação no seu dispositivo.

npm install redis
sudo apt update
sudo apt install redis-server
sudo systemctl enable redis-server.service
sudo systemctl start redis-server.service

CLI instalada, Next configurado, vamos começar. Antes, de tudo, você também pode utilizar o Redis Insight para conseguir visualizar através de uma interface gráfica, o seu banco de dados.

Caso você não queira, você pode utilizar o Redis CLI, e executar o seguinte comando:

redis-cli

E em seguida para visualizar as informações em nosso cenário

get totalVisits
hgetall monthlyVisits

Vamos criar a conexão com o Redis em src/lib/redis.js

import { createClient } from 'redis';

const client = createClient({
  url: process.env.REDIS_URL || 'redis://localhost:6379'
});

client.on('error', (err) => {
  console.error('Redis client not connected to the server:', err);
});

client.on('connect', () => {
  console.log('Redis client connected to the server');
});

client.connect();

export default client;

Depois, vamos criar uma Rota de API para registrar as visitas em pages/api/visit.js

import client from '../../src/lib/redis';

export default async function handler(req, res) {
    if (req.method === 'POST') {
        try {
            // Garantir que o cliente está conectado
            if (!client.isOpen) {
                await client.connect();
            }

            const now = new Date();
            const yearMonth = `${now.getFullYear()}-${now.getMonth() + 1}`;

            await client.incr('totalVisits');
            await client.hIncrBy('monthlyVisits', yearMonth, 1);

            console.log('Visit recorded');
            res.status(200).json({ message: 'Visit recorded' });
        } catch (error) {
            console.error('Error recording visit', error);
            res.status(500).json({ message: 'Internal Server Error' });
        }
    } else {
        res.setHeader('Allow', ['POST']);
        res.status(405).end(`Method ${req.method} Not Allowed`);
    }
}

E em seguida, vamos criar a rota para obter as contagens de visitas em pages/api/visits.js

import redisClient from '../../src/lib/redis';

export default async function handler(req, res) {
    if (req.method === 'GET') {
        const totalVisits = await redisClient.get('totalVisits');
        const monthlyVisits = await redisClient.hGetAll('monthlyVisits');

        res.status(200).json({ totalVisits, monthlyVisits });
    } else {
        res.setHeader('Allow', ['GET']);
        res.status(405).end(`Method ${req.method} Not Allowed`);
    }
}

E após isso, registrar as visitas em pages/_app.js para isso rodar independente da página que for acessada.

import React, { useEffect } from 'react';
import '../styles/globals.css'

// eslint-disable-next-line react/prop-types
function MyApp({ Component, pageProps }) {

    useEffect(() => {
        fetch('/api/visit', {
            method: 'POST',
        });
    }, []);

    return (
        <>
            <Component {...pageProps} />
        </>
    )
}

export default MyApp

Bacana, não é mesmo? Dessa maneira, conseguimos ter as seguintes informações, por enquanto.

  • Total de visitas realizadas naquele mês
  • Total de visitas realizadas separadas por mês.

Claro que existe alguns problemas ainda e otimizações a serem feitas, mas essa é apenas a ponta do iceberg para você ter noção do que é o Redis e sua funncionalidade.

Que tipos de situações temos que adicionar ainda? Por exemplo, a cada F5, a atualização sobe e eu não gostaria que isso acontecesse, pois o usuário pode simplesmente ficar apertando F5 várias e várias vezes para ganhar visualização e isso não é o ideal.

Assim como também queremos filtrar qual é a página em que o usuário está acessando, seria bacana, não é mesmo? Saber que em determinada página tem X acessos e na outra Y e assim por diante. São algumas costumizações a serem feitas.

E como faço para rodar esse projeto?

Inicialmente, suba o projeto na Vercel com a sua conta cadastrada e configure seu ambiente de desenvolvimento para receber as variáveis de ambiente como:

REDIS_URL=redis://your_redis_cloud_url

Em seguida, crie uma conta no Redis Cloud e configura sua nova instância gratuita para conseguir ter acesso e registro no banco em que cadastramos. Pegue a URL da instância e grave no seu .env.local dentro do REDIS_URL.

Essas adaptações ainda irão ser alterada para o cenário do Onigiri Hardcore, aonde você pode estar acompanhando através do repositório oficial do Github. Caso queira ajudar, fique à vontade para criar uma pull request e mandar sua alteração/sugestão.

Se tiver com alguma dúvida ou dificuldade, não hesite em me chamar no X/Twitter.

Obrigado por ler até aqui!

Fique atualizado!

Nunca perca um post ou anúncio de projeto que eu faça. Siga-me no Twitter para manter contato, fazer perguntas ou conversar.

Gostou do artigo? Faça um PIX de café! ☕