折腾记录|使用 Nuxt.js 重写个人主页,使用 SSR 优化 SEO ,实现一些期待已久的效果

grtsinry43
9/19/2024
24 views
预计阅读时长 10 分钟

在 22 年刚创建个人主页的时候,由于我的技术水平不够,只能用一些 wordpress typecho 这种直观的工具,后来因为换域名等等一系列的问题就被搁置了...再后来为了过备案,用图形化工具和 bootstrap 糊了一个,而如今熟练掌握 Vue 和 React 等框架之后,也到了完全重写的时候了,于是就有了这段记录。

<!--more-->

关键词:Vue SSR,Nuxt.js

网页的开发一直在持续哇...本文章会持续跟进更新

最后链接:https://www.grtsinry43.com/

框架选择

首先,对于这种主页类的网站,单纯的 Vue React SPA(单页面应用)肯定是不行的,比如说这里我们使用 pure-admin 模板创建的一个后台系统(Vue3),对于搜索引擎来说不会等待页面完全加载和渲染,而抓到的这些内容无法分析网站的关键词和主题等,导致很难被搜索引擎排名考前,因此我们不得不从历史中汲取经验,从服务端生成静态网页,到了客户端渲染的单页面应用,又回到了服务端渲染

这样是很难做好 SEO 的

对于个人主页这种比较小的项目,我更喜欢使用 Vue 来完成开发,也就是其对应的 SSR 框架——Nuxt.js

快速上手

由于要使用 NuxtUI,我们便可以使用官方的创建工程的脚手架

BASH
1npx nuxi@latest init -t ui [项目名称]

创建好项目之后,我们便可以像正常写 Vue 一样来进行开发啦

前置准备工作

在代码块以及项目名称中,我们选用一个等宽而且适用于代码的字体 JetBrains Mono,于是我们可以在 assets/fonts.css 中这样进行引入

CSS
1@font-face {
2    font-family: 'JetBrains Mono';
3    src: url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff2/JetBrainsMono-Medium.woff2') format('woff2');
4    font-weight: 500;
5    font-style: normal;
6}
7
8.font-jb-mono {
9    /* 设置fallback防止出现宋体 */
10    font-family: 'JetBrains Mono', 'Courier New', Courier, 'Lucida Sans Typewriter', 'Lucida Console', 'Microsoft YaHei', 'WenQuanYi Micro Hei', monospace;
11}

注意这里要设置好 fallback 字体,因为某些 Windows 系统(雾)默认会回落到宋体,导致中文字体不堪入目

以后当我们需要使用的时候只需要挂上这个类名就好

防止掉头发

经典防止掉头发几件套:assets/global.css

CSS
1* {
2    margin: 0;
3    padding: 0;
4    box-sizing: border-box;
5}
6
7a {
8    text-decoration: none;
9    color: inherit;
10}
11
12ul {
13    list-style: none;
14}

疑难解决方案与创新点

桌面与移动端导航栏适配

为了达到最完美的使用效果,我直接写了 NavBarNavBarMobile 两个组件,通过简单的媒体查询来进行切换

CSS
1@media (max-width: 800px) {
2  .nav-bar-desktop {
3    display: none;
4  }
5
6  .nav-bar-mobile {
7    display: block;
8  }
9}

对于移动段的 Navbar,我选择了可收起菜单来优化体验

