iT邦幫忙

2025 iThome 鐵人賽

DAY 21
0
Modern Web

手刻部落格,從設計到部署的實戰攻略系列 第 21

瀏覽計數器(三):實作計數器,Astro 整合 API

  • 分享至 

  • xImage
  •  

前一講我們討論了記錄瀏覽數的策略,透過 IP Address + HTTP User-Agent 的資訊來辨識使用者,而後制定 Session 持續的時間,只要使用者在一個頁面中互動不超過一段時間,就僅僅視為 1 個瀏覽人次。

透過這樣的方式,就能夠得到有價值的瀏覽次數。而這一講,我們更進一步來聊聊計數器的實作架構,並且看看如何整合進 Astro 的專案。

API - AWS Lambda + DynamoDB + API Gateway

針對每篇文章或頁面的瀏覽數,我們需要以下兩個 HTTP APIs

  • POST /view - 用來增加瀏覽數,當使用者每次進入、重新整理頁面,都會觸發此 Request,並且回傳最新的瀏覽數
  • GET /views?slugs={slug1},{slug2},... - 用來獲取多個頁面的瀏覽總數,在文章列表等地方會使用

要實作上述兩個 APIs,由於使用 SSG,沒有一個我們自己設計的後端伺服器,所以需要找尋其他方式來開發這些 APIs,以下簡單敘述我挑選的技術棧:

Serverless 的 AWS Lambda 就是一個我蠻喜歡的服務,所謂 Serverless 的意思就是你無需自己管理伺服器,只要聚焦在商業邏輯就好。

AWS Lambda 提供上傳 Function 的功能,可以簡單透過 Web Console 操作,也能選擇不同程式語言來實作這個 Function,最後提供一個 API Endpoint 讓你呼叫。

AWS Lambda 建立 Function 示例

*AWS Lambda 建立 Function 示例

資料庫的部分,由於部落格使用 SSG 開發,會需要讀取資料的時間只有在瀏覽頁面時,若維護一個 24 小時在跑的伺服器會有點耗成本,而且要自己維護。

所以我選用 AWS DynamoDB,一個 NoSQL 的 Key-Value 來作為資料庫,其優點就是低維運、高擴展性,而且整合 AWS Lambda 也較為容易。

我們可以建立一個簡單的 Table,使用 slug 作為主鍵,views 來記錄瀏覽數;另外開一張處理去重的 Table,用 slug+client_id 作為主鍵,lastSeen 來記錄上次瀏覽頁面時間,然後在 Labmda 中套用上一講提過的計數邏輯來達成去重的目的。

最後再透過 AWS API Gateway,新增一個 HTTP API 指向我們建立好的 Lambda Function 如 blog-page-view,最後可以得到如 https://xxx.lambda-url.ap-southeast-1.on.aws/ 這樣 URL,用以在我們的 Astro 專案中使用。

整合進 Astro

有了瀏覽數 APIs,我們可以將其整合到 Astro 的專案中,首先針對每篇部落格文章來修改。

在前幾講製作文章列表時,我們聊到透過 Astro 的 Content Collections,可以用 src/pages/blog/[id].astro 當成每篇文章的模板。

所以在這個檔案的 Frontmatter 底下,就很適合用來送出 POST /view 的 Request 來新增並且獲取最新的瀏覽數。

做法如下,加入以下這段 Snippets:

/** getStaticPaths ... **/
const { post } = Astro.props;

const API_URL = import.meta.env.PUBLIC_VIEWS_API_URL;
const API_KEY = import.meta.env.PUBLIC_VIEWS_API_KEY;

const response = await fetch(`${API_URL}/view`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', ...(API_KEY && { 'x-api-key': API_KEY }) },
  body: JSON.stringify({ slug: post.id }),
});
const { view } = await response.json();
console.log('View count:', view);

我們用 JavaScript 原生的 fetch API 來送出一個 POST Request,Body 中包入 post.id,這是我們在設定 getStaticPaths 後所得到的資訊,也就是產出的文章因為套用 src/pages/blog/[id].astro 模板所得到的 id

這個 id 也對應到 DynamoDB 中記錄瀏覽數的主鍵 slug,當此 POST Request 送出後,瀏覽器會夾帶 Client 的訊息給 Lambda 來處理去重,然後決定更新瀏覽數 + 1 與否,最終回傳新的數值。

在重新整理頁面後,就能看到 console.log 印出的瀏覽數了,最後一步便是整合進頁面顯示即可。

參考資料

  1. AWS Lambda
  2. Astro - Data Fetching

上一篇
瀏覽計數器(二):計數策略,怎麼避免短時間內的重複瀏覽?
下一篇
網站能見度(一):淺談 SEO 及 Open Graph
系列文
手刻部落格,從設計到部署的實戰攻略23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言