Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Redis

เร่งความเร็วแอปพลิเคชัน Next.js ของคุณด้วย Redis

Next.js เป็นเว็บเฟรมเวิร์กที่ประสบความสำเร็จอย่างมาก ซึ่งรวบรวมการเรนเดอร์ฝั่งเซิร์ฟเวอร์และการสร้างไซต์แบบคงที่ SSG เพิ่มความเร็วเว็บไซต์ของคุณด้วยการแคช CDN ในขณะเดียวกัน SSR จะช่วยคุณในด้าน SEO และข้อมูลแบบไดนามิก

การเรนเดอร์ฝั่งเซิร์ฟเวอร์เป็นคุณสมบัติที่ยอดเยี่ยมซึ่งช่วยให้คุณเขียนแอปพลิเคชันแบบเต็มสแต็ก แต่ถ้าคุณไม่ระวัง ประสิทธิภาพของเว็บไซต์ Next.js ของคุณอาจได้รับผลกระทบได้ง่าย ในบล็อกโพสต์นี้ ฉันจะอธิบายวิธีใช้ประโยชน์จาก Redis เพื่อเพิ่มความเร็วในการเรียก Next.js API ของคุณ ก่อนหน้านั้น ฉันจะพูดถึงวิธีที่ง่ายกว่าในการปรับปรุงประสิทธิภาพของคุณโดยย่อ

ใช้ SWR ในการเรียก API ของคุณ

SWR เป็นไลบรารีดึงข้อมูลที่ชาญฉลาดมาก ใช้กลยุทธ์การทำให้แคช HTTP ใช้งานไม่ได้ (เก่าขณะตรวจสอบใหม่) ที่อธิบายโดย HTTP RFC 5861 เมื่อคุณเรียกใช้ API ด้วย SWR ข้อมูลดังกล่าวจะส่งคืนข้อมูลที่แคชไว้ทันที แต่จะดึงข้อมูลปัจจุบันและอัปเดต UI แบบอะซิงโครนัส คุณยังสามารถตั้งค่า refreshInterval โดยขึ้นอยู่กับความอดทนของคุณต่อความค้าง

const { data: user } = useSWR('/api/user', { refreshInterval: 2000 })

ในโค้ดด้านบนนี้ API ของผู้ใช้จะรีเฟรชทุกๆ 2 วินาที

การแคชด้วย Redis

SWR นั้นเรียบง่ายและมีประสิทธิภาพมาก แต่มีบางกรณีที่คุณจะต้องแคชฝั่งเซิร์ฟเวอร์:

  • การแคชฝั่งไคลเอ็นต์ช่วยเพิ่มประสิทธิภาพให้กับไคลเอ็นต์ แต่ถ้าจำนวนไคลเอนต์สูง คุณอาจพบกับการโหลดสูงในทรัพยากรฝั่งเซิร์ฟเวอร์ ซึ่งจะส่งผลต่อประสิทธิภาพฝั่งไคลเอ็นต์ในที่สุดด้วย
  • หากคุณกำลังใช้ API ภายนอกที่มีโควต้า คุณจะต้องควบคุมการใช้ API ที่ฝั่งเซิร์ฟเวอร์ มิฉะนั้น ลูกค้าจำนวนมากเกินไปจะใช้ API อย่างรวดเร็ว
  • หากคุณมีทรัพยากรที่คำนวณ ดึงข้อมูล หรือประมวลผลที่ฝั่งเซิร์ฟเวอร์โดยใช้อินพุตแบบไดนามิก การแคชฝั่งไคลเอ็นต์จะไม่มีประโยชน์มากนัก

ตัวอย่างโครงการ:Covid Tracker

ในโครงการนี้ เราจะใช้ Covid API ของ Javier Aviles และค้นหาประเทศ 10 อันดับแรกที่มีจำนวนผู้ป่วยมากที่สุด ตรวจสอบเว็บไซต์และซอร์สโค้ด

