Skip to content

Commit 99334ed

Browse files
committed
perf: 优化前端性能和资源加载
- 将Font Awesome加载移至body底部提升页面渲染性能 - 为关键图片添加fetchpriority="high"属性优化LCP - 实现静态文件缓存中间件,设置24小时缓存头 - 优化图片懒加载策略,优先加载首屏内容 - 改进Actix静态文件服务配置,启用ETag和Last-Modified
1 parent 72965d5 commit 99334ed

6 files changed

Lines changed: 119 additions & 19 deletions

File tree

.DS_Store

0 Bytes
Binary file not shown.

src/main.rs

Lines changed: 84 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,88 @@ use admin_handlers::{
1616
batch_delete_vods, create_collection, create_config, create_indexes, create_or_update_binding,
1717
create_type, create_vod, delete_binding, delete_collection, delete_config, delete_type,
1818
delete_vod, get_bindings, get_collect_progress, get_collection_binding_status, get_collections,
19-
get_config_by_key, get_configs, get_index_status, get_indexes_data, get_running_tasks, get_scheduled_task_logs,
20-
get_scheduled_task_status, get_statistics, get_types, get_vods_admin, list_indexes, start_collection_collect,
21-
start_scheduled_task, stop_collect_task, stop_scheduled_task, update_collection, update_config,
22-
update_scheduled_task_config, update_type, update_vod,
19+
get_config_by_key, get_configs, get_index_status, get_indexes_data, get_running_tasks,
20+
get_scheduled_task_logs, get_scheduled_task_status, get_statistics, get_types, get_vods_admin,
21+
list_indexes, start_collection_collect, start_scheduled_task, stop_collect_task,
22+
stop_scheduled_task, update_collection, update_config, update_scheduled_task_config,
23+
update_type, update_vod,
2324
};
2425
use collect_handlers::{get_collect_categories, get_collect_videos, start_collect_task};
2526
use site_data::SiteDataManager;
2627

2728
use actix_files::Files;
2829
use actix_session::{storage::CookieSessionStore, SessionMiddleware};
2930
use actix_web::cookie::Key;
30-
use actix_web::{get, web, App, HttpResponse, HttpServer, Responder};
31+
use actix_web::dev::{forward_ready, Service, Transform};
32+
use actix_web::http::header::{HeaderValue, CACHE_CONTROL};
33+
use actix_web::{
34+
dev::{ServiceRequest, ServiceResponse},
35+
get, web, App, Error, HttpResponse, HttpServer, Responder, Result,
36+
};
3137
use actix_web_flash_messages::{storage::CookieMessageStore, FlashMessagesFramework};
3238
use futures::stream::TryStreamExt;
3339
use mongodb::Database;
40+
use std::future::{ready, Ready};
41+
use std::rc::Rc;
42+
43+
// Static file cache middleware
44+
pub struct StaticCacheMiddleware;
45+
46+
impl<S, B> Transform<S, ServiceRequest> for StaticCacheMiddleware
47+
where
48+
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
49+
S::Future: 'static,
50+
B: 'static,
51+
{
52+
type Response = ServiceResponse<B>;
53+
type Error = Error;
54+
type InitError = ();
55+
type Transform = StaticCacheMiddlewareService<S>;
56+
type Future = Ready<Result<Self::Transform, Self::InitError>>;
57+
58+
fn new_transform(&self, service: S) -> Self::Future {
59+
ready(Ok(StaticCacheMiddlewareService {
60+
service: Rc::new(service),
61+
}))
62+
}
63+
}
64+
65+
pub struct StaticCacheMiddlewareService<S> {
66+
service: Rc<S>,
67+
}
68+
69+
impl<S, B> Service<ServiceRequest> for StaticCacheMiddlewareService<S>
70+
where
71+
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
72+
S::Future: 'static,
73+
B: 'static,
74+
{
75+
type Response = ServiceResponse<B>;
76+
type Error = Error;
77+
type Future =
78+
std::pin::Pin<Box<dyn std::future::Future<Output = Result<Self::Response, Self::Error>>>>;
79+
80+
forward_ready!(service);
81+
82+
fn call(&self, req: ServiceRequest) -> Self::Future {
83+
let service = self.service.clone();
84+
85+
Box::pin(async move {
86+
let is_static = req.path().starts_with("/static/");
87+
let mut res = service.call(req).await?;
88+
89+
if is_static {
90+
// Set cache headers for static files (24 hours)
91+
res.headers_mut().insert(
92+
CACHE_CONTROL,
93+
HeaderValue::from_static("public, max-age=86400"),
94+
);
95+
}
96+
97+
Ok(res)
98+
})
99+
}
100+
}
34101

