文章摘要
加载中...|
此内容根据文章生成,并经过人工审核,仅用于文章内容的解释与总结 投诉

缘由

其实这个项目算是一时兴起而来的,某一天突然想搞一个像 今日热榜 这样的网站,于是这个项目就诞生了。

最初时,由于对于 Node.js 了解得不够多,就草草选择了 Koa 框架作为了文件路由,并且没有采用 TypeScript,随着更多的小伙伴的参与开发后,当初随手写的路由框架就显得杂乱不堪了,并且也造成了一些维护上的问题,这时候重构就得提上日程了,虽然不是必需,但是我还是抽空花了几周时间将整个项目重写了一下。

重构

koa -> Hono

了解到这个 Hono 框架还是从 DIYgod 大佬写的一篇文章:一个六岁开源项目的崩溃与新生 中了解到的,看了官网和文档后,我也觉得这个框架不错,并且它还支持在多个平台上运行( 后面发现没这么简单 ),于是就着手替换。

这无疑是一个大工程,Hono 的中间件和 APIKoa 完全不同,需要重写原项目的所有路由和中间件,这算得上是一个大工程了。

JavaScript -> TypeScript

LanguagesLanguages

引入 TypeScript 主要是为了给项目增加类型安全性和更好的开发体验。在单人开发的项目中,使用 JavaScript 或者 TypeScript 其实没并没有什么区别,无非是少了一些编辑器的提示罢了,甚至可以说是多此一举,但是一旦项目开源,有其他开发者参与进来后,由于每个人的写法都可能不一样,这样就会导致后期难以维护,于是使用了 TypeScript 来保持代码的一致,和保持后续贡献的路由代码质量不至于太糟糕。

CommonJS -> ESM

ESM 是原生 JavaScript 模块系统,在现代浏览器中可以直接运行,同时 Node.js 也对此有支持。本项目当然也要跟上时代,于是全面更改为 ESM 模式( 主要是 ESM 支持了动态导入,可以实现路由文件的按需加载 )

HTML -> JSX

没办法,Hono 对原生的 HTML 支持性不太好( 也可能是我还不太会用 Hono ),只能使用 JSX 来实现一些静态页面,比如项目的启动首页和报错页面等。

新的功能

RSS

新版本支持了 RSS 模式,就是可以在各大阅读器中直接阅读热榜数据了。只需在请求的网址后面加上参数 rss=true 即可,例如:

bash
GET https://www.example.com/bilibili?rss=true

Limit

由于部分榜单返回的数据量过多,特地添加了一个 limit 限制,你可以在请求的网址后面加上参数 limit=20 即可,例如:

bash
GET https://www.example.com/bilibili?limit=20

这样如果榜单的数据大于20条,就只会返回前 20 条数据。

获取最新数据

WARNING

注意,请勿频繁使用该功能调用接口,否则你将可能会遇到被封禁 IP 等其他问题

由于保证项目的稳定,采用了 60 分钟的缓存,在首次获取到原数据后,会将原数据缓存起来,在后续请求时,若未超出缓存时长,将直接采用缓存数据。但是如果你需要数据的时效性,你可以在请求的网址后面加上参数 cache=false 即可,这样每次请求时,都将返回最新数据,例如:

bash
GET https://www.example.com/bilibili?cache=false

新的路由

由于原本的路由文件过于繁杂,非常不便于后续的开发和维护,于是在本次重构时,对路由文件做出了重大修改:

  • 现在所有路由文件都位于项目根目录下的 src/routes/ 目录中,网址路径以文件名为准。
  • 基本所有的路由都采用如下规则,后续贡献路由将以下方代码为准:
ts
// 最终导出的方法
// 接受传入参数并返回出最终列表数据
export const handleRoute = async (c: ListContext, noCache: boolean) => {
  // 接受传入参数,网址 ? 后面的参数
  const type = c.req.query("type") || "0";
  // 获取返回的结果
  const { fromCache, data, updateTime } = await getList({ type }, noCache);
  // 生成最终数据
  const routeData: RouterData = {
    name: "bilibili",
    title: "哔哩哔哩",
    type: "热门榜",
    description: "你所热爱的,就是你的生活",
    parameData: {},
    link: "https://www.bilibili.com/v/popular/rank/all",
    total: data?.length || 0,
    updateTime,
    fromCache,
    data,
  };
  return routeData;
};

// 这里是获取数据的方法
// 可能采用调用接口或者网页爬虫的方式
const getList = async (options: Options, noCache: boolean) => {
  // 根据传入的参数来构建出请求的网址
  const { type } = options;
  const url = `https://api.bilibili.com/x/web-interface/ranking/v2?rid=${type}`;
  // 发送请求获取地址数据
  const result = await get({
    url,
    headers: {
      Referer: `https://www.bilibili.com/ranking/all`,
    },
    noCache,
  });
  // 解析出列表原数据
  const list = result.data.data.list;
  return {
    // 是否来自缓存
    fromCache: result.fromCache,
    // 数据更新时间
    updateTime: result.updateTime,
    // 最终的列表数据
    data: list.map((v: RouterType["bilibili"]) => ({
      id: v.bvid, // 唯一性 ID
      title: v.title, // 文章标题
      desc: v.desc, // 文章介绍
      cover: v.pic.replace(/http:/, "https:"), // 文章封面
      author: v.owner.name, // 文章作者
      hot: v.stat.view, // 热门数据
      url: v.short_link_v2 || `https://www.bilibili.com/video/${v.bvid}`, // 文章地址
      mobileUrl: `https://m.bilibili.com/video/${v.bvid}`, // 文章移动端地址
    })),
  };
};

关于部署

在一切都重构完成后,出现了一点小插曲,原来的 Vercel 部署方法不再适用了,所以目前对于 Vercel 部署支持暂时下线,待日后搞定了之后再说,如果目前仅能通过 Vercel 进行部署的小伙伴请不要更新到新版本 v2.0.0,请谅解。

当然,其他部署方式一切正常,在此还是推荐使用 Docker 方式进行部署,这种方式不易发生问题,并且过程十分简单,全程只需两行命令。

Docker 部署

安装及配置 Docker 将不在此处说明,请自行解决

本地构建

bash
# 构建
docker build -t dailyhot-api .
# 运行
docker run -p 6688:6688 -d dailyhot-api
# 或使用 Docker Compose
docker-compose up -d

在线部署

bash
# 拉取
docker pull imsyy/dailyhot-api:latest
# 运行
docker run -p 6688:6688 -d imsyy/dailyhot-api:latest

手动部署

最直接的方式,可以按照以下步骤部署在任何地方

安装

bash
git clone https://github.com/imsyy/DailyHotApi.git
cd DailyHotApi

然后再执行安装依赖

bash
npm install

开发

bash
npm run dev

成功启动后程序会在控制台输出可访问的地址

编译运行

bash
npm run build
npm run start

成功启动后程序会在控制台输出可访问的地址

Railway 部署

本项目支持使用 Railway 一键部署,请先将本项目 fork 到您的仓库中,即可使用一键部署。

Zeabur 部署

本项目支持使用 Zeabur 一键部署,请先将本项目 fork 到您的仓库中,即可使用一键部署。

赞赏博主
感谢您赐予我前进的力量
微信 微信
支付宝 支付宝
评论 隐私政策