利用本科最后一个学生身份参加了开源之夏,有幸参与到 dromara 官网的开发工作。由于比较熟悉 Vue,选择了 Vuepress 开发,主题为 vuepress-theme-hope。 并使用 VuePress Theme Hope 主题的 V2 版本构建。V2 基于 VuePress2, 带有 Vite4 / Webpack5 和 Vue3 的强大功能。以下为开发过程中的一些经验记录。
1.在 VuePress 项目中使用 Vue 组件与 Vue 语法。
由于组织对官网的美观有一定要求,官网开发之前就进行了很长时间的设计,然后发现 ai 设计功能还是不太行 hhh,最后去闲鱼找了一位设计师,效果就很好了。 拿到设计图就会发现 vuepress-theme-hope 是由 frontmatter 关键词渲染生成的样式,设计图完全无法由内置的模块生成,就思考怎么使用 Vue 语法自己写。查阅文档后,项目中主要使用了两种方式:
替换主题组件 主要参考hope 文档的替换主题组件 当在
hopeTheme()的第二个参数中设置{ custom: true }时,主题将通过@theme-hope别名来引入组件,然后在.vuepress/config.ts中通过alias替换主题中使用的组件别名,这样就可以替换主题的任何一个组件。 比如将主页组件改为自己组件 .vuepress/components 下的 HomePage.vue 首先设置 { custom: true },再在 alias 中映射就可以。// .vuepress/config.ts import { getDirname, path } from "@vuepress/utils"; import { defineUserConfig } from "vuepress"; import { hopeTheme } from "vuepress-theme-hope"; const __dirname = getDirname(import.meta.url); export default defineUserConfig({ theme: hopeTheme( { // 主题选项 // ... }, { custom: true } ), alias: { // 你可以在这里将别名定向到自己的组件 // 比如这里我们将主题的主页组件改为用户 .vuepress/components 下的 HomePage.vue "@theme-hope/components/HomePage": path.resolve( __dirname, "./components/HomePage.vue" ), }, });项目中替换了
@theme-hope/components/HomePage主页与@theme-hope/components/PageFooter页脚在 Markdown 中使用 Vue 语法与组件 参考官网在 Markdown 中使用 Vue 语法与组件
- Markdown 中允许使用 HTML。
- Vue 模板语法是和 HTML 兼容的。
因此在 Markdown 中允许直接使用 Vue 模板语法。
具体使用时,由于 Markdown 会被转换为缓存目录下的 Vue 单文件组件,任何相对路径的导入会在 Vue SFC 中失效。因此导入自己的组件,需要为它们创建别名,即通过 alias 选项
// .vuepress/config.ts
import { getDirname, path } from "@vuepress/utils";
const __dirname = getDirname(import.meta.url);
export default {
alias: {
"@ProjectsPage": path.resolve(__dirname, "components/ProjectsPage/ProjectsPage.vue"),
};
};
访问到 src/projects/README.md 页面时,即可拿到 ProjectsPage.vue,并进行渲染。 projects 的 README 文档结构如下所示: 顶部是 md 的 frontmatter,把框架配置的结构为 false,只留空白页面。并在 script 中引入 ProjectsPage.vue。接着使用 ProjectsPage 这个组件。还可以在 style 标签中修改样式。
// src/projects/README.md
---
title: Projects
index: false
sidebar: false
breadcrumb: false
pageInfo: false
contributors: false
editLink: false
lastUpdated: false
prev: false
next: false
---
<script setup lang="ts">
import ProjectsPage from "@ProjectsPage";
</script>
<ProjectsPage />
<style scoped lang="scss">
.theme-hope-content {
margin: 0;
padding: 0;
max-width: none;
position: relative;
z-index: 1;
top: -161px;
@media (min-width: 1440px) {
background: #f9fbff;
}
}
</style>
2. 多语言方案
由于上文把内置模块替换成 Vue 组件,会影响到多语言的实现。切换语言时,只有 md 的标题会变化,而 md 中使用的 Vue 组件需要找到方式联动。
一开始想用主题提供的 api 引入变量,将来改东西直接在 md 文档改,内部自动映射过来。结果看了提供的 api,发现首页还是只能拿到用不了的那些模块。
找到 jinchaolove 的 demo,发现可以拿到框架提供的多个 hooks,其中 useSiteLocaleData() 的 lang 属性即为当前的语言。
所以考虑自己实现多语言,就是把文字常量放在 en.ts 和 zh.ts,引入到 vue 文件中,里面 watch 语言类型的变化,切换就把 homeOption 换掉。
// src\.vuepress\components\ProjectsPage\ProjectsPage.vue
<div class="project-container">
<h1 class="title">{{ projectsOption.PROJECTS }}</h1>
<p class="description">
{{ projectsOption.DESCRIPTION }}
</p>
</div>
import { useSiteLocaleData } from "@vuepress/client";
const siteLocaleData = useSiteLocaleData();
watch(
() => siteLocaleData.value.lang,
(newLang) => {
lang.value = newLang;
if (lang.value === "zh-CN" || lang.value === "/zh/") {
projectsOption = zhProjectsOption;
} else {
projectsOption = enProjectsOption;
}
},
{
immediate: true
}
);
询问阿超前辈后,认为可以这么实现,维护还好,大概后续不会特别关注底层,于是使用了该方案,后续转换也很顺畅。
3. 通过插件拿到所有 frontmatter 信息
有个场景,想当用户点击新闻标签时,显示所有新闻的博客信息,包括标题、链接、作者、日期等,也就是自动拿到 src\zh\news 这个文件夹下所有 md 文档的 frontmatter,然后内部进行处理,最终显示在新闻标签页。自己翻框架文档没找到可实现的 api,在思考使用 Node.js 自己写工具,还是换其他方式时,决定去请教阿超前辈。
阿超前辈通过 demo 展示了正确地使用框架内部插件的方式。我在项目里按照正确方式,运行很好。
前辈告诉我需要理解框架中配插件的方式与插件生命周期,然后可以打印出来看到底提供了哪些属性。
实现方式主要利用 vuepress2 提供的插件 API extendsPage
其类型为: (page: Page, app: App) => void | Promise
可以在 page 和 app 中拿到 frontmatter,并放在 app.siteData.frontmatter 中。
module.exports = {
name: 'get-all-frontmatter',
extendsPage: (page, app) => {
app.siteData.frontmatter = app.siteData.frontmatter ?? []
app.siteData.frontmatter.push(page.data.frontmatter)
},
};
然后在新闻的 vue 文件中
import { siteData } from "@vuepress/client";
const allPagesFrontmatter = siteData.value.frontmatter;
就能获得 siteData.value.frontmatter,并做想要的转换。 这样,只要在所有新闻的 md 中,增加相应的 frontmatter,就可以在新闻页全部拿到对应信息。
4. hope 主题中使用 webpack
曾经想用 webpack 的 gzip 压缩下代码、使用 cdn,但发现我的网站慢主要是因为使用 gh-pages 部署的,还是应该在这上面下功夫,但翻到的前人在 hope 主题中使用 webpack 的方式还是很有用,可以用 webpack 的各种插件、loader,所以一并贴出来。 https://newzone.top/web/VuePress.html#%E6%97%B6%E9%97%B4%E5%8F%82%E6%95%B0
完整代码可参考仓库,欢迎大家指教。
「真诚赞赏,手留余香」
真诚赞赏,手留余香
使用微信扫描二维码完成支付
