Vitepress 相关问题优化
非根目录部署
下列配置在./vitepress.config.js中
配置 base
默认情况下,我们假设站点将部署在域名 (/) 的根路径上。如果站点在子路径中提供服务,例如 https://mywebsite.com/blog/,则需要在 VitePress 配置中将 base 选项设置为 ‘/blog/’。
例:如果你使用的是 Github(或 GitLab)页面并部署到 user.github.io/repo/,请将 base 设置为 /repo/。
取消生成简洁的 URL
注意:
-
非根目录时, 需要将cleanUrls 设置成 false, 因为默认情况下,VitePress 会生成简洁的 URL,例如 /vite/bar.html 会被重定向到 /vite/bar。但是,当您在该页面上执行原地刷新时,浏览器会将相对路径与当前 URL 组合,导致它尝试加载 /vite/index.md 这样的路径。
-
根目录部署时,cleanUrls 推荐设置成 true, 这样网络路径可以省略.html, 显得更专业。
nginx配置如下
location /vite {
#开启gzip
gzip on;
#低于1kb的资源不压缩
gzip_min_length 1k;
#压缩级别1-9,越大压缩率越高,同时消耗cpu资源也越多,建议设置在5左右。
gzip_comp_level 5;
#需要压缩哪些响应类型的资源,多个空格隔开。不建议压缩图片.
gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css;
#配置禁用gzip条件,支持正则。此处表示ie6及以下不启用gzip(因为ie低版本不支持)
gzip_disable "MSIE [1-6]\.";
#是否添加“Vary: Accept-Encoding”响应头
gzip_vary on;
alias /data/web/vite/;
try_files $uri $uri/ /vite/index.html;
}
开启GZIP压缩
修改package.json
"scripts": {
"dev": "cross-env NODE_ENV=development vitepress dev docs --port=8732",
"build": "npm run daily-notes && vitepress build docs",
"compress": "node ./docs/.vitepress/compress.js", 添加这行
"postbuild": "npm run compress", 添加这行
"build:docs": "vitepress build docs",
"daily-notes": "node ./scripts/daily-notes.js",
"update:friend": "node ./scripts/update-friend.js",
"preview": "vitepress preview docs --port 8730",
"lint": "prettier --write .",
"prepare": "husky install"
},
对应位置创建compress.js
import { promises as fs } from "fs";
import { gzip } from "zlib";
import { promisify } from "util";
import fg from "fast-glob";
const gzipAsync = promisify(gzip);
async function compressFiles() {
try {
const files = await fg(["./dist/**/*.{html,jpg,jpeg,png}"], { onlyFiles: true });
for (const file of files) {
const content = await fs.readFile(file);
const originalSize = content.length;
// Gzip 压缩
const gzipped = await gzipAsync(content);
const gzippedSize = gzipped.length;
if (gzippedSize < originalSize * 0.95) { // 如果压缩效果超过 5%
await fs.writeFile(`${file}.gz`, gzipped);
// console.log(`${file} 已保存为 .gz`);
} else {
// console.log(`${file} 的 Gzip 压缩效果不足 5%,跳过。`);
}
}
console.log("Compression complete.");
} catch (error) {
console.error("Error during compression:", error);
}
}
compressFiles();
即在构建完成后执行压缩操作。
nginx配置同上。
添加字数及阅读时长
自定义布局容器
<script setup>
import DefaultTheme from 'vitepress/theme'
const { Layout } = DefaultTheme
....
</script>
<template>
<Layout v-bind="$attrs">
<!-- 这里指的是文章前, 同时可以在文章内设置readingTime=false来关闭 -->
<template #doc-before v-if="frontmatter.readingTime !== false">
<!-- 计算字数和阅读时间 -->
<ReadingTime />
</template>
<!-- 其他可扩展的插槽 -->
...
</Layout>
</template>
计算字数和阅读时间
<script setup>
import { ref, watch, onMounted, nextTick } from 'vue'
import { useData } from 'vitepress'
const { page } = useData()
// 统计逻辑
const stats = ref({ words: 0, minutes: 0 })
const calculateStats = () => {
// 优先尝试从页面数据中获取内容(如果 theme 或 page 提供了内容字段)
let content = page.value.content
if (!content) {
// 如果没有则通过 DOM 查询获取
content = document.querySelector('.vp-doc')?.textContent || ''
}
// 去除所有空白字符后统计字符数(中文场景下更适合统计“字”)
const wordCount = content.replace(/\s+/g, '').length
const readingTime = Math.ceil(wordCount / 350)
stats.value = {
words: wordCount,
minutes: readingTime
}
}
// 当路由变化时重新计算阅读统计
watch(() => page.value.relativePath, async () => {
await nextTick() // 等待 DOM 更新完成
calculateStats()
})
// 初次挂载后计算一次
onMounted(async () => {
await nextTick()
calculateStats()
})
</script>
<template>
<div class="reading-stats" v-if="stats.words > 10">
<span class="reading-stats-text">
全文共 {{ stats.words }} 字, 预计阅读: {{ stats.minutes }} 分钟
</span>
</div>
</template>
<style scoped>
.reading-stats {
font-size: 0.8em;
text-align: center;
margin: 0px 0 25px;
}
.reading-stats-text {
color: rgb(145, 89, 48);
background-color: rgba(234, 179, 8, 0.14);
padding: 5px 16px;
border-radius: 5px;
}
</style>