เราจะใช้ Redis เพื่อแคชการตอบสนองจาก Covid API ดังนั้น:

  • การตอบสนองจะเร็วขึ้นมาก หากคุณตรวจสอบเว็บไซต์ คุณจะเห็นว่าการเรียก Covid API นั้นใช้เวลาหลายร้อยมิลลิวินาทีในขณะที่ดึงข้อมูลจาก Redis นั้นใช้เวลา 1-2 มิลลิวินาที
  • เราจะไม่ครอบงำ Covid API ด้วยคำขอมากเกินไป

รหัส API

ก่อนอื่นโค้ดจะตรวจสอบว่าเรามีแคชผลลัพธ์ API ใน Redis หรือไม่ หากไม่ เราจะรับรายชื่อประเทศทั้งหมดจาก Covid API และจัดเรียงตามจำนวนเคสของวันปัจจุบันและบันทึก 10 อันดับแรกไปที่ Redis ขณะบันทึกไปยัง Redis เราตั้งค่าพารามิเตอร์ "EX" 60 ซึ่งหมายความว่า Redis จะลบรายการภายใน 60 วินาที

import Redis from "ioredis";

let redis = new Redis(process.env.REDIS_URL);

export default async (req, res) => {
  let start = Date.now();
  let cache = await redis.get("cache");
  cache = JSON.parse(cache);
  let result = {};
  if (cache) {
    console.log("loading from cache");
    result.data = cache;
    result.type = "redis";
    result.latency = Date.now() - start;
    return res.status(200).json(result);
  } else {
    console.log("loading from api");
    start = Date.now();
    return fetch("https://coronavirus-19-api.herokuapp.com/countries")
      .then((r) => r.json())
      .then((data) => {
        data.sort(function (a, b) {
          return b.todayCases - a.todayCases;
        });
        result.data = data.splice(1, 11);
        result.type = "api";
        result.latency = Date.now() - start;
        redis.set("cache", JSON.stringify(result.data), "EX", 60);
        return res.status(200).json(result);
      });
  }
};

รหัส UI

UI เป็นรหัสตอบโต้อย่างง่าย เราดึงข้อมูลจาก API โดยใช้ SWR

export default function Home() {
  function refresh(e) {
    e.preventDefault();
    window.location.reload();
  }
  const { data, error } = useSWR("api/data", fetcher);
  if (error) return "An error has occurred.";
  if (!data) return "Loading...";
  return (
    <div className={styles.container}>
      <Head>
        <title>Covid Tracker</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main className={styles.main}>
        <h1 className={styles.title}>Covid Tracker</h1>

        <p className={styles.description}>
          Top 10 countries with the most cases today
        </p>

        <div className={styles.grid}>
          <div className={styles.card} onClick={refresh}>
            <table className={styles.table}>
              <thead>
                <tr>
                  <th>Country</th>
                  <th>Today Cases</th>
                  <th>Today Deaths</th>
                </tr>
              </thead>
              <tbody>
                {data.data.map((item) => (
                  <tr>
                    <td>{item.country}</td>
                    <td>{item.todayCases}</td>
                    <td>{item.todayDeaths}</td>
                  </tr>
                ))}
              </tbody>
            </table>
            <br />
            <em>
              Loaded from {data.type} in <b>{data.latency}</b> milliseconds.
              Click to reload.
            </em>
          </div>
        </div>
      </main>

      <footer className={styles.footer}>
        This is a sample project for the blogpost &nbsp;
        <a
          href="https://blog.upstash.com/nextjs-caching-with-redis"
          target="_blank"
          rel="noopener noreferrer"
        >
          Speed up your Next.js application using Serverless Redis for caching.
        </a>
      </footer>
    </div>
  );
}

https://swr.vercel.app/docs/with-nextjs

https://brianlovin.com/writing/caching-api-routes-with-next-js

https://coronavirus-19-api.herokuapp.com/countries

https://github.com/javieraviles/covidAPI