使用nuxt3重构个人网站

nuxt
框架
2024-05-04 16:15

不闻不若闻之,闻之不若见之,见之不若知之,知之不若行之,学至于行而止矣。

前言

使用Nuxt 3重构个人网站:从Vite到Nuxt的转型之旅

在前端开发领域,技术的更新换代总是快速而频繁的。作为一名热衷于技术探索的开发者,学习使用新的技术栈来以保持与时俱进。最近,我决定将我的个人网站从基于Vite 5.x、Vue 3、Tailwind CSS、Pinia、Bootstrap 5.x以及Element-Plus组件库的技术栈,转型为使用Nuxt 3、Vue 3、Tailwind CSS、Pinia和Quasar的新架构。

背景与动机

我的个人网站最初是基于Vite 5.x和Vue 3构建的,使用了Tailwind CSS进行样式设计,Pinia作为状态管理工具,Bootstrap 5.x用于快速布局和样式预设,以及Element-Plus组件库来丰富页面交互。然而,对于SPA来说,SEO的支持并不是那么的友好。

此外:

  1. 首屏加载时间长:SPA将所有页面资源打包在一个文件中,可能导致首屏加载时间较长。
  2. SEO挑战:由于SPA是通过JavaScript动态渲染内容的,搜索引擎可能难以索引其内容,从而影响SEO效果。不过,可以通过服务端渲染(如Nuxt3的SSR模式)等技术来改善SEO。
  3. 对JavaScript的依赖:SPA高度依赖于JavaScript,如果用户的浏览器不支持或禁用了JavaScript,则可能导致应用无法正常工作。

随着Nuxt 3的发布,我被其带来的服务器端渲染(SSR)和静态站点生成(SSG)的功能所吸引。Nuxt 3不仅能够提供更快的页面加载速度和更好的用户体验,还能通过其内置的功能和插件生态,简化开发流程,提高开发效率。因此,我决定对网站进行重构,顺便也作为一个学习nuxt的练习项目。

Nuxt 3

  1. Nuxt 3 vs Vite 5.x

Nuxt 3是一个基于Vue 3的服务器端渲染框架,它提供了丰富的功能和插件生态,支持SSR、SSG和静态网站部署。Nuxt使用约定和一套规范的目录结构来自动化重复的任务,让开发者可以专注于推动功能的开发。配置文件仍然可以自定义和覆盖其默认行为。

认识nuxt3

  • 基于文件的路由: 根据pages/目录的结构定义路由。这样可以更容易地组织应用程序,避免手动配置路由的需要。
  • 代码分割: Nuxt自动将代码拆分成较小的块,这有助于减少应用程序的初始加载时间。
  • 内置服务器端渲染: Nuxt具备内置的服务器端渲染能力,因此你不需要自己设置单独的服务器。
  • 自动导入: 在各自的目录中编写Vue组件和可组合函数,并在使用时无需手动导入,享受树摇和优化JS捆绑包的好处。
  • 数据获取工具: Nuxt提供了可用于处理与服务器端渲染兼容的数据获取的可组合函数,以及不同的策略。
  • 零配置的TypeScript支持: 可以编写类型安全的代码,无需学习TypeScript,因为我们提供了自动生成的类型和tsconfig.json配置文件。
  • 配置好的构建工具: 我们默认使用Vite来支持开发中的热模块替换(HMR),以及在生产中将代码打包成符合最佳实践的形式。

服务器端渲染

  • Nuxt默认具备内置的 服务器端渲染(SSR)能力,无需自己配置服务器,这对于Web应用有许多好处:

    • 更快的初始页面加载时间: Nuxt向浏览器发送完全渲染的HTML页面,可以立即显示。这可以提供更快的页面加载时间和更好的用户体验(UX),特别是在网络或设备较慢的情况下。
    • 改善SEO: 搜索引擎可以更好地索引SSR页面,因为HTML内容立即可用,而不需要依赖JavaScript在客户端渲染内容。
    • 在低功率设备上的更好性能: 减少了需要在客户端下载和执行的JavaScript量,这对于处理重型JavaScript应用程序可能有困难的低功率设备非常有益。
    • 更好的可访问性: 内容在初始页面加载时立即可用,改善了依赖屏幕阅读器或其他辅助技术的用户的可访问性。
    • 更容易的缓存: 页面可以在服务器端缓存,这可以通过减少生成和发送内容所需的时间而进一步提高性能。

    总体而言,服务器端渲染可以提供更快更高效的用户体验,同时改善搜索引擎优化和可访问性。

  1. Quasar vs Bootstrap 5.x + Element-Plus

