搜索 K
Appearance
正在开门...
Appearance
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: 将 kongjianguan.fyi 首屏 JS 从 3.6MB 降至 ~1.5MB,首次加载时间从 1-2 分钟缩至 20-30 秒,二次访问秒开。
Architecture: 通过 ECharts 动态导入移除 ~1MB 首屏 JS;删除未使用的 Twikoo 样式减小 CSS;清理 BackgroundImg.ts 注释图片;新增 vercel.json 配置强缓存 + 启用 Brotli 压缩。
Tech Stack: VitePress 1.6.x, Teek 主题 1.5.x, Vue 3, TypeScript, pnpm, Vercel
Files:
Modify: docs/.vitepress/theme/components/ContributeChart.vue:2(移除顶层 import)
Modify: docs/.vitepress/theme/components/ContributeChart.vue:43-46(将 echarts.init 改为动态 import)
Step 1: 修改 ContributeChart.vue,将 echarts 顶层导入改为动态导入
核心思路:把 renderChart 改为 async,内部动态 import("echarts")。Vite 的模块缓存保证 echarts 只会被网络加载一次,后续调用走内存缓存。
改前(顶部 import,第 2 行):
<script setup lang="ts" name="ContributeChart">
import * as echarts from "echarts";
import { ref, watch, nextTick, computed, useTemplateRef, onMounted } from "vue";
import { useData } from "vitepress";
import { formatDate, usePosts, useIntersectionObserver } from "vitepress-theme-teek";改后(移除 echarts import):
<script setup lang="ts" name="ContributeChart">
import { ref, watch, nextTick, computed, useTemplateRef, onMounted } from "vue";
import { useData } from "vitepress";
import { formatDate, usePosts, useIntersectionObserver } from "vitepress-theme-teek";改前(renderChart 函数,第 103-113 行):
const renderChart = (data: any) => {
option.calendar.itemStyle.borderColor = isDark.value ? "#1b1b1f" : "#fff";
option.calendar.itemStyle.color = isDark.value ? "#787878" : "#ebedf0";
if (contributeChart.value) echarts.dispose(contributeChart.value);
if (chartRef.value) contributeChart.value = echarts.init(chartRef.value);
option.series.data = data;
contributeChart.value?.setOption(option);
};改后(renderChart 改为 async,内部动态 import):
const renderChart = async (data: any) => {
const echarts = await import("echarts");
option.calendar.itemStyle.borderColor = isDark.value ? "#1b1b1f" : "#fff";
option.calendar.itemStyle.color = isDark.value ? "#787878" : "#ebedf0";
if (contributeChart.value) echarts.dispose(contributeChart.value);
if (chartRef.value) contributeChart.value = echarts.init(chartRef.value);
option.series.data = data;
contributeChart.value?.setOption(option);
};改前(intersection observer 回调,第 35-52 行):
const { create } = useIntersectionObserver(
chartRef,
entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
requestAnimationFrame(() => {
try {
renderChart(contributeList.value);
} catch (error) {
console.error("初始化动画失败:", error);
}
});
}
});
},
0.1
);改后(await async renderChart):
const { create } = useIntersectionObserver(
chartRef,
entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
requestAnimationFrame(async () => {
try {
await renderChart(contributeList.value);
} catch (error) {
console.error("初始化动画失败:", error);
}
});
}
});
},
0.1
);改前(watch contributeList,第 115-122 行):
watch(
contributeList,
async newValue => {
await nextTick();
renderChart(newValue);
},
{ flush: "post" }
);改后(await async renderChart):
watch(
contributeList,
async newValue => {
await nextTick();
await renderChart(newValue);
},
{ flush: "post" }
);改前(watch isDark,第 124-127 行):
watch(isDark, async () => {
await nextTick();
renderChart(contributeList.value);
});改后(await async renderChart):
watch(isDark, async () => {
await nextTick();
await renderChart(contributeList.value);
});注意:
await import("echarts")在 Vite 中只会发出一次网络请求,后续调用从模块缓存中读取,不会重复加载。
cd /home/misaka/me/VitepressBlog
NODE_OPTIONS=--max-old-space-size=5120 pnpm build 2>&1Expected: 构建成功,exit code 0,无 echarts 相关错误。
ls -lh docs/.vitepress/dist/assets/chunks/theme.*.jsExpected: 从 3.6M 降至 ~2.5M 以下。
git add docs/.vitepress/theme/components/ContributeChart.vue
git commit -m "perf: 将 echarts 改为动态导入,减少首屏 JS 约 1MB"Files:
Delete: docs/.vitepress/theme/style/Twikoo.scss
Modify: docs/.vitepress/theme/style/index.scss
Step 1: 删除 Twikoo.scss 文件
rm /home/misaka/me/VitepressBlog/docs/.vitepress/theme/style/Twikoo.scss改前(index.scss):
@use "./var.scss"as *; //自定义变量
@use "./Twikoo.scss"as *; // 评论框样式 - Hyde 出品
@use "./scrollbar-2.scss"; // 滚动条样式-2,渐变色滚动条
@use "./Fix-Horizontal-Scrollbar.scss"; // 修复水平滚动条问题
@use "./bounce-loading.scss"; // 加载动画 - 圆点弹跳改后:
@use "./var.scss"as *; //自定义变量
@use "./scrollbar-2.scss"; // 滚动条样式-2,渐变色滚动条
@use "./Fix-Horizontal-Scrollbar.scss"; // 修复水平滚动条问题
@use "./bounce-loading.scss"; // 加载动画 - 圆点弹跳cd /home/misaka/me/VitepressBlog
NODE_OPTIONS=--max-old-space-size=5120 pnpm build 2>&1Expected: 构建成功。确认 CSS 文件大小减少:
ls -lh docs/.vitepress/dist/assets/style.*.cssExpected: 从 256K 降至 ~200K 左右。
git add docs/.vitepress/theme/style/Twikoo.scss docs/.vitepress/theme/style/index.scss
git commit -m "perf: 删除未使用的 Twikoo 评论样式,减少 CSS 体积"Files:
Modify: docs/.vitepress/config/BackgroundImg.ts
Step 1: 删除所有被注释的图片条目
当前文件中被 // 注释或 /* ... */ 包裹的图片条目全部删除。保留所有非注释的有效条目。
需要删除的注释条目(共约 40 条):
// ${imgBase}/129487999_p0.jpg(菲比)// ${imgBase}/144370432_p0.jpg(爱弥斯 漂泊者 合照)// ${imgBase}/X@ddengart-2019818370867294543.jpg(爱弥斯)// ${imgBase}/X@vvsimyeol-1874745010434068680.jpg(珂莱塔)// ${imgBase}/140937524_p0.jpg(鸣潮 爱弥斯)// ${imgBase}/120189621_p0.jpg(鸣潮 长离)// ${imgBase}/142598882_p0.jpg(鸣潮 西格莉卡)// ${imgBase}/142094263_p0.jpg(Fate)// ${imgBase}/142052076_p0.jpg(爱弥斯)// ${imgBase}/142210069_p0.jpg(爱弥斯)// ${imgBase}/140831812_p0.jpg(鸣潮 爱弥斯)// ${imgBase}/134.jpg(胡桃 - 原CDN不存在)// ${imgBase}/2025-6-12.jpg(卡提希娅)// ${imgBase}/131473201_p0.jpg(卡提希娅)// ${imgBase}/2025-08-29.jpg(今汐)// ${imgBase}/121206620_p1.png(长离)// ${imgBase}/120767239_p0.png(长离)// ${imgBase}/119879001_p0.png(吟霖)// ${imgBase}/125117828_p0.jpg(吟霖)// ${imgBase}/125670168_p0.jpg(吟霖)// ${imgBase}/134417892_p0.jpg(奥古斯塔)// ${imgBase}/134440043_p0.jpg(奥古斯塔)// ${imgBase}/134452846_p0.jpg(奥古斯塔)// ${imgBase}/2025-09-02.jpg(奥古斯塔)// ${imgBase}/139955382_p0.jpg(奥古斯塔)// ${imgBase}/139955461_p0.jpg(奥古斯塔)// ${imgBase}/2025-04-07.jpg(坎特蕾拉)// ${imgBase}/2025-3-23.jpg(坎特蕾拉)// ${imgBase}/137499724_p0.jpg(赞妮)// ${imgBase}/139754531_p0.jpg(琳奈)// ${imgBase}/2025-12-25-2.jpg(琳奈)// ${imgBase}/2025-12-25-1.jpg(琳奈)// ${imgBase}/backgruond-city.jpg// ${imgBase}/180.jpg(下拉裙摆 - 原CDN不存在)// ${imgBase}/4.2b.png(尼尔)/* */ 注释块(目前在第183-184行附近,可能是 // ] 和 // export const Imgs:Array<string> = [ 相关)注意:只删除注释行,不要动有效代码行。注释分类标签(如 "// 日常", "// re: zero" 等)保留。
cd /home/misaka/me/VitepressBlog
NODE_OPTIONS=--max-old-space-size=5120 pnpm build 2>&1Expected: 构建成功,无报错。
git add docs/.vitepress/config/BackgroundImg.ts
git commit -m "chore: 清理 BackgroundImg.ts 中所有注释掉的无效图片条目"Files:
Create: vercel.json(项目根目录)
Step 1: 创建 vercel.json
cd /home/misaka/me/VitepressBlog创建 vercel.json:
{
"headers": [
{
"source": "/assets/(.*)",
"headers": [
{ "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }
]
}
]
}
max-age=31536000= 1 年。由于 VitePress 构建输出的资源文件名包含 content hash,资源更新时 URL 自动变化,不会让用户拿到过期缓存。
登录 https://vercel.com → 进入 kongjianguan.fyi 项目 → Settings → Enable Brotli Compression(开关打开)。
此为手动步骤,无法通过代码完成。
git add vercel.json
git commit -m "perf: 添加 vercel.json 配置静态资源强缓存策略"cd /home/misaka/me/VitepressBlog
NODE_OPTIONS=--max-old-space-size=5120 pnpm build 2>&1Expected: build complete,exit code 0
# 检查 theme chunk 大小
ls -lh docs/.vitepress/dist/assets/chunks/theme.*.js
# 检查 CSS 大小
ls -lh docs/.vitepress/dist/assets/style.*.css
# 检查总 dist 大小
du -sh docs/.vitepress/dist/assets/
# 确认 Twikoo 已被移除
grep -r "Twikoo\|twikoo" docs/.vitepress/dist/ 2>/dev/null || echo "Twikoo 已从构建产物中清除"Expected:
theme chunk: < 2.5MB
CSS: < 200KB
无 Twikoo 残留
构建产物总大小合理
Step 3: 部署到 GitHub + Vercel 自动部署
cd /home/misaka/me/VitepressBlog
git pushExpected: GitHub Actions 运行成功,Vercel 自动部署至 kongjianguan.fyi。
# 测试首页可访问
curl -s -o /dev/null -w "HTTP: %{http_code}\n" https://kongjianguan.fyi
# 测试缓存头
curl -sI https://kongjianguan.fyi/assets/style.*.css 2>&1 | grep -i "cache-control"
# 测试 JS asset 缓存头
curl -sI https://kongjianguan.fyi/assets/chunks/theme.*.js 2>&1 | grep -i "cache-control"Expected: HTTP 200,Cache-Control 包含 max-age=31536000。
如有文件变更(如构建生成的 lockfile 更新):
git status
git add -A
git commit -m "perf: 构建产物及配置文件更新"
git push| 检查项 | 当前 | 目标 |
|---|---|---|
| theme chunk 体积 | 3.6 MB | < 2.5 MB |
| CSS 体积 | 256 KB | < 200 KB |
| BackgroundImg.ts 条目 | ~100(含注释) | ~60(仅有效) |
| Cache-Control | 无 | max-age=31536000 |
| 构建是否通过 | — | 全部通过 |