কম্পিউটার টিউটোরিয়াল

আপস্ট্যাশ রেডিস দিয়ে আপনার Next.js ব্লগে ভিউ কাউন্টার যোগ করুন

Lee-এর ব্লগ থেকে অনুপ্রাণিত হয়ে, যেখানে প্রতিটি ব্লগ পোস্ট এর ভিউ সংখ্যা দেখায়, আমি আমার পেজের জন্য কিছু একই ধরনের কিছু করতে চেয়েছিলাম। আমি Next.js 13 ব্যবহার করছি নতুন app router দিয়ে, কিন্তু পেজ ভিউগুলো MySQL ডেটাবেসে না রাখে আপস্ট্যাশ রেডিসে রাখব।

এখানে একটি উদাহরণ দেওয়া হলো যা আমরা বানাব। হোম পেজের প্রতিটি কার্ডে এর ভিউ সংখ্যা দেখাবে।

আপস্ট্যাশ রেডিস দিয়ে আপনার Next.js ব্লগে ভিউ কাউন্টার যোগ করুন

কেন রেডিস?

রেডিসে ইতিমধ্যে ২টি চমৎকার কমান্ড আছে যা কাউন্টার ইনক্রিমেন্ট এবং ডিডুপ্লিকেট করা সহজ করে তোলে।

আরো সঠিক কাউন্টার পেতে, আমি কাউন্টার ইনক্রিমেন্ট ডিবাউন্স করতে চাই। যদি ব্যবহারকারী পেজ রিফ্রেশ করে, কাউন্টার শুধু একবার ইনক্রিমেন্ট হওয়া উচিত। আমরা এটি রেডিসের SET কমান্ড দিয়ে খুব সহজে করতে পারি। এটিতে NX অপশন আছে যা কী শুধু তখন সেট করবে যখন এটি ইতিমধ্যে না থাকে, এবং EX অপশন যা একটি নির্দিষ্ট সেকেন্ডের পর কী এক্সপায়ার করবে। এই দুটি অপশন একসাথে ব্যবহার করে আমরা নিশ্চিত করতে পারি যে একটি নির্দিষ্ট ব্যবহারকারী প্রদত্ত টাইমফ্রেমের মধ্যে একাধিকবার কাউন্টার ইনক্রিমেন্ট করতে পারছে না।

দ্বিতীয় কমান্ড হলো INCR যা একটি দਿੱয়ে কীকে অ্যাটমিকভাবে ইনক্রিমেন্ট করে।

রেডিস সেটআপ

আপস্ট্যাশে ডেটাবেস সেটআপ করা সহজ এবং इसमें প্রতিদিন ১০ হাজার রিকোয়েস্ট ফ্রি! আপনি এখানে একটি নতুন ডেটাবেস তৈরি করতে পারেন। এটা শুধু কিছু সেকেন্ড লাগে। তারপর নিচে স্ক্রল করে REST কানেকশন সিক্রেটগুলো আপনার .env.local ফাইলে কপি করুন:

.env.local
UPSTASH_REDIS_REST_URL=
UPSTASH_REDIS_REST_TOKEN=

Next.js

এখন যেহেতু আমাদের রেডিস ডেটাবেস আছে, আমরা কাউন্টার বাস্তবায়ন শুরু করতে পারি। প্রথমে @upstash/redis ইনস্টল করুন:

pnpm add @upstash/redis

পেজ ভিউ সংরক্ষণ করার জন্য, আমাদের দুটি কম্পোনেন্ট দরকার। একটি API রুট এবং একটি ক্লায়েন্ট কম্পোনেন্ট। API রুট দিয়ে শুরু করা যাক।

/api/incr.ts

আপস্ট্যাশ এবং @upstash/redis Vercel-এর Edge ফাংশনগুলোর সাথে কম্প্যাটিবল, তাই প্রথমে আমরা প্রয়োজনীয় সব কিছু ইম্পোর্ট করব, রেডিস সেটআপ করব, এবং রানটাইম edge কনফিগার করব।

/api/incr.ts নামে একটি নতুন ফাইল তৈরি করুন এবং নিচের কোড যোগ করুন:

/api/incr.ts
import { NextRequest, NextResponse } from "next/server";
import { Redis } from "@upstash/redis";
const redis = Redis.fromEnv();
export const config = {
  runtime: "edge",
};

এরপর আমাদের রিকোয়েস্ট বডিতে একটি slug বা অনুরূপ আইডেন্টিফায়ার পাস করা থাকতে হবে। যদি না থাকে, আমরা 400 স্ট্যাটাস কোড ফেরত দেব।

/api/incr.ts
export default async function incr(req: NextRequest): Promise<NextResponse> {
  const body = await req.json();
  const slug = body.slug as string | undefined;
  if (!slug) {
    return new NextResponse("Slug not found", { status: 400 });
  }
  // আরও কোড আসবে
}

তারপর আমাদের ব্যবহারকারীর IP ঠিকানা জানতে হবে। আমরা req.ip প্রপার্টি ব্যবহার করে এটি করতে পারি। আমরা IP ঠিকানাকে SHA-256 অ্যালগরিদম দিয়ে হ্যাশ করব এবং ডেটাবেসে সংরক্ষণ করব। এইভাবে আমাদের সরাসরি IP ঠিকানা সংরক্ষণ করতে হবে না, যা নিরাপত্তা উদ্বেগের বিষয় হতে পারে।

