perf: JS按需加载优化 + PJAX适配
- 首页JS减少56%(800KB → 350KB) - 文章页JS减少44%(800KB → 450KB) - 完美适配PJAX导航 - 保持所有功能正常
This commit is contained in:
1 parent
c65dbab67e
commit
cbf2034f78
16 files changed
+6445
-63
No files matched your search
@@ -0,0 +1,705 @@
|
||||
# 第1步:CSS加载策略优化实施方案
|
||||
|
||||
## 📋 当前状态分析
|
||||
|
||||
### CSS文件清单
|
||||
- `normalize.css` - CSS重置(基础,必须首屏加载)
|
||||
- `remixicon.css` - 图标字体(必须首屏加载)
|
||||
- `uikit.min.css` - UIkit框架(必须首屏加载)
|
||||
- `nprogress.min.css` - 进度条(核心功能,首屏加载)
|
||||
- `message.min.css` - 消息提示(可延迟)
|
||||
- `main.css` - 主题样式(需要拆分)
|
||||
|
||||
### main.css 结构分析
|
||||
|
||||
#### 首屏关键CSS(约15-20KB)
|
||||
```css
|
||||
1. CSS变量定义(:root)
|
||||
2. @font-face 字体声明
|
||||
3. html/body 基础样式
|
||||
4. .main 容器布局(居中、阴影、背景)
|
||||
5. .header 头部布局
|
||||
6. .header-menu 导航菜单
|
||||
7. .header-avatar 头像
|
||||
8. .header-social 社交链接
|
||||
9. .header-bio 个人介绍
|
||||
10. [data-theme="dark"] 深色模式基础变量
|
||||
11. 基础排版(h1-h6, p, a, ul)
|
||||
12. .footer 页脚
|
||||
13. 滚动条样式
|
||||
14. 基础图片样式
|
||||
15. hr 分割线
|
||||
```
|
||||
|
||||
#### 非首屏CSS(可延迟加载,约35-40KB)
|
||||
```css
|
||||
1. 代码相关
|
||||
- .code-fold-container
|
||||
- .code-expand-btn
|
||||
- pre, code 特殊样式
|
||||
- 代码高亮主题
|
||||
|
||||
2. 文章详情页
|
||||
- blockquote 样式
|
||||
- 文章列表特殊样式
|
||||
- 打赏按钮(.reward-container)
|
||||
- 相关文章(.related-posts)
|
||||
|
||||
3. 评论系统
|
||||
- Artalk 相关样式(.atk-*)
|
||||
- 评论区布局
|
||||
|
||||
4. 友链页面
|
||||
- .links-item
|
||||
- .link-active-badge
|
||||
- .link-dead-badge
|
||||
|
||||
5. 弹幕系统
|
||||
- .barrage-container
|
||||
- 弹幕动画
|
||||
|
||||
6. 搜索功能
|
||||
- .search-modal
|
||||
- .search-results
|
||||
|
||||
7. 其他功能
|
||||
- 浮动工具(.floating-tools)
|
||||
- Toast 提示
|
||||
- 图片灯箱
|
||||
- 无限滚动加载提示
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 优化方案
|
||||
|
||||
### 策略1:CSS代码拆分(推荐)
|
||||
|
||||
将 `main.css` 拆分为两个文件:
|
||||
- `critical.css` - 首屏关键CSS(内联到HTML)
|
||||
- `main.css` - 其余样式(异步加载)
|
||||
|
||||
### 策略2:CSS层级加载
|
||||
|
||||
保留单个 `main.css`,但使用Hugo的模板逻辑分层输出:
|
||||
- 首屏样式:内联 `<style>` 标签
|
||||
- 其余样式:`<link rel="preload">` 异步加载
|
||||
|
||||
---
|
||||
|
||||
## 📝 实施步骤
|
||||
|
||||
### 步骤1.1:创建关键CSS文件
|
||||
|
||||
**文件路径:** `themes/Ying/assets/css/critical.css`
|
||||
|
||||
**内容:** 从main.css提取首屏关键样式
|
||||
|
||||
```css
|
||||
/* ========================================
|
||||
首屏关键CSS - Critical CSS
|
||||
用于内联到<head>中,提升FCP
|
||||
======================================== */
|
||||
|
||||
/* CSS变量 */
|
||||
:root {
|
||||
--background-color: #fafafa;
|
||||
--background-dark-color: #020617;
|
||||
--text-content-color: #24292e;
|
||||
--text-content-dark-color: #d1d5db;
|
||||
--text-title-color: #111827;
|
||||
--text-title-dark-color: #e5e7eb;
|
||||
--text-highlight-color: #696565;
|
||||
--frame-dark-color: #1f2933;
|
||||
--frame-color: #eee;
|
||||
--card-shadow-light: 0 10px 20px 0 rgba(236, 236, 236, 0.86);
|
||||
--card-shadow-dark: 0 18px 45px rgba(0, 0, 0, 0.9), 0 0 0 1px rgba(148, 163, 184, 0.45);
|
||||
--link-color-light: #374151;
|
||||
--link-hover-color-light: #111827;
|
||||
--link-color-dark: #e5e7eb;
|
||||
--link-hover-color-dark: #d1d5db;
|
||||
}
|
||||
|
||||
/* 字体声明 */
|
||||
@font-face {
|
||||
font-family: 'zql';
|
||||
src: url('../font/zql-v2.woff2') format('woff2'),
|
||||
url('../font/zql-v2.woff') format('woff');
|
||||
font-display: swap;
|
||||
unicode-range: U+0000-007F, U+4E00-9FFF, U+2000-206F, U+3000-303F;
|
||||
}
|
||||
|
||||
/* 基础样式 */
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'zql', serif;
|
||||
color: var(--text-content-color);
|
||||
line-height: 1.6;
|
||||
font-size: 16px;
|
||||
background: var(--background-color);
|
||||
/* 背景图片 */
|
||||
background-image: url(data:image/webp;base64,...); /* 实际base64数据
|
||||
background-repeat: round;
|
||||
background-size: contain;
|
||||
background-attachment: fixed;
|
||||
z-index: 5;
|
||||
transition: background-color 0.3s ease, color 0.3s ease;
|
||||
}
|
||||
|
||||
/* 深色模式基础 */
|
||||
[data-theme="dark"] body {
|
||||
color: var(--text-content-dark-color);
|
||||
background-color: var(--background-dark-color);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .main {
|
||||
background: rgba(15, 23, 42, 0.99);
|
||||
box-shadow: var(--card-shadow-dark);
|
||||
}
|
||||
|
||||
/* 主容器 */
|
||||
.main {
|
||||
max-width: 618px;
|
||||
overflow: hidden;
|
||||
margin: 60px auto;
|
||||
padding: 50px;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
box-shadow: var(--card-shadow-light);
|
||||
border-radius: 8px;
|
||||
z-index: 10;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
backdrop-filter: blur(6px);
|
||||
-webkit-backdrop-filter: blur(6px);
|
||||
transition: background-color 0.5s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
color 0.5s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
/* 头部布局 */
|
||||
.header {
|
||||
margin-bottom: 10px;
|
||||
padding-bottom: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.header-top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.header-avatar {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.header-avatar img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
border-radius: 50%;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.header-info {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.header-social {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.header-social a {
|
||||
color: var(--link-color-light);
|
||||
font-size: 1.2rem;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.header-social a:hover {
|
||||
color: var(--link-hover-color-light);
|
||||
}
|
||||
|
||||
.header-bio {
|
||||
font-size: 0.9rem;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 导航菜单 */
|
||||
.header-menu {
|
||||
border-top: 1px solid #eee;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.header-menu ul {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
list-style: none;
|
||||
gap: 25px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.header-menu ul li a {
|
||||
color: var(--link-color-light);
|
||||
text-decoration: none;
|
||||
font-size: 0.95rem;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.header-menu ul li.active a {
|
||||
color: var(--text-title-color);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 深色模式导航 */
|
||||
[data-theme="dark"] .header nav {
|
||||
border-top-color: #1f2933;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .header nav ul.flat li a {
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .header nav ul.flat li.active a {
|
||||
color: #e5e7eb;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .header-social a {
|
||||
color: var(--link-color-dark);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .header-social a:hover {
|
||||
color: var(--link-hover-color-dark);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .header-bio {
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
/* 排版 */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
line-height: 1.2;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
h1 { font-size: 1.5rem; }
|
||||
h2 { font-size: 1.375rem; }
|
||||
h3 { font-size: 1.25rem; }
|
||||
h4, h5, h6 { font-size: 1.125rem; }
|
||||
|
||||
a {
|
||||
color: var(--link-color-light);
|
||||
text-decoration: none;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--link-hover-color-light);
|
||||
}
|
||||
|
||||
[data-theme="dark"] a {
|
||||
color: var(--link-color-dark);
|
||||
}
|
||||
|
||||
[data-theme="dark"] a:hover {
|
||||
color: var(--link-hover-color-dark);
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0.8em 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-left: 0px;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
/* 图片基础样式 */
|
||||
img {
|
||||
max-width: 100%;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
a img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* 分割线 */
|
||||
hr {
|
||||
display: block;
|
||||
height: 1px;
|
||||
border: 0;
|
||||
border-top: 1px solid #cccccc;
|
||||
margin: 1rem 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
[data-theme="dark"] hr {
|
||||
border-top-color: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
/* 滚动条 */
|
||||
::-webkit-scrollbar {
|
||||
width: 13px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
min-height: 16px;
|
||||
background-color: #999999;
|
||||
background-clip: padding-box;
|
||||
border: 3px solid #fdfdfd;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: #444;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* 图标 */
|
||||
.icon {
|
||||
width: 1.8em;
|
||||
height: 1.8em;
|
||||
vertical-align: -1em;
|
||||
fill: currentColor;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 文章元信息 */
|
||||
.meta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
gap: 10px;
|
||||
margin-bottom: 20px;
|
||||
color: #999;
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.meta-item {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .meta {
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
/* 页脚 */
|
||||
.footer {
|
||||
border-top: 1px solid #eee;
|
||||
padding-top: 20px;
|
||||
margin-top: 30px;
|
||||
color: #999;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .footer {
|
||||
border-top-color: #1f2933;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
/* 文章标题 */
|
||||
.post-title {
|
||||
color: var(--text-title-color);
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .post-title {
|
||||
color: var(--text-title-dark-color);
|
||||
}
|
||||
|
||||
/* 深色模式链接和文本 */
|
||||
[data-theme="dark"] .post-content {
|
||||
color: var(--text-content-dark-color);
|
||||
}
|
||||
|
||||
/* 主题切换按钮 */
|
||||
.theme-toggle-button {
|
||||
border: none;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
padding: 4px 8px;
|
||||
color: #586069;
|
||||
}
|
||||
|
||||
.theme-toggle-button:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .theme-toggle-button {
|
||||
color: #e5e7eb;
|
||||
}
|
||||
|
||||
/* 响应式 - 大屏优化 */
|
||||
@media (min-width: 768px) {
|
||||
.main {
|
||||
background: rgba(255, 255, 255, 0.88);
|
||||
-webkit-backdrop-filter: blur(6px);
|
||||
backdrop-filter: blur(6px);
|
||||
}
|
||||
}
|
||||
|
||||
/* 主题切换动画 */
|
||||
#theme-toggle i {
|
||||
transition: transform 0.5s cubic-bezier(0.4, 0.0, 0.2, 1);
|
||||
}
|
||||
|
||||
#theme-toggle.rotate i {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 步骤1.2:修改 head.html - 实施CSS加载策略
|
||||
|
||||
**文件路径:** `themes/Ying/layouts/partials/head.html`
|
||||
|
||||
**修改位置:** 第127-135行(Stylesheets部分)
|
||||
|
||||
**当前代码:**
|
||||
```gohtml
|
||||
{{ $normalize := resources.Get "css/libs/normalize.css" }}
|
||||
{{ $remixicon := resources.Get "css/libs/remixicon.css" }}
|
||||
{{ $uikit := resources.Get "css/libs/uikit.min.css" }}
|
||||
{{ $nprogress := resources.Get "css/libs/nprogress.min.css" }}
|
||||
{{ $message := resources.Get "css/libs/message.min.css" }}
|
||||
{{ $main := resources.Get "css/main.css" }}
|
||||
|
||||
{{ $style := slice $normalize $remixicon $uikit $nprogress $message $main | resources.Concat "css/style.css" | resources.Minify | resources.Fingerprint }}
|
||||
<link rel="stylesheet" href="{{ $style.RelPermalink }}">
|
||||
```
|
||||
|
||||
**修改后代码:**
|
||||
```gohtml
|
||||
{{/* ====== CSS加载优化:关键CSS内联 + 非关键CSS异步加载 ====== */}}
|
||||
|
||||
{{/* 1. 首屏关键CSS - 内联到<head> */}}
|
||||
{{ $critical := resources.Get "css/critical.css" | resources.Minify }}
|
||||
<style>{{ $critical.Content | safeCSS }}</style>
|
||||
|
||||
{{/* 2. 非首屏CSS - 预加载但不阻塞渲染 */}}
|
||||
{{ $normalize := resources.Get "css/libs/normalize.css" }}
|
||||
{{ $remixicon := resources.Get "css/libs/remixicon.css" }}
|
||||
{{ $uikit := resources.Get "css/libs/uikit.min.css" }}
|
||||
{{ $nprogress := resources.Get "css/libs/nprogress.min.css" }}
|
||||
{{ $message := resources.Get "css/libs/message.min.css" }}
|
||||
{{ $main := resources.Get "css/main.css" }}
|
||||
|
||||
{{/* 合并非关键CSS */}}
|
||||
{{ $nonCritical := slice $normalize $remixicon $uikit $nprogress $message $main | resources.Concat "css/style.css" | resources.Minify | resources.Fingerprint }}
|
||||
|
||||
{{/* 使用preload异步加载,不阻塞渲染 */}}
|
||||
<link rel="preload" href="{{ $nonCritical.RelPermalink }}" as="style" onload="this.onload=null;this.rel='stylesheet'">
|
||||
<noscript><link rel="stylesheet" href="{{ $nonCritical.RelPermalink }}"></noscript>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 步骤1.3:创建Hugo构建脚本(可选,用于自动化)
|
||||
|
||||
**文件路径:** `themes/Ying/scripts/extract-critical-css.sh`
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# 从main.css提取关键CSS的辅助脚本
|
||||
# 用法:./scripts/extract-critical-css.sh
|
||||
|
||||
echo "正在分析main.css..."
|
||||
|
||||
# 标记:以下选择器为首屏关键CSS
|
||||
CRITICAL_SELECTORS=(
|
||||
":root"
|
||||
"html"
|
||||
"body"
|
||||
".main"
|
||||
".header"
|
||||
".header-top"
|
||||
".header-avatar"
|
||||
".header-info"
|
||||
".header-social"
|
||||
".header-bio"
|
||||
".header-menu"
|
||||
"h1"
|
||||
"h2"
|
||||
"h3"
|
||||
"h4"
|
||||
"h5"
|
||||
"h6"
|
||||
"a"
|
||||
"p"
|
||||
"ul"
|
||||
"img"
|
||||
"hr"
|
||||
".meta"
|
||||
".meta-item"
|
||||
".footer"
|
||||
".post-title"
|
||||
".theme-toggle-button"
|
||||
"@media"
|
||||
"@font-face"
|
||||
":root"
|
||||
"[data-theme"
|
||||
)
|
||||
|
||||
echo "请根据以上选择器手动提取CSS到critical.css"
|
||||
echo "或使用自动化CSS提取工具如:critical、penthouse"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 测试验证清单
|
||||
|
||||
### 测试1:首屏渲染性能
|
||||
- [ ] 使用Chrome DevTools的Network面板查看:
|
||||
- 首字节时间(TTFB)是否正常
|
||||
- 首次内容绘制(FCP)是否提升
|
||||
- 样式表是否正确加载
|
||||
|
||||
### 测试2:视觉一致性
|
||||
- [ ] 首页显示正常
|
||||
- [ ] Header布局正确
|
||||
- [ ] 导航菜单样式正确
|
||||
- [ ] 头像显示正常
|
||||
- [ ] 社交链接图标正确
|
||||
- [ ] 深色模式切换正常
|
||||
- [ ] 文章列表页显示正常
|
||||
- [ ] 文章卡片样式正确
|
||||
- [ ] 分页按钮正常
|
||||
|
||||
### 测试3:深色模式
|
||||
- [ ] 点击头像切换深色模式
|
||||
- [ ] 所有文字颜色正确
|
||||
- [ ] 背景颜色正确
|
||||
- [ ] 阴影效果正确
|
||||
- [ ] 链接颜色正确
|
||||
|
||||
### 测试4:响应式布局
|
||||
- [ ] 桌面端(>768px)显示正常
|
||||
- [ ] 移动端(<768px)显示正常
|
||||
- [ ] 菜单在移动端正确折叠
|
||||
|
||||
### 测试5:资源加载
|
||||
- [ ] 检查Console无错误
|
||||
- [ ] 所有CSS文件加载成功
|
||||
- [ ] 字体文件加载成功(Network面板)
|
||||
- [ ] 无404错误
|
||||
|
||||
---
|
||||
|
||||
## 📊 预期收益
|
||||
|
||||
### 性能指标提升(预估)
|
||||
| 指标 | 优化前 | 优化后 | 提升 |
|
||||
|------|--------|--------|------|
|
||||
| 首屏CSS大小 | ~500KB | ~20KB(内联) | ⚡ -96% |
|
||||
| CSS阻塞时间 | ~800ms | ~0ms | ⚡ -100% |
|
||||
| FCP | ~1.8s | ~1.2s | ⚡ -33% |
|
||||
| Speed Index | ~2.5s | ~1.8s | ⚡ -28% |
|
||||
|
||||
### 用户体验提升
|
||||
- ✅ 页面立即开始渲染(无需等待CSS下载)
|
||||
- ✅ 深色模式无闪烁(CSS变量立即生效)
|
||||
- ✅ 字体加载更平滑(font-display: swap生效)
|
||||
- ✅ 首屏内容更快可见
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
### 1. 背景图片的base64数据
|
||||
当前body的background-image使用了很长的base64数据。这个数据应该:
|
||||
- 保持在critical.css中(确保首屏背景显示)
|
||||
- 或者移至单独文件并使用preload
|
||||
|
||||
建议:将base64数据移至单独的CSS文件 `background.css`,使用 `fetchpriority="high"` 优先加载
|
||||
|
||||
### 2. Remixicon字体文件
|
||||
`remixicon.css` 引用了字体文件(.woff2, .woff)。确保:
|
||||
- 字体文件路径正确
|
||||
- 使用 `font-display: swap` 避免FOIT
|
||||
|
||||
### 3. UIkit依赖
|
||||
UIkit的CSS可能包含一些组件样式(如grid、modal等)。检查:
|
||||
- 深色模式是否正确覆盖UIkit默认样式
|
||||
- 是否有样式冲突
|
||||
|
||||
### 4. 浏览器兼容性
|
||||
`<link rel="preload" onload>` 技术需要测试:
|
||||
- Chrome/Edge:✅ 完全支持
|
||||
- Firefox:✅ 支持
|
||||
- Safari:✅ 支持(11.1+)
|
||||
- IE11:❌ 不支持(需要polyfill或fallback)
|
||||
|
||||
---
|
||||
|
||||
## 🔄 回滚方案
|
||||
|
||||
如果出现问题,快速回滚到原始方案:
|
||||
|
||||
```gohtml
|
||||
{{/* 回滚到原始CSS加载方式 */}}
|
||||
{{ $normalize := resources.Get "css/libs/normalize.css" }}
|
||||
{{ $remixicon := resources.Get "css/libs/remixicon.css" }}
|
||||
{{ $uikit := resources.Get "css/libs/uikit.min.css" }}
|
||||
{{ $nprogress := resources.Get "css/libs/nprogress.min.css" }}
|
||||
{{ $message := resources.Get "css/libs/message.min.css" }}
|
||||
{{ $main := resources.Get "css/main.css" }}
|
||||
|
||||
{{ $style := slice $normalize $remixicon $uikit $nprogress $message $main | resources.Concat "css/style.css" | resources.Minify | resources.Fingerprint }}
|
||||
<link rel="stylesheet" href="{{ $style.RelPermalink }}">
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 扩展阅读
|
||||
|
||||
1. **Critical CSS最佳实践**
|
||||
- https://web.dev/extract-critical-css/
|
||||
- https://github.com/addyosmani/critical
|
||||
|
||||
2. **CSS加载策略**
|
||||
- https://web.dev/preload-responsive-stylesheets/
|
||||
- https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload
|
||||
|
||||
3. **性能优化工具**
|
||||
- Lighthouse:https://developers.google.com/web/tools/lighthouse
|
||||
- WebPageTest:https://www.webpagetest.org/
|
||||
|
||||
---
|
||||
|
||||
## ✅ 实施清单
|
||||
|
||||
- [ ] 创建 `themes/Ying/assets/css/critical.css`
|
||||
- [ ] 修改 `themes/Ying/layouts/partials/head.html`
|
||||
- [ ] 测试首页显示
|
||||
- [ ] 测试深色模式
|
||||
- [ ] 测试移动端
|
||||
- [ ] 使用Lighthouse验证性能提升
|
||||
- [ ] 提交代码
|
||||
|
||||
---
|
||||
|
||||
**预计耗时:** 1-2小时
|
||||
**风险等级:** 低(有完整回滚方案)
|
||||
Reference in new issue
Block a user