项目总览
相关源文件
本页面内容基于以下源文件生成:
LunaTV 是一个基于 Next.js 构建的现代化影视聚合平台,定位为“空壳项目”,即不内置任何播放源或直播源,需要用户自行配置。该项目旨在提供一个功能完备的前端应用框架,支持多源聚合搜索、在线播放、进度同步及 PWA 离线访问等核心能力。当前版本为 100.1.2。
项目采用前后端分离架构(基于 Next.js 全栈框架),前端使用 React 进行组件化开发,后端通过 API Routes 处理业务逻辑。数据存储方面,支持 Kvrocks、Redis 或 Upstash 作为状态存储后端,实现多端观看进度同步。为了解决跨域及内容代理问题,项目还集成了基于 Cloudflare Worker 的代理服务。
核心功能与特性
LunaTV 的核心功能围绕“搜索-观看-管理”的用户体验闭环设计,主要包含以下模块:
- 多源聚合搜索:支持一次搜索即刻返回多个数据源的结果,减少用户在不同站点间切换的成本 (README.md:22-61)。
- 丰富详情页:提供完整的元数据展示,包括剧集列表、演员阵容、年份信息及剧情简介 (README.md:22-61)。
- 流畅在线播放:集成 HLS.js 处理流媒体,并使用 ArtPlayer 作为播放器内核,确保播放体验 (README.md:22-61)。
- 收藏与进度同步:利用 Kvrocks/Redis/Upstalk 存储用户数据,支持收藏影片及跨端同步播放进度 (README.md:22-61)。
- PWA 支持:具备离线缓存能力,可安装至桌面或主屏,提供接近原生的移动端体验 (README.md:22-61)。
- 响应式布局:针对桌面端和移动端设计了不同的导航模式(桌面侧边栏 + 移动底部导航),自适应各种屏幕尺寸 (README.md:22-61)。
- 智能去广告:实验性功能,尝试自动跳过视频中的切片广告 (README.md:22-61)。
技术栈概览
项目采用现代化的前端技术栈,核心依赖如下表所示:
| 分类 | 主要技术/依赖 | 版本/说明 |
|---|---|---|
| 核心框架 | Next.js | React 全栈框架,支持 SSR/SSG |
| UI 组件 | Tailwind CSS | 原子化 CSS 框架 |
| 状态管理 | Zustand | 轻量级状态管理库 |
| 播放器 | HLS.js, ArtPlayer | 流媒体处理与 UI 播放器 |
| 数据存储 | Kvrocks / Redis / Upstash | 用于存储用户进度和收藏 |
| PWA | next-pwa | Next.js 的 PWA 插件 |
| 测试 | Jest, Testing Library | 单元测试与端到端测试 |
| 代码质量 | ESLint, Prettier | 代码检查与格式化 |
技术架构与框架选型
LunaTV 的架构设计充分考虑了性能、可维护性与部署便捷性。通过配置文件分析,可以深入了解其构建与运行机制。
核心构建配置
项目使用 Next.js 的 standalone 输出模式,这是构建轻量级 Docker 镜像的关键配置 (next.config.js:1-79)。
- Standalone 模式:配置项
output: 'standalone'使得构建产物仅包含运行应用所需的最小文件集,大幅减小了 Docker 镜像体积。 - 图片优化策略:配置了
images.unoptimized: true,禁用了 Next.js 默认的图片优化服务。这通常是为了避免在 standalone 模式下依赖外部图片优化缓存服务,或者是为了减少服务器 CPU 压力,转而使用原始图片资源。 - SVG 处理:通过自定义 Webpack 配置,实现了 SVG 的双重用途:作为 URL 资源加载(
?url)或作为 React 组件直接导入(使用@svgr/webpack)。 - Polyfill 策略:在 Webpack 配置中显式设置了
net,tls,crypto等模块的 fallback 为false(next.config.js:61-66)。这表明项目运行在浏览器环境或 Node.js 环境时,不依赖这些 Node.js 核心模块,或者由运行时环境提供。
PWA 集成
项目集成了 next-pwa 以提供渐进式 Web 应用能力 (next.config.js:72-79)。
- Service Worker 生成:配置了
dest: 'public',将 Service Worker 文件输出到 public 目录。 - 开发环境处理:在开发环境下禁用了 PWA 功能 (
disable: process.env.NODE_ENV === 'development'),以便于热更新和调试。 - 用户体验:启用了
skipWaiting: true,确保新版本的 Service Worker 立即激活,避免用户需要手动刷新页面才能获取更新。
工程化与代码规范
为了保证代码质量和团队协作效率,项目配置了严格的工程化工具链。
- ESLint 规则:基于
eslint:recommended和next扩展,并集成了 TypeScript 规则。特别值得注意的是,项目配置了simple-import-sort插件,强制对 import 语句进行排序和分组 (.eslintrc.js:42-78)。这有助于保持代码整洁,减少合并冲突。 - Prettier 配置:统一了代码风格,包括使用单引号、分号结尾以及 2 空格缩进 (.prettierrc.js:1-7)。
- 测试环境:使用
next/jest创建 Jest 配置,并配置了模块路径别名(如@/指向src/),确保测试环境与源码环境一致 (jest.config.js:1-30)。
部署与运行机制
LunaTV 的部署流程设计为自动化且健壮,特别是在 Docker 容器化环境中。启动脚本 start.js 扮演了关键角色。
启动流程与生命周期管理
start.js 脚本不仅仅是启动 Node.js 服务器,它还负责初始化检查和后台任务调度 (start.js:8-90)。
- Manifest 生成:脚本首先调用
scripts/generate-manifest.js生成manifest.json文件。这是 PWA 应用的关键元数据文件,定义了应用的名称、图标和显示模式。 - 服务启动:通过
require('./server.js')直接在当前进程中启动 Next.js 的 standalone 服务器。 - 健康检查:启动后,脚本会立即开始轮询
http://localhost:3000/login(或配置的 HOSTNAME/PORT)。只有当服务器返回 2xx 状态码时,才认为启动成功 (start.js:33-45)。这种机制确保了后续任务在服务完全就绪后才执行。 - Cron 任务调度:一旦服务启动,脚本会立即执行一次 Cron 任务(通过请求
/api/cron接口),随后设置每小时执行一次的定时任务 (start.js:44-59)。这通常用于定时刷新影视源数据或清理缓存。
代理服务
为了解决浏览器的跨域限制(CORS)以及隐藏真实请求来源,项目包含了一个基于 Cloudflare Worker 的代理服务 (proxy.worker.js:6-133)。
- 请求转发:Worker 接收请求,提取路径中的目标 URL,并构造新的请求发往目标服务器。
- Header 过滤:自动过滤掉以
cf-开头的 Cloudflare 特定请求头,防止目标服务器识别请求来源 (proxy.worker.js:29-33)。 - 重定向处理:对于 3xx 重定向响应,Worker 会修改
Location头,将重定向目标重新编码回代理路径,确保用户始终通过代理访问资源 (proxy.worker.js:94-105)。 - HTML 内容重写:当响应类型为 HTML 时,Worker 会使用正则表达式替换页面中的相对路径(如
href和src),将其转换为代理路径,确保页面内的资源加载也经过代理 (proxy.worker.js:108-125)。
系统架构图
下图展示了 LunaTV 的核心模块及其依赖关系,涵盖了从客户端请求到后端服务及外部代理的完整链路。
正在加载图表渲染器...
架构说明:
- 客户端层:用户通过浏览器或安装的 PWA 应用发起请求。播放器组件负责解析和渲染视频流。
- 应用服务器:Next.js 服务器作为核心枢纽,处理页面渲染(SSR/CSR)和 API 请求。
/api/cron等接口负责后台定时任务。 - 存储层:使用 Redis 兼容存储(Kvrocks/Upstash)来持久化用户数据,支持高并发读写。
- 代理服务:Cloudflare Worker 作为中间层,拦截对影视源和视频流的请求,处理跨域问题和内容重写。
- 外部资源:实际的视频数据和元数据由第三方源提供,项目本身不存储媒体文件。
关键数据流启动与定时任务
下图详细描述了 Docker 容器启动时,系统如何初始化并建立定时任务调度机制。
正在加载图表渲染器...
流程说明:
- 初始化:
start.js首先确保 PWA 所需的manifest.json文件存在,这是应用图标和名称配置的关键。 - 服务启动:通过
require直接加载server.js,这种方式使得启动脚本和服务器运行在同一个进程,便于管理生命周期。 - 健康检查:使用轮询机制检查
/login路径。这是一个简单的存活检查,确保服务器真正准备好接受连接。 - 任务调度:一旦服务就绪,立即触发一次 Cron 任务(可能是为了预热缓存),随后进入每小时一次的常规调度循环。这种设计避免了使用额外的进程管理器(如 crontab),简化了 Docker 容器的内部逻辑。
