Xây dựng một trình đọc RSS tĩnh để chống lại FOMO bên trong bạn

theanh

Administrator
Nhân viên
Trong một ngành công nghiệp phát triển nhanh như công nghệ, thật khó để đối phó với nỗi sợ bỏ lỡ tin tức quan trọng. Nhưng, như nhiều người trong chúng ta biết, có một lượng thông tin khổng lồ xuất hiện hàng ngày và việc tìm đúng thời điểm và sự cân bằng để theo kịp có thể rất khó khăn, nếu không muốn nói là căng thẳng. Một công nghệ cổ điển như nguồn cấp RSS là một cách thú vị để lấy lại quyền sở hữu thời gian của chính chúng ta. Trong bài viết này, chúng ta sẽ tạo một trình đọc Really Simple Syndication (RSS) tĩnh, trình đọc này sẽ cung cấp cho bạn tin tức tuyển chọn mới nhất chỉ một lần (vâng: một lần) mỗi ngày.

Rõ ràng là chúng ta sẽ làm việc với công nghệ RSS trong quá trình này, nhưng chúng ta cũng sẽ kết hợp nó với một số thứ mà có thể bạn chưa từng thử trước đây, bao gồm Astro (khung trang web tĩnh), TypeScript (dành cho các tiện ích JavaScript), một gói có tên là rss-parser (để kết nối mọi thứ với nhau), cũng như các hàm được lên lịchcác móc xây dựng do Netlify cung cấp (mặc dù có những dịch vụ khác thực hiện việc này).

Tôi chọn những công nghệ này chỉ vì tôi thực sự, thực sự thích chúng! Có thể có những giải pháp khác hiệu quả hơn, đi kèm với nhiều tính năng hơn hoặc đơn giản là thoải mái hơn đối với bạn — và trong những trường hợp đó, tôi khuyến khích bạn hoán đổi bất cứ thứ gì bạn muốn. Điều quan trọng nhất là có được kết quả cuối cùng!

Kế hoạch​

Đây là cách thức thực hiện. Astro tạo trang web. Tôi đã đưa ra quyết định cố ý sử dụng một trang web tĩnh vì tôi muốn các nguồn cấp RSS khác nhau chỉ được lấy một lần trong thời gian xây dựng và đó là điều chúng tôi có thể kiểm soát mỗi khi trang web được "xây dựng lại" và triển khai lại với các bản cập nhật. Đó là lúc các chức năng theo lịch trình của Netlify phát huy tác dụng, vì chúng cho phép chúng tôi kích hoạt việc xây dựng lại tự động vào những thời điểm cụ thể. Không cần phải kiểm tra thủ công các bản cập nhật và triển khai chúng! Các tác vụ Cron cũng có thể dễ dàng thực hiện việc này nếu bạn thích giải pháp phía máy chủ.

Trong quá trình xây dựng lại được kích hoạt, chúng tôi sẽ để gói rss-parser thực hiện chính xác những gì nó nói: phân tích cú pháp danh sách các nguồn cấp RSS có trong một mảng. Gói này cũng cho phép chúng tôi đặt bộ lọc cho các kết quả đã lấy để chúng tôi chỉ lấy những kết quả từ ngày hôm qua, tuần trước, v.v. Cá nhân tôi chỉ hiển thị tin tức trong bảy ngày qua để tránh quá tải nội dung. Chúng ta sẽ đến đó!

Nhưng trước tiên…

RSS là gì?​