35102
// Handler to get a list of vods
36103
#[get("/vods")]
@@ -114,7 +181,8 @@ async fn main() -> std::io::Result<()> {
114181

115182
// 初始化定时任务配置
116183
println!("🔧 正在初始化定时任务配置...");
117-
let scheduled_task_manager = std::sync::Arc::new(scheduled_task::ScheduledTaskManager::new(db.clone()));
184+
let scheduled_task_manager =
185+
std::sync::Arc::new(scheduled_task::ScheduledTaskManager::new(db.clone()));
118186
match scheduled_task_manager.initialize_config().await {
119187
Ok(_) => {
120188
println!("✅ 定时任务配置初始化完成");
@@ -137,6 +205,8 @@ async fn main() -> std::io::Result<()> {
137205
.app_data(web::Data::new(site_data_manager.clone()))
138206
// Store the scheduled task manager in the application state
139207
.app_data(web::Data::new(scheduled_task_manager.clone()))
208+
// Static file cache middleware
209+
.wrap(StaticCacheMiddleware)
140210
// Session and Flash Messages Middleware
141211
.wrap(
142212
FlashMessagesFramework::builder(
@@ -169,8 +239,14 @@ async fn main() -> std::io::Result<()> {
169239
web::resource("/search")
170240
.route(web::get().to(web_handlers::search_page_handler_wrapper)),
171241
)
172-
// Static files
173-
.service(Files::new("/static", "./static").show_files_listing())
242+
// Static files with cache configuration
243+
.service(
244+
Files::new("/static", "./static")
245+
.show_files_listing()
246+
.use_etag(true)
247+
.use_last_modified(true)
248+
.prefer_utf8(true),
249+
)
174250
// Admin Web routes
175251
.service(
176252
web::resource("/admin/login")

templates/base.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@
1010
<meta name="keywords" content="{% block keywords %}{{ SITEKEYWORDS | default(value=" 视频,电影,电视剧,综艺,动漫") }}{% endblock
1111
keywords %}">
1212

13-
<!-- Font Awesome -->
14-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
15-
1613
<!-- Custom CSS -->
1714
<link href="/static/css/output.css" rel="stylesheet">
1815

@@ -76,6 +73,9 @@
7673
</div>
7774
</footer>
7875

76+
<!-- Font Awesome - loaded before closing body for better performance -->
77+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
78+
7979
<!-- JavaScript -->
8080
<script src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js" defer></script>
8181
<script src="/static/js/app.js"></script>

templates/detail.html

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
{% block description %}{{ video.vod_name }}{% if video.vod_year %}({{ video.vod_year }}){% endif %} - {% if
55
video.vod_area %}{{ video.vod_area }}{% endif %}{{ video.vod_director }}导演,{{ video.vod_actor }}主演。{{ video.vod_content
66
| striptags | truncate(length=100) }} - {{ SITENAME }}{% endblock description %}
7-
{% block keywords %}{{ video.vod_name }},在线观看,免费观看,{{ video.vod_year }},{{ video.vod_area }},{{ video.vod_director }},{{ video.vod_actor }},{{ SITEKEYWORDS | default(value="") }}{% endblock keywords %}
7+
{% block keywords %}{{ video.vod_name }},在线观看,免费观看,{{ video.vod_year }},{{ video.vod_area }},{{ video.vod_director }},{{
8+
video.vod_actor }},{{ SITEKEYWORDS | default(value="") }}{% endblock keywords %}
89

910
{% block head %}
1011
<style>
@@ -110,7 +111,8 @@
110111
<div class="flex-shrink-0">
111112
<div class="relative group">
112113
<img src="{{ video.vod_pic | default(value='https://via.placeholder.com/300x450') }}"
113-
alt="{{ video.vod_name }}" class="w-48 h-72 lg:w-64 lg:h-96 object-cover rounded-lg shadow-2xl">
114+
alt="{{ video.vod_name }}" class="w-48 h-72 lg:w-64 lg:h-96 object-cover rounded-lg shadow-2xl"
115+
fetchpriority="high">
114116
<div
115117
class="absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-30 transition-all duration-300 rounded-lg flex items-center justify-center">
116118
<div class="opacity-0 group-hover:opacity-100 transition-opacity duration-300">
@@ -127,28 +129,33 @@
127129

128130
<!-- Video Info -->
129131
<div class="flex-1 text-center lg:text-left">
130-
<h1 class="text-3xl lg:text-4xl font-bold mb-4">{{ video.vod_name }}{% if video.vod_remarks %} - {{ video.vod_remarks }}{% endif %}</h1>
132+
<h1 class="text-3xl lg:text-4xl font-bold mb-4">{{ video.vod_name }}{% if video.vod_remarks %} - {{
133+
video.vod_remarks }}{% endif %}</h1>
131134

132135
<div class="flex flex-wrap items-center justify-center lg:justify-start gap-4 mb-6">
133136
{% if video.vod_year %}
134-
<a href="/list/{{ video.type_id }}?year={{ video.vod_year }}" class="bg-white bg-opacity-20 px-3 py-1 rounded-full text-sm hover:bg-opacity-30 transition-colors">
137+
<a href="/list/{{ video.type_id }}?year={{ video.vod_year }}"
138+
class="bg-white bg-opacity-20 px-3 py-1 rounded-full text-sm hover:bg-opacity-30 transition-colors">
135139
<i class="fas fa-calendar mr-1"></i> {{ video.vod_year }}
136140
</a>
137141
{% endif %}
138142
{% if video.vod_area %}
139-
<a href="/list/{{ video.type_id }}?area={{ video.vod_area }}" class="bg-white bg-opacity-20 px-3 py-1 rounded-full text-sm hover:bg-opacity-30 transition-colors">
143+
<a href="/list/{{ video.type_id }}?area={{ video.vod_area }}"
144+
class="bg-white bg-opacity-20 px-3 py-1 rounded-full text-sm hover:bg-opacity-30 transition-colors">
140145
<i class="fas fa-globe mr-1"></i> {{ video.vod_area }}
141146
</a>
142147
{% endif %}
143148
{% if category %}
144149
{% if category.type_pid == 0 %}
145150
<!-- 一级分类,直接跳转到分类页面 -->
146-
<a href="/list/{{ category.type_id }}" class="bg-white bg-opacity-20 px-3 py-1 rounded-full text-sm hover:bg-opacity-30 transition-colors">
151+
<a href="/list/{{ category.type_id }}"
152+
class="bg-white bg-opacity-20 px-3 py-1 rounded-full text-sm hover:bg-opacity-30 transition-colors">
147153
<i class="fas fa-tag mr-1"></i> {{ category.type_name }}
148154
</a>
149155
{% else %}
150156
<!-- 二级分类,跳转到一级分类页面并带上sub_type参数 -->
151-
<a href="/list/{{ category.type_pid }}?sub_type={{ category.type_id }}" class="bg-white bg-opacity-20 px-3 py-1 rounded-full text-sm hover:bg-opacity-30 transition-colors">
157+
<a href="/list/{{ category.type_pid }}?sub_type={{ category.type_id }}"
158+
class="bg-white bg-opacity-20 px-3 py-1 rounded-full text-sm hover:bg-opacity-30 transition-colors">
152159
<i class="fas fa-tag mr-1"></i> {{ category.type_name }}
153160
</a>
154161
{% endif %}

templates/index.html

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ <h1 class="text-4xl md:text-6xl font-bold mb-4">{{ SITENAME | default(value="mac
4747
<!-- Video Categories -->
4848
<div class="container mx-auto px-4 py-8">
4949
{% for cat_data in categorized_videos %}
50+
{% set is_first_category = loop.first %}
5051
<section class="mb-12">
5152
<div class="flex items-center justify-between mb-6">
5253
<div class="flex items-center">
@@ -64,8 +65,16 @@ <h2 class="text-2xl font-bold text-gray-800">{{ cat_data.category.type_name }}</
6465
<div class="video-card bg-white rounded-lg shadow-md overflow-hidden">
6566
<a href="/detail/{{ vod._id['$oid'] }}" class="block">
6667
<div class="relative">
68+
{% if is_first_category and loop.first %}
6769
<img src="{{ vod.vod_pic | default(value='https://via.placeholder.com/200x300') }}"
68-
alt="{{ vod.vod_name }}" class="w-full h-48 object-cover" loading="lazy">
70+
alt="{{ vod.vod_name }}" class="w-full h-48 object-cover transition-opacity duration-300 opacity-100" fetchpriority="high">
71+
{% elif is_first_category and loop.index <= 6 %}
72+
<img src="{{ vod.vod_pic | default(value='https://via.placeholder.com/200x300') }}"
73+
alt="{{ vod.vod_name }}" class="w-full h-48 object-cover transition-opacity duration-300 opacity-100">
74+
{% else %}
75+
<img src="{{ vod.vod_pic | default(value='https://via.placeholder.com/200x300') }}"
76+
alt="{{ vod.vod_name }}" class="w-full h-48 object-cover transition-opacity duration-300 opacity-100" loading="lazy">
77+
{% endif %}
6978
<div class="absolute top-2 right-2 bg-black bg-opacity-60 text-white px-2 py-1 rounded text-xs">
7079
{{ vod.vod_remarks | default(value='更新中') }}
7180
</div>

templates/list.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,8 +259,16 @@ <h2 class="text-xl font-semibold text-gray-800">搜索结果</h2>
259259
<div class="video-card bg-white rounded-lg shadow-md overflow-hidden">
260260
<a href="/detail/{{ vod._id['$oid'] }}" class="block">
261261
<div class="relative">
262+
{% if loop.first %}
263+
<img src="{{ vod.vod_pic | default(value='https://via.placeholder.com/200x300') }}"
264+
alt="{{ vod.vod_name }}" class="w-full h-64 object-cover" fetchpriority="high">
265+
{% elif loop.index <= 2 %}
266+
<img src="{{ vod.vod_pic | default(value='https://via.placeholder.com/200x300') }}"
267+
alt="{{ vod.vod_name }}" class="w-full h-64 object-cover">
268+
{% else %}
262269
<img src="{{ vod.vod_pic | default(value='https://via.placeholder.com/200x300') }}"
263270
alt="{{ vod.vod_name }}" class="w-full h-64 object-cover" loading="lazy">
271+
{% endif %}
264272
<div
265273
class="absolute top-2 right-2 bg-black bg-opacity-60 text-white px-2 py-1 rounded text-xs">
266274
{{ vod.vod_remarks | default(value='更新中') }}

0 commit comments

Comments
 (0)