Quasar是一个基于Vue 3的开源UI框架,它提供了丰富的组件和插件,支持多种平台和设备。与Bootstrap 5.x和Element-Plus相比,Quasar更加专注于Vue 3的集成和优化,提供了更加灵活和可定制的组件库。此外,Quasar还支持Material Design、iOS和Android等多种设计风格,使得开发者可以更加轻松地构建出符合用户需求的界面。

创建nuxt项目

要求:Node.js - v18.0.0 或更新版本

shell 复制代码
npx nuxi@latest init <project-name>

搭建项目结构

首先,我使用Nuxt 3的官方脚手架工具创建了一个新的项目,并配置了必要的依赖和插件。然后,我根据网站的需求,设计了合理的项目结构,包括页面、组件、样式、路由等部分。

bash 复制代码
leisure-article
├── README.md
├── api # 接口文件
├── app.vue # 入口文件
├── assets # 静态资源
├── components # 全局组件
├── composables # 组合式函数
├── constant # 枚举常量
├── ecosystem.config.js 
├── layouts # 布局文件
├── nuxt.config.ts # 配置文件
├── pages # 页面文件
├── plugins # 插件
├── server # 服务端
├── store # 状态管理
├── tailwind.config.ts # tailwindcss配置
├── tsconfig.json
└── utils # 工具类

配置tailwindcss

  1. 安装
bash 复制代码
# Using pnpm
pnpm add --save-dev @nuxtjs/tailwindcss

# Using yarn
yarn add --dev @nuxtjs/tailwindcss

# Using npm
npm install --save-dev @nuxtjs/tailwindcss
  1. 添加到nuxt.config.ts
typescript 复制代码
export default defineNuxtConfig({
  modules: [
    '@nuxtjs/tailwindcss'
  ]
})
  1. 配置tailwind-config
typescript 复制代码
import type { Config } from 'tailwindcss'

export default {
  prefix: 'cz-',// 配置样式前缀,以cz-xxx开头
  content: [
    './components/**/*.{vue,js,ts}',
    './layouts/**/*.vue',
    './pages/**/*.vue',
    './app.{js,ts,vue}'
  ],
  // 3.4+版本的配置,如果不是,查看官网进行修改
  darkMode: ['class', '[class="dark"]'],
  theme: {
    extend: {
      boxShadow: {
        base: '2px 2px 5px 1px rgba(229,231,235,1)'
      }
    }
  },
  plugins: []
} satisfies Config

以上是基于nuxt3集成了tailwindcss,所以会少很多的配置就可以直接使用,如果不是,需要根据tailwindcss进行配置

bootstrap-icons图标库

使用bootstrap-icons图标库有两种方式,一是使用官方的安装方式,二是使用nuxt3集成的nuxt-bootstrap-icons方式,使用这种方式的好处是有图标提示,但是我这里使用的是第一种方式。至于为什么没有使用集成的图标库,因为在使用过程中发现有些图标无法使用,大概看了源码,基本上也是使用bootstrap-icons进行封装,所以直接使用官网的方式可能会直接一点,直接选择需要的图标复制代码即可。

  1. 安装
bash 复制代码
npm i bootstrap-icons
  1. 引入样式文件
typescript 复制代码
// app.vue
import 'bootstrap-icons/font/bootstrap-icons.css';

集成Quasar组件库

开始的想法是不依赖任务的组件库进行重构,但是基于目前个人的业余时间限制,同时也想着能够更快的重构完成,先基于组件库方法开发吧。

在做组件库选择的时候,为什么没有选择Element-Plus继续作为UI库,其一原因是它对于响应式的配合度不是很高,然后转而想使用vuetify组件框架进行重构,但是在使用的过程中发现,在进行SSR时,会出现一些组件水合问题,关于这一个问题在其issue上面也会有一样的问题,但是还是无法解决,对于一个有着强迫症😂的人来说,总感觉哪里怪怪的。

在迁移过程中,我逐渐将原有的Bootstrap 5.x和Element-Plus组件替换为Quasar组件。至于为什么选择Quasar

因为:

  • 基于Vue.js
  • 开箱即用的提供给网站应用程序的最先进的UI(遵循《Material指南》)
  • 开箱即用的对桌面和移动浏览器(包括iOS Safari!)的最佳支持
  • 通过与我们自己的CLI紧密集成,对每种构建模式(SPA、SSR、PWA、移动应用程序、桌面应用程序和浏览器扩展)提供了一流的支持,并提供了最佳的开发人员体验
  • 易于自定义(CSS)和可扩展(JS)
  • 这是最注重性能的框架
  • 自动tree shaking
  • 在我们的论坛和Discord聊天基础上的很棒的社区
  • 具有包括新功能在内的定期发布周期
  • 获得快速修复并听取社区的要求
  • 处理整个开发经验(甚至包括创建应用程序的图标和启动画面)

