Vue 3 模块化作品集主页,浅色极简风格,中英双语懒加载 i18n。 - 模块注册表(import.meta.glob)约定式收集项目模块,新增页签无需改导航/路由 - i18n: 中文同步注入主 chunk,英文动态 import() 拆独立 chunk,仅切换时下载 - 第一个页签 mobile-game: 展示 448/449 移动游戏毕设(概览/截图轮播/版本时间线/团队/排行榜/ML视频) - 排行榜复用 /449/449rest.php,失败优雅降级 - 构建: vite outDir=/root/html,emptyOutDir=false,产物用 mainPage/ 命名空间 - 样式: CSS 变量令牌,无 UI 框架运行时依赖
8.7 KiB
mainPage · 作品集主页
Zikai 的作品集主页 -- 一个 Vue 3 模块化的多项目展示站点。 采用浅色极简美术风格,中英双语并支持懒加载(默认中文,只看中文的访客不会下载英文资源)。 设计目标:高内聚低耦合、可扩展 -- 后续每个新项目都是一个独立「模块」,自动生成页签与路由。
这是「主页」项目本身。它展示的第一个项目页签是 448/449 移动游戏毕设, 详见同级目录下的
/root/html/448/README.md与/root/html/449/README.md。
技术栈
| 层 | 选型 |
|---|---|
| 框架 | Vue 3(<script setup> Composition API) |
| 构建 | Vite 5 |
| 路由 | vue-router 4(history 模式,路由表由模块注册表动态生成) |
| 国际化 | vue-i18n 9(中文同步注入,英文动态 import() 懒加载) |
| 样式 | 原生 CSS + CSS 变量令牌(无 UI 框架,零运行时样式依赖) |
Node 版本要求:≥ 18(本项目在 Node 18.19 + npm 9.2 下开发与构建)。
目录结构
mainPage/
├── index.html # Vite 入口模板
├── package.json
├── vite.config.js # ★ 构建输出配置(见下「构建与部署」)
├── .gitignore
├── README.md # 本文件
├── public/
│ └── favicon.svg # 站点图标
└── src/
├── main.js # 应用入口(挂载 i18n、router、全局样式)
├── App.vue # 根布局:顶栏 + 标签导航 + <router-view> + 页脚
│
├── i18n/ # 国际化(懒加载核心)
│ ├── index.js # i18n 实例;仅同步注入中文;loadLocaleAsync() 动态切语言
│ └── locales/
│ ├── zh-CN.js # 中文(默认,打进主 chunk)
│ └── en.js # 英文(动态 import() -> 独立 chunk,切换时才下载)
│
├── router/
│ └── index.js # 路由表遍历模块注册表自动生成
│
├── modules/ # ★★★ 扩展点:每个项目一个模块文件夹
│ ├── index.js # 模块注册表(import.meta.glob 约定式收集)
│ └── mobile-game/ # 第一个页签:448/449 移动游戏项目
│ ├── index.js # 模块元数据(id / tabKey / order / 懒加载组件)
│ ├── MobileGame.vue # 项目展示主页
│ ├── components/
│ │ ├── HeroSection.vue # 顶部项目概览横幅
│ │ ├── ScreenshotCarousel.vue# 截图轮播(复用 /448/1..3.jpg)
│ │ ├── VersionTimeline.vue # 版本演进时间线
│ │ ├── TeamCard.vue # 团队成员卡片
│ │ └── Leaderboard.vue # 排行榜(AJAX 调 /449/449rest.php,失败降级)
│ └── data/
│ ├── versions.js # 版本数据(448 各版本信息)
│ └── team.js # 团队成员数据
│
├── components/ # 全局共享组件
│ ├── TabNav.vue # 标签页导航(由模块注册表驱动,自动生成页签)
│ ├── LanguageSwitcher.vue # 中/英切换按钮
│ └── ui/ # 基础 UI 基元
│ ├── Card.vue
│ └── Tag.vue
│
├── composables/ # 组合式逻辑
│ ├── useProjects.js # 读取已注册模块列表
│ └── useI18nLazy.js # 语言懒加载切换逻辑
│
└── styles/
├── variables.css # 主题令牌(浅色极简:色板/圆角/阴影/间距)
└── base.css # 重置 + 排版基础
架构要点
1. 模块化扩展(高内聚低耦合)
新增一个项目页签 = 新建 src/modules/<新项目>/ 文件夹,无需改动导航或路由代码。
src/modules/index.js用import.meta.glob('./*/index.js', { eager: true })约定式收集所有模块。- 每个模块
index.js默认导出元数据:export default { id: 'mobile-game', // 唯一标识,同时作路由 path tabKey: 'tabs.mobileGame', // i18n 键,页签标题 order: 1, // 页签排序 component: () => import('./MobileGame.vue') // 懒加载组件 } TabNav.vue遍历注册表渲染页签;router/index.js遍历注册表生成路由。- 模块自包含组件、数据,模块间无直接引用 -> 高内聚低耦合。
2. i18n 懒加载(中文页不加载英文资源)
- 创建 i18n 实例时只同步注入中文
zh-CN(随主 chunk 下发)。 en.js通过() => import('./locales/en.js')注册,Vite/Rollup 自动拆成独立 chunken.[hash].js。- 切换英文时
useI18nLazy先await import()拉取英文 chunk,mergeLocaleMessage后再切locale。 - 结果:只看中文的访客永不请求英文 chunk;首次切英文才下载,之后切换无网络请求。
- 构建产物可见
js/mainPage/en.[hash].js(约 0.27 KB)独立存在。
3. 浅色极简美术
主题令牌集中在 src/styles/variables.css:白底 #fff / 浅灰面 #f7f8fa、单一靛蓝强调色 #4f46e5、圆角 12px、柔和阴影、细线边框、充足留白。无深色、无渐变铺底、无霓虹;悬浮微交互克制(轻微上移 + 阴影加深)。
开发
cd /root/zikai/mainPage
npm install # 首次安装依赖
npm run dev # 启动开发服务器 (http://localhost:5173)
开发服务器配置了代理:/448、/449 请求转发到 http://localhost:8080
(假设该端口有静态服务器在跑,否则截图/排行榜/视频会 404,但页面其余部分正常)。
开发时可临时用 python3 -m http.server 8080 --directory /root/html 提供这些静态资源。
构建与打包
npm run build # 产物输出到 /root/html
输出路径与安全策略(vite.config.js)
build.outDir = '/root/html',emptyOutDir = false(★ 不清空 outDir)。/root/html已含 448/449/旧 js/css 等既有内容,绝不能被构建清空。- 用
mainPage/命名空间子目录避免与/root/html/js、/root/html/css旧文件冲突:- JS ->
js/mainPage/[name].[hash].js - CSS ->
css/mainPage/[name].[hash].css - 其他资源 ->
assets/mainPage/[name].[hash][extname]
- JS ->
base = '/',引用既有 448/449 资源用站点根绝对路径(/448/...、/449/...)。
构建产物示例
/root/html/
├── index.html # 入口(Vite 注入 <script>/<link>)
├── favicon.svg
├── js/mainPage/
│ ├── index.[hash].js # 主 chunk(含 Vue/router/中文 i18n)
│ ├── MobileGame.[hash].js # 移动游戏页(懒加载)
│ └── en.[hash].js # 英文语言包(懒加载,仅切英文时下载)
└── css/mainPage/
├── index.[hash].css # 全局样式
└── MobileGame.[hash].css # 移动游戏页样式
预览构建产物
npm run preview # 本地预览构建后的产物
部署
构建产物直接落在站点根 /root/html,由 Web 服务器(如 nginx)以 /root/html 为根提供静态服务即可。
注意:当前主机上 nginx 默认 root 为 /var/www/html(与 /root/html 内容同步);
若需以 /root/html 为根对外服务,请调整 nginx 的 root 指令并启用 nginx。
主页引用的 /448/...、/449/... 资源必须能从站点根访问到(448/449 目录本就在 /root/html 下)。
如何新增一个项目页签
- 复制
src/modules/mobile-game/为src/modules/<新项目>/。 - 编辑
<新项目>/index.js,改id、tabKey、order、component指向。 - 在
src/i18n/locales/zh-CN.js与en.js的tabs下新增对应的tabKey文案。 - 实现模块主组件与子组件(可复用
components/ui/基元)。 npm run build-- 页签与路由自动出现,无需改动TabNav或router。
已知限制
- 排行榜依赖
/449/449rest.php(PHP + MySQL)在线;后端不可用时组件优雅降级显示「服务暂不可用」。 - 演示视频
/448/ml/449ml.mp4(约 34 MB)用preload="none",点播才加载。 - 448/449 的 README 总结了既有项目(构建产物,无源码),见各自目录。