/api/incr.ts
const ip = req.ip;
// IP হ্যাশ করে হেক্স স্ট্রিং-এ রূপান্তর
const buf = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(ip));
const hash = Array.from(new Uint8Array(buf))
  .map((b) => b.toString(16).padStart(2, "0"))
  .join("");

এখন উপরে উল্লিখিত প্রথম রেডিস কমান্ডটি ব্যবহার করি। SET কে NX এবং EX সহ ব্যবহার করলে আমরা সহজে চেক করতে পারি যে কোনো নির্দিষ্ট IP ঠিকানা গত ২৪ ঘন্টার মধ্যে কোনো পেজ দেখেছে কিনা:

/api/incr.ts
const isNew = await redis.set(["deduplicate", hash, slug].join(":"), true, {
  nx: true,
  ex: 24 * 60 * 60,
});
if (!isNew) {
  new NextResponse(null, { status: 202 });
}

শেষ কাজ হলো প্রদত্ত slug-এর জন্য কাউন্টার ইনক্রিমেন্ট করা। এর জন্য আমরা INCR কমান্ড ব্যবহার করব:

/api/incr.ts
await redis.incr(["pageviews", "projects", slug].join(":"));
return new NextResponse(null, { status: 202 });

রেফারেন্সের জন্য, সম্পূর্ণ কোড এখানে পাবেন।

/app/[slug]/view.tsx

এখন, একটি ছোট ক্লায়েন্ট কম্পোনেন্ট তৈরি করি, যা আমরা যায়গা তৈরি করা API রুটে একটি রিকোয়েস্ট পাঠাবে যখনই এটি মাউন্ট হবে। এই কম্পোনেন্টটি যেকোনো পেজে এম্বেড করা যাবে যা আমরা ট্র্যাক করতে চাই।

/app/[slug]/view.tsx
"use client";
import { useEffect } from "react";
export const ReportView: React.FC<{ slug: string }> = ({ slug }) => {
  useEffect(() => {
    fetch("/api/incr", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ slug }),
    });
  }, [slug]);
  return null;
};

/app/[slug]/page.tsx

শেষ কাজ হলো আমরা যে পেজটি ট্র্যাক করতে চাই সেটিতে ReportView কম্পোনেন্টটি যোগ করা:

/app/[slug]/page.tsx
import { ReportView } from "./view";
type Props = {
  params: { slug: string; };
};
export default function Page({ params }: Props) {
  return (
    <div>
      <ReportView slug={params.slug} />
      {/* আপনার পেজ কন্টেন্ট এখানে যোগ করুন */}
    </div>
  );
}

এখন থেকে /app/[slug]-এ সব ভিজিট ট্র্যাক হবে এবং গত ২৪ ঘন্টার মধ্যে প্রতিটি অনন্য ভিজিটরের জন্য কাউন্টার ইনক্রিমেন্ট হবে।

ভিউ প্রদর্শন

ভিউ ট্র্যাক করা ভালো, কিন্তু আমরা এগুলো পাবলিকলি প্রদর্শনও করতে চাই। দেখি কীভাবে করা যায়।

ভিউ সংখ্যা প্রদর্শন করার জন্য, আমাদের ডেটাবেস থেকে সেগুলো লুকাপ করতে হবে। আমরা GET কমান্ড ব্যবহার করে এটি করতে পারি। পেজ কম্পোনেন্টে একটি revalidate কনফিগও যোগ করা উচিত, যাতে পেজটি প্রতিটি রিকোয়েস্টের জন্য নয়, প্রতি ৬০ সেকেন্ডে রিভ্যালিডেট হয়।

/app/[slug]/page.tsx
type Props = {
  params: { slug: string; };
};
export const revalidate = 60
export default function Page({ params }: Props) {
  const views = await redis.get<number>(["pageviews", "projects", params.slug].join(":")) ?? 0
  return ...
}

শেষ কথা

এই পূর্ণ উদাহরণটি chronark-এ দেখুন। কোড GitHub-এ উপলব্ধ। নির্দিষ্টভাবে, প্রাসঙ্গিক অংশগুলো:

  • API রুট
  • ট্র্যাকিং কম্পোনেন্ট
  • ভিউ সংখ্যা লোড করা

আপনি যদি আরও পেজ ভিউ অ্যানালিটিক্সে আগ্রহী হন, দয়া করে টুইটার বা ডিসকোর্ডে আমাদের জানান।

  1. Node.js-এ 'npm ERR! missing script: start' এরর ফিক্স করার উপায়

  2. HTML-এ টেবিল সেলের প্রস্থ ও উচ্চতা সেট করা

  3. সিবর্ন + প্যান্ডাস সেকেন্ডারি Y-আক্ষসহ প্লটিং-এ গ্রিড লাইন সরানো

  4. CSS3 filter: saturation() দিয়ে ছবির স্যাচুরেশন (রঙের ঘনতা) বর্ধন/কম করা