QIcon组件允许你轻松地在其他组件或页面的任何其他区域插入图标。 Quasar开箱即用支持:Material IconsMaterial SymbolsFont AwesomeIoniconsMDIEva IconsThemify IconsLine AwesomeBootstrap Icons

此外,您可以对任何图标库自行添加支持

Quasar中有多种图标类型:基于Webfont,基于svg和基于图像。 您不必在网站/应用中仅使用一种类型。

重要的是,其图标库组件还会支持bootstrap-icons,完美的契合度🙌

以上时来自Quasar官网的介绍,这一看,哎,这不是符合我的需求嘛,开箱即用的桌面和移动浏览器端,噗哈哈哈哈(太开心了🤣🤣🤣)

  1. 安装
bash 复制代码
# npm
npm install quasar @quasar/extras
npx nuxi@latest module add quasar
  1. 配置nuxt.config.ts
typescript 复制代码
  quasar: {
      // 添加相关插件
    plugins: [
        'Notify',
        'Dialog'
    ],
    extras: {
      font: 'roboto-font',
    },

    components: {
      defaults: {
        QBtn: {
          unelevated: true,
        },
      },
    },
  },

迁移页面和组件

接下来,我开始将原有的页面和组件迁移到新的项目中。由于Nuxt 3和Vue 3的API与Vite 5.x和Vue 3基本一致,因此迁移过程相对顺利。我主要关注于页面和组件的布局、样式和交互逻辑的实现,确保它们在新的项目中能够正常工作。

开始码字

时间原因此处省略xxx字(后面抽时间补上噗哈哈哈哈)

部署上线

node环境

  1. 打包
typescript 复制代码
npm run build
  1. 编写启动文件ecosystem.config.js
typescript 复制代码
module.exports = {
    apps: [
        {
            name: 'articleNuxt',
            port: '6666',
            exec_mode: 'cluster',
            instances: 'max',
            script: './server/index.mjs'
        }
    ]
}

打包后的文件,然后将ecosystem.config.js复制到。output目录下即可。

image-20240504133135866
  1. 宝塔面板启动项目

    可能第一次启动的时候会出现,找不到package.json提示,此时,关闭然后修改项目目录即可。

image-20240504133647632

nginx配置代理

主要部分配置文件

在添加域名和开启外网访问时,会生成相关的nignx文件,然后添加以下代理即可。

nginx 复制代码
server
{
    # HTTP反向代理相关配置开始 >>>
    location ~ /purge(/.*) {
        proxy_cache_purge cache_one $host$request_uri$is_args$args;
    }

    location / {
        proxy_pass http://127.0.0.1:端口;# 转发到pm2启动的项目地址,一般默认127.0.0.1地址即可
        proxy_set_header Host $host:$server_port;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header REMOTE-HOST $remote_addr;
        add_header X-Cache $upstream_cache_status;
        proxy_set_header X-Host $host:$server_port;
        proxy_set_header X-Scheme $scheme;
        proxy_connect_timeout 30s;
        proxy_read_timeout 86400s;
        proxy_send_timeout 30s;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
    # HTTP反向代理相关配置结束 <<<
#PROXY-START/api/
    # 可以不配此处
location ~* \.(php|jsp|cgi|asp|aspx)$
{
	proxy_pass https://xxx域名地址;
    proxy_set_header Host xxx域名地址;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header REMOTE-HOST $remote_addr;
}
    # 启用api代理
location ^~ /api/
{
    proxy_pass https://xxx域名地址/;
    proxy_set_header Host xxx域名地址;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header REMOTE-HOST $remote_addr;
    
    add_header X-Cache $upstream_cache_status;
    
    #Set Nginx Cache

    proxy_set_header Accept-Encoding "";
		sub_filter "/api/" "/";# 注意将api替换成需要代理的前缀
    sub_filter_once off;
    	add_header Cache-Control no-cache;
    expires 12h;
}

#PROXY-END/api/
    access_log  /www/wwwlogs/server.log;
    error_log  /www/wwwlogs/server.error.log;
}

完美效果(部分截图)

image-20240504134843247
image-20240504134916605

好了,今天就写到这里吧~,最后祝大家五一节日快乐叭。

img

相关链接

  1. nuxt3中文网
  2. tailwindcss中文网
  3. quasar中文网
  4. bootstrap-icons图标库
最近更新:

目录