RSS là công nghệ nguồn cấp dữ liệu web mà bạn có thể đưa vào trình đọc hoặc trình tổng hợp tin tức. Vì RSS được chuẩn hóa, nên bạn biết phải mong đợi điều gì khi nói đến định dạng của nguồn cấp dữ liệu. Điều đó có nghĩa là chúng ta có rất nhiều khả năng thú vị khi xử lý dữ liệu mà nguồn cấp dữ liệu cung cấp. Hầu hết các trang web tin tức đều có nguồn cấp dữ liệu RSS riêng mà bạn có thể đăng ký (đây là nguồn cấp dữ liệu RSS của Tạp chí Smashing: https://www.smashingmagazine.com/feed/). Nguồn cấp dữ liệu RSS có khả năng cập nhật mỗi khi một trang web xuất bản nội dung mới, nghĩa là nó có thể là nguồn tin tức mới nhất nhanh chóng, nhưng chúng ta cũng có thể tùy chỉnh tần suất đó.

Nguồn cấp dữ liệu RSS được viết theo định dạng Ngôn ngữ đánh dấu mở rộng (XML) và có các thành phần cụ thể có thể được sử dụng trong đó. Thay vì tập trung quá nhiều vào các chi tiết kỹ thuật ở đây, tôi sẽ cung cấp cho bạn một liên kết đến thông số kỹ thuật RSS. Đừng lo lắng; trang đó sẽ đủ dễ quét để bạn tìm thấy thông tin phù hợp nhất mà bạn cần, chẳng hạn như các loại phần tử được hỗ trợ và chúng biểu thị điều gì. Đối với hướng dẫn này, chúng tôi chỉ sử dụng các phần tử sau: , [*] , , . Chúng tôi cũng sẽ để gói trình phân tích cú pháp RSS thực hiện một số công việc cho chúng tôi.

Tạo trang web State​

Chúng ta sẽ bắt đầu bằng cách tạo trang web Astro của mình! Trong thiết bị đầu cuối của bạn, hãy chạy pnpm create astro@latest. Bạn có thể sử dụng bất kỳ trình quản lý gói nào bạn muốn — Tôi chỉ đang thử pnpm cho chính mình.

Sau khi chạy lệnh, trình trợ giúp dựa trên trò chuyện của Astro, Houston, sẽ hướng dẫn một số câu hỏi thiết lập để bắt đầu mọi thứ.
Mã:
astro Trình tự khởi chạy được khởi tạo. dir Chúng ta nên tạo dự án mới của bạn ở đâu? ./rss-buddy tmpl Bạn muốn bắt đầu dự án mới của mình như thế nào? Bao gồm các tệp mẫu ts Bạn có định viết TypeScript không? Có sử dụng TypeScript nên nghiêm ngặt đến mức nào? Cài đặt phụ thuộc nghiêm ngặt? Có git Khởi tạo kho lưu trữ git mới? Có
Tôi thích sử dụng các tệp mẫu của Astro để có thể bắt đầu nhanh chóng, nhưng chúng ta sẽ dọn dẹp chúng một chút trong quá trình này. Hãy dọn dẹp tệp src/pages/index.astro bằng cách xóa mọi thứ bên trong các thẻ . Sau đó, chúng ta đã sẵn sàng!

Từ đó, chúng ta có thể xoay vòng mọi thứ bằng cách chạy pnpm start. Thiết bị đầu cuối của bạn sẽ cho bạn biết địa chỉ máy chủ cục bộ nào bạn có thể tìm thấy trang web của mình.

Lấy thông tin từ nguồn cấp dữ liệu RSS​

Tệp src/pages/index.astro là nơi chúng ta sẽ tạo một mảng các nguồn cấp dữ liệu RSS mà chúng ta muốn theo dõi. Chúng ta sẽ sử dụng cú pháp mẫu của Astro, vì vậy giữa hai hàng rào mã (—), hãy tạo một mảng feedSources và thêm một số nguồn cấp dữ liệu. Nếu bạn cần cảm hứng, bạn có thể sao chép mã này:
Mã:
const feedSources = [ 'https://www.smashingmagazine.com/feed/', 'https://developer.mozilla.org/en-US/blog/rss.xml', // v.v.]
Bây giờ chúng ta sẽ cài đặt gói rss-parser trong dự án của mình bằng cách chạy pnpm install rss-parser. Gói này là một thư viện nhỏ chuyển đổi XML mà chúng ta nhận được từ việc tải nguồn cấp dữ liệu RSS thành các đối tượng JavaScript. Điều này giúp chúng ta dễ dàng đọc nguồn cấp RSS và thao tác dữ liệu theo bất kỳ cách nào chúng ta muốn.

Sau khi cài đặt gói, hãy mở tệp src/pages/index.astro và ở trên cùng, chúng ta sẽ nhập rss-parser và khởi tạo lớp Partner.
Mã:
import Parser from 'rss-parser';const parser = new Parser();
Chúng ta sử dụng trình phân tích cú pháp này để đọc nguồn cấp RSS và (thật bất ngờ!) phân tích cú pháp chúng thành JavaScript. Chúng ta sẽ xử lý danh sách các lời hứa ở đây. Thông thường, tôi có thể sẽ sử dụng Promise.all(), nhưng vấn đề là, đây được cho là một trải nghiệm phức tạp. Nếu một trong các nguồn cấp không hoạt động vì lý do nào đó, tôi muốn bỏ qua nó.

Tại sao? Vâng, vì Promise.all() từ chối mọi thứ ngay cả khi chỉ có một trong những lời hứa của nó bị từ chối. Điều đó có nghĩa là nếu một nguồn cấp dữ liệu không hoạt động theo cách tôi mong đợi, toàn bộ trang của tôi sẽ trống khi tôi lấy đồ uống nóng để đọc tin tức vào buổi sáng. Tôi không muốn bắt đầu ngày mới của mình bằng một lỗi.

Thay vào đó, tôi sẽ chọn sử dụng Promise.allSettled(). Phương pháp này thực sự sẽ cho phép tất cả các lời hứa hoàn thành ngay cả khi một trong số chúng không thành công. Trong trường hợp của chúng tôi, điều này có nghĩa là bất kỳ nguồn cấp dữ liệu nào có lỗi sẽ chỉ bị bỏ qua, điều này thật hoàn hảo.

Hãy thêm điều này vào tệp src/pages/index.astro:
Mã:
interface FeedItem { feed?: string; title?: string; link?: string; date?: Date;}const feedItems: FeedItem[] = [];await Promise.allSettled( feedSources.map(async (source) => { try { const feed = await parser.parseURL(source); feed.items.forEach((item) => { const date = item.pubDate ? new Date(item.pubDate) : undefined; feedItems.push({ feed: feed.title, title: item.title, link: item.link, date, }); }); } catch (error) { console.error(`Error fetching feed from ${source}:`, error); } }));
Điều này tạo ra một mảng (hoặc nhiều hơn) có tên là feedItems. Đối với mỗi URL trong mảng feedSources mà chúng ta đã tạo trước đó, trình phân tích cú pháp rss sẽ truy xuất các mục và, vâng, phân tích chúng thành JavaScript. Sau đó, chúng ta trả về bất kỳ dữ liệu nào chúng ta muốn! Chúng tôi sẽ giữ mọi thứ đơn giản ngay bây giờ và chỉ trả về những thông tin sau:
  • Tiêu đề nguồn cấp dữ liệu,
  • Tiêu đề của mục nguồn cấp dữ liệu,
  • Liên kết đến mục,
  • Và ngày xuất bản của mục.
Bước tiếp theo là đảm bảo rằng tất cả các mục được sắp xếp theo ngày để chúng ta thực sự có được tin tức "mới nhất". Thêm đoạn mã nhỏ này vào công việc của chúng ta:
Mã:
const sortedFeedItems = feedItems.sort((a, b) => (b.date ?? new Date()).getTime() - (a.date ?? new Date()).getTime());
Ồ, và… bạn còn nhớ khi tôi nói rằng tôi không muốn trình đọc RSS này hiển thị bất kỳ nội dung nào cũ hơn bảy ngày không? Hãy giải quyết vấn đề đó ngay bây giờ vì chúng ta đã ở trong đoạn mã này.

Chúng ta sẽ tạo một biến mới có tên là sevenDaysAgo và gán cho nó một ngày. Sau đó, chúng ta sẽ đặt ngày đó thành bảy ngày trước và sử dụng logic đó trước khi thêm một mục mới vào mảng feedItems của chúng ta.

Đây là giao diện của tệp src/pages/index.astro tại thời điểm này:
Mã:
---import Layout from '../layouts/Layout.astro';import Parser from 'rss-parser';const parser = new Parser();const sevenDaysAgo = new Date();sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);const feedSources = [ 'https://www.smashingmagazine.com/feed/', 'https://developer.mozilla.org/en-US/blog/rss.xml',]interface FeedItem { feed?: string; title?: string; link?: string; date?: Date;}const feedItems: FeedItem[] = [];await Promise.allSettled( feedSources.map(async (nguồn) => { thử { const feed = await parser.parseURL(nguồn); feed.items.forEach((mục) => { const date = item.pubDate ? new Date(item.pubDate) : undefined; if (ngày && ngày >= sevenDaysAgo) { feedItems.push({ feed: feed.title, title: item.title, link: item.link, date, }); } }); } catch (lỗi) { console.error(`Lỗi khi tìm nạp nguồn cấp dữ liệu từ ${nguồn}:`, lỗi); } }));const sortedFeedItems = feedItems.sort((a, b) => (b.date ?? new Date()).getTime() - (a.date ?? new Date()).getTime());---

Kết xuất dữ liệu XML​

Đã đến lúc hiển thị các bài viết tin tức của chúng tôi trên trang Astro! Để đơn giản, chúng tôi sẽ định dạng các mục theo danh sách không có thứ tự thay vì một số bố cục lạ mắt khác.

Tất cả những gì chúng ta cần làm là cập nhật phần tử trong tệp bằng các đối tượng XML được rải rác cho tiêu đề, URL và ngày xuất bản của mục nguồn cấp dữ liệu.
Mã:
  {sortedFeedItems.map(item => ( [LIST] 
[*]  {item.title} 
{item.feed}
 
{item.date}
  [/LIST] ))}
Tiếp tục và chạy pnpm start từ thiết bị đầu cuối. Trang sẽ hiển thị danh sách các mục nguồn cấp dữ liệu không theo thứ tự. Tất nhiên, mọi thứ đều được định dạng tại thời điểm này, nhưng may mắn thay, bạn có thể làm cho nó trông chính xác như bạn muốn bằng CSS!

Và hãy nhớ rằng thậm chí còn có nhiều trường hơn nữa có sẵn trong XML cho mỗi mục nếu bạn muốn hiển thị nhiều thông tin hơn. Nếu bạn chạy đoạn mã sau trong bảng điều khiển DevTools, bạn sẽ thấy tất cả các trường bạn có thể sử dụng:
Mã:
feed.items.forEach(item => {}

Lên lịch xây dựng trang web tĩnh hàng ngày​

Chúng ta sắp hoàn tất! Các nguồn cấp dữ liệu đang được tải xuống và chúng đang trả về dữ liệu cho chúng ta bằng JavaScript để sử dụng trong mẫu trang Astro của chúng ta. Vì các nguồn cấp dữ liệu được cập nhật bất cứ khi nào nội dung mới được xuất bản, nên chúng ta cần một cách để tải các mục mới nhất từ nguồn cấp dữ liệu đó.

Chúng ta muốn tránh thực hiện bất kỳ thao tác nào trong số này theo cách thủ công. Vì vậy, hãy đặt trang web này trên Netlify để có quyền truy cập vào các hàm được lên lịch của họ kích hoạt quá trình xây dựng lại và các móc dựng của họ thực hiện quá trình xây dựng. Một lần nữa, các dịch vụ khác thực hiện việc này và bạn có thể triển khai công việc này với một nhà cung cấp khác — Tôi chỉ thiên vị Netlify vì tôi làm việc ở đó. Trong mọi trường hợp, bạn có thể làm theo Tài liệu hướng dẫn của Netlify về thiết lập một trang web mới.

Sau khi trang web của bạn được lưu trữ và hoạt động, bạn đã sẵn sàng để lên lịch xây dựng lại. móc xây dựng cung cấp cho bạn một URL để sử dụng để kích hoạt bản dựng mới, trông giống như thế này:
Mã:
https://api.netlify.com/build_hooks/your-build-hook-id
Chúng ta hãy kích hoạt bản dựng vào lúc nửa đêm hàng ngày. Chúng ta sẽ sử dụng các hàm được lên lịch của Netlify. Đó thực sự là lý do tại sao tôi sử dụng Netlify để lưu trữ điều này ngay từ đầu. Việc chuẩn bị sẵn chúng thông qua máy chủ giúp đơn giản hóa mọi thứ rất nhiều vì không cần phải làm việc với máy chủ hay cấu hình phức tạp để thực hiện việc này. Chỉ cần thiết lập và quên nó đi!

Chúng ta sẽ cài đặt @netlify/functions (hướng dẫn) vào dự án rồi tạo tệp sau trong thư mục gốc của dự án: netlify/functions/deploy.ts.

Đây là những gì chúng ta muốn thêm vào tệp đó:
Mã:
// netlify/functions/deploy.tsimport type { Config } from '@netlify/functions';const BUILD_HOOK = 'https://api.netlify.com/build_hooks/your-build-hook-id'; // thay thế tôi!xuất mặc định async (req: Yêu cầu) => { chờ lấy (BUILD_HOOK, { phương thức: 'POST', })};xuất const cấu hình: Cấu hình = { lịch trình: '0 0 * * *',};
Nếu bạn cam kết mã của mình và đẩy nó, trang web của bạn sẽ tự động triển khai lại. Từ thời điểm đó trở đi, nó sẽ tuân theo một lịch trình xây dựng lại trang web mỗi ngày vào lúc nửa đêm, sẵn sàng để bạn uống cà phê buổi sáng và bắt kịp mọi thứ mà bạn cho là quan trọng.
 
Back
Bên trên