VUE
1const toggleMenu = () => {
2  isMenuOpen.value = !isMenuOpen.value
3}
4
5const toggleLocale = () => {
6  locale.value = locale.value === 'en' ? 'zh' : 'en';
7};
8</script>
9
10<template>
11  <div
12      class="nav-container fixed w-full bg-opacity-80 bg-blue-50 text-blue-950 dark:bg-opacity-80 dark:bg-black dark:text-white">
13    <UContainer class="flex flex-row items-center justify-between nav-inner">
14      <div class="nav-logo">
15        <NuxtLink :to="localePath('/')" class="font-bold">{{ $t('homePageTitle') }}</NuxtLink>
16      </div>
17      <!-- Toggle Button for Mobile Menu -->
18      <UButton class="lg:hidden bg-opacity-0 dark:bg-opacity-0" @click="toggleMenu"
19               icon="i-heroicons:bars-3-bottom-right"
20               square
21               color="gray"
22      >
23      </UButton>
24      <!-- Theme Toggle Button -->
25      <div class="theme-option lg:block">
26        <UToggle
27            on-icon="i-heroicons-moon-20-solid"
28            off-icon="i-heroicons-sun-20-solid"
29            :model-value="colorMode.preference === 'dark'"
30            @change="toggleTheme"
31        />
32      </div>
33      <!-- Icons Container -->
34      <div class="actions-container hidden lg:grid">
35        <Icon class="language-toggle-icon hover:text-blue-400 dark:hover:text-blue-600" name="i-heroicons-language" @click="toggleLocale"/>
36        <Icon class="rss-icon hover:text-blue-400 dark:hover:text-blue-600" name="i-heroicons-rss"/>
37        <a href="https://github.com/grtsinry43/home-web" target="_blank">
38          <Icon class="github-icon hover:text-blue-400 dark:hover:text-blue-600" name="i-grommet-icons:github"/>
39        </a>
40      </div>
41    </UContainer>
42
43    <!-- Mobile Navigation Menu -->
44    <div v-show="isMenuOpen"
45         class="nav-extend-container flex flex-col items-center bg-blue-50 bg-opacity-85 dark:bg-black dark:bg-opacity-80 backdrop-blur-lg">
46      这里就是菜单项目啦
47    </div>
48  </div>
49</template>

深浅色模式的极不优雅解决方案

JS
1import {onMounted} from "vue";
2const colorMode = useColorMode();
3
4const toggleTheme = () => {
5  if (colorMode.preference === 'system') {
6    colorMode.preference = colorMode.value === 'dark' ? 'light' : 'dark';
7    buttonState.value = colorMode.preference === 'dark';
8  } else {
9    colorMode.preference = colorMode.preference === 'dark' ? 'light' : 'dark';
10    buttonState.value = colorMode.preference === 'dark';
11  }
12};
13
14const buttonState = ref(false);
15
16onMounted(() => {
17  // 根据最开始的主题设置按钮的图标
18  buttonState.value = colorMode.value === 'dark';
19})

这里深色模式的实现有点太不优雅了,我发现 NuxtUI 官网确实有一个跟随主题的开关,但是自己实现起来就是很奇怪,对于输出的 colorMode 有两个用的上的属性,一个是 preference 对应偏好主题(light dark system),一个是 value 对应当前主题(light dark),由于偏好能被保存下来,于是选择在切换按钮时改变 preference 的对应的值

当组件被挂载(onMounted),首先根据 value 设置初始的状态,当点击切换时,对于当前是否偏好系统要采取不同的方式来切换,不知道大佬们有没有什么好办法,或者过几天我再看看 Nuxt 源码

相关推荐

使用 BeautifulSoup 配合请求库实现简单的爬虫程序

事情起源于课内的课程实验作业...因为要求要用爬虫,~~不必说课内讲的一言难尽,更不必说就算讲了我也...

grtsinry43
1/7/2025
67
0
0

学习分享|跨域解决、安卓开发探索、油猴脚本探索

最近学习的一些内容,包括跨域问题及其解决方案,安卓开发的简单探索,OpenAI的api做了个小插...

grtsinry43
6/10/2024
35
0
0

使用 pf4j-spring 实现插件注入和 api 接口动态注册 | 插件系统构建(上)

哪个男孩不想拥有一个自己的插件系统?(x)话说回来,这个我已经计划好久了,不过一直在学其他的东西,刚...

grtsinry43
1/26/2025
40
0
0

问题解决|使用Less变量和媒体查询实现深浅色模式适配

使用Less变量简化css写法,并不影响css变量和媒体查询在深浅模式切换时的效果 <!--m...

grtsinry43
6/10/2024
33
0
0

用一个月的时间写一个自己的博客系统——Grtblog的技术介绍

终于,历时一个多月的开发 ~~bug~~ 和测试,这个目前问题很多很不成熟很难用的系统终于上线了.....

grtsinry43
12/14/2024
117
4
0
COMMENT 7273217684182011904

发表评论

登录之后评论体验更好哦 ~
支持 Markdown 语法 0 / 3000

在风雨飘摇之中

本站已运行了

一路走来,感谢陪伴与支持

愿我们不负热爱,继续前行

全站通知
更新通知