emfont 官方文件

背後原理

emfont 的運行原理。

當你 clone 下專案,執行 pnpm ipnpm start 之後 emfont 會做這些事:

初始化

基本設定和套件引入

先讓網站跑得起來,但還在載入中無法提供服務。可以先用 console 狀態,之後可以在網頁顯示 loading 之類的。

  • 引入 Fastify, EJS, JWT, Cookie 等
  • 中間件註冊
  • 路由註冊
  • 連結 Redis, PostgreSQL, MinIO, R2

處裡字體檔案

這些事除了開機時以外也會自己定期檢查或是手動按鈕檢查。

  • 從 Database 抓取字體資料列表
  • 從 minIO 抓取檔案列表
  • 從 R2 抓取檔案列表

都抓到之後互相比較:

  1. 列出所有 Database 有的字體
  2. 檔案在不在 MinIO - 沒有的話跳警告,在 Database 標記忽略字體
  3. 檔案在不在 local - 要比較 hash,沒有或是錯誤的話從 minIO 下載
  4. 有沒有突然出現在 minIO 但 Database 不認識的字體 - 跳警告,先不要用,也先不要自動生成資料庫
  5. 有沒有超過定期重切時間 - 有的話全部重切。
  6. 檢查 R2 有沒有切好的字體 - 沒有的話新鮮現切然後丟 R2
  7. 檢查字體是否有更新 - 自動去 GitHub Release 抓,其他的手動。有的話通知 (有一個頁面或著是 Webhook)
  8. 檢查 R2 的極致壓縮是否都有紀錄在 Database - R2, Database 任意一個有少都直接刪除,反正重新生成也很快。
  9. 檢查 R2 有沒有每一個純 CSS 載入字體的 CSS - 沒有的話重新生成 (就字串組合) 然後丟去 R2。

執行

當上面的初始話處裡好的之後就可以開始提供 Webfont 服務:

文檔

/_next, /docs

Caddy 會自動 reverse proxy 去 Next.js 的靜態網頁。

字體服務

記得要紀錄每次請求情況。

載入整個字體

重新導向去 Cloudflare R2。

載入指定文字 (極致壓縮 / 切好的字體)

API 請求要那些字體跟文字回傳 Json 或是 CSS

  • https://font.emtech.cc/css/ 會回傳 CSS

  • https://font.emtech.cc/g/ 會回傳 JSON

  • 靜態: 固定切好得檔案

  • 動態: 單獨生成指定文字的檔案

    • 如果 Radis 紀錄被使用超過 3 次則暫存 R2, 30 天沒人使用(或是硬碟空間不夠)就刪除。

要去 PostgreSQL 之前都先去看看 Radis 有沒有快取,如果沒有去 PostgreSQL 然後自己搞。

Radis

Radis 簡單來說就是快取,因為存在記憶體所以可以讀寫比 PostgreSQL 更快。讀過的資料就存去 Redis 先放著。這部分我看我們還沒處裡可以先空著沒關係,就先都去 SQL 抓。

async function getFontRequests(userId) {
    // 先檢查 Redis
    const cacheKey = `font_requests:${userId}`;
    const cachedData = await redis.get(cacheKey);
    
    if (cachedData) {
        return JSON.parse(cachedData);
    }
    
    // 如果 Redis 沒有,從 PostgreSQL 查詢
    const result = await db.query('SELECT * FROM font_requests WHERE user_id = $1', [userId]);
    
    // 存入 Redis(設定 5 分鐘過期)
    await redis.setex(cacheKey, 300, JSON.stringify(result.rows));
    
    return result.rows;
}

On this page