🤷♂️ 为什么要自己写个官网?
俗话说:"人靠衣装,佛靠金装,公司靠官网装。"
官网是公司的门面,就像是 名片 + 海报 + 展厅 的三合一。
如果官网掉链子,那就像穿着拖鞋去相亲------第一印象直接减分。
我们公司之前的官网,是几年前外包团队做的:
- 技术栈老得能当"古董";
- UI 风格满满的 2015 味儿;
- 响应式体验勉强凑合,性能还常常"慢半拍";
- 更要命的是:每次想加个新功能,都得像修老爷车一样,拧半天螺丝,还不一定能启动。
所以,经过自我的灵魂拷问,最终决定: 👉 "自己动手,丰衣足食"
⚙️ 技术选型:把官网打造成"国际化大别墅"
我们的新官网为什么选 Nuxt3 ?因为它比普通 Vue3 就像 跑车比自行车 (😱💥🤯些许夸张):
- 快得飞起:内置服务端渲染 + 静态生成,页面秒开不拖拉。
- 搜索引擎爱它:百度、Google、Bing都抢着认它朋友。
- 开发起来像开挂:文件路由自动生成、组合式 API、TypeScript 支持,写代码也能"飘起来"。
- 改版不慌:组件化 + Pinia,团队协作顺畅,维护像玩积木一样轻松。
总结一句:Nuxt3 不只是盖个官网,它帮我们盖了个 智能别墅------炫酷、好用、随时升级。而之前那个老外包官网?嗯......就像老式公寓,住得了,但卡顿掉漆,让人抓狂。
这就是我们选择 Nuxt3 的理由------既要面子,也要里子,还顺便秀了点技术实力。
新官网可不是随便盖盖,我们得满足老板的"国外网站范儿"审美:大气、简洁、有格调。于是技术选型就像挑家具------要好看,还要好用:
-
国际化支持(i18n):官网得能说多国语言,客户来自世界各地,不然国外的小伙伴看到中文界面估计直接右上角叉掉。但涉及到每个页面元素、按钮文字、提示信息等等,都需要有人去整理、翻译、校对(这是痛苦的过程,无论对于设计、还是对于开发人员);
-
TailwindCSS + Bootstrap:老板喜欢 Bootstrap 的简洁大气,我想用 Tailwind 玩出定制化风格......结果 CSS 冲突就像两只猫抢沙发,互相打架(解决方案在底部)。
-
Element Plus UI:"联系我们"模块中更青睐 Element Plus 表单的优雅交互。
- 实际用途 :
- Bootstrap:用于整体布局和国际化风格,满足老板对"国外网站大气感"的审美。
- Element Plus:专注于表单控件和交互体验,让用户填写信息更顺畅。
- 分析与建议 :
- 按需引入:Bootstrap 用于布局和网格,Element Plus 只在表单等必要模块引入。
- 避免冲突:两套 UI 样式尽量隔离,统一主题风格,避免界面割裂。
- 维护成本:虽然有两套 UI,但只在有限场景使用 Element Plus,维护成本可控。
- 实际用途 :
总结一句:Bootstrap 是"外表帅气",Element Plus 是"功能贴心",两者组合让网站既有颜值又有体验。
- Pinia(状态管理):严格来说不是必须,但给它留个位置,就像在客厅摆个备用沙发,什么时候需要随时派上用场。
总结一句:新官网就是一栋智能别墅,国际化大门敞开,布局漂亮,UI 风格多样,状态管理随时待命。走进来,你就知道"高级感"不是吹的。
🗂️ Nuxt3 项目结构
1. assets/
- 存放未编译的静态资源(SASS/LESS、图片、字体)。
- 不会直接被打包到
/public
,需通过import
或url()
使用。
2. components/
- 存放可复用的 Vue 组件。
- Nuxt3 支持 自动导入 ,可直接使用components/下定义的组件,自动导入统一把组件名转成 PascalCase 或 kebab-case,同时支持子目录嵌套,比如
components/ui/Button.vue → <UiButton />
(😅写惯了组件导入的方式,前期使用的时候都是手动导入,虽然都支持,但既然支持自动导入,尽量使用自动导入)。
3. composables/
- 存放自定义 Composition API 函数(
useXXX
)。 - 用于逻辑复用,例如
useUser()
、useProduct()
。
4. layouts/
- 页面布局模板,例如
default.vue
、bootstrap.vue
、admin.vue
、empty.vue
。 - 页面可通过
definePageMeta({ layout: 'bootstrap' })
使用不同布局。
5. middleware/
- 页面或路由守卫逻辑,例如登录验证、权限检查。
- 可全局或单页面使用。 📝 我们官网暂时不涉及注册登录的逻辑,可能有些公司涉及到产品购物车相关的业务,需要登录验证和权限检查
6. pages/
- 存放路由页面,自动生成路由。
- 例如
pages/index.vue
→/
,pages/about.vue
→/about
。 📝 Nuxt3支持动态路由,[param].vue
,比如我的产品详情页目录结构是pages/products/detail/[id].vue
7. plugins/
- 注册全局插件,如第三方库、全局组件、API 封装。
- 可选择客户端(xxx.client.ts)、服务端(xxx.server.ts)或两者同时加载(文件名无需 .client 或 .server)。 📝 一般涉及到window、document或者动画相关的都在客户端,访问数据库、文件系统都在服务端,一些工具函数则两端都可。
8. public/
- 放置静态资源,直接映射到网站根路径。
- 例如
/favicon.ico
、/robots.txt
,因为官网涉及到很多资源素材,同样也存放在该目录,如图片、视频、字体等。
9. server/
- Nuxt3 内置服务端目录(Nitro)。
server/api/
→ REST API 路由,例如server/api/user.ts
→/api/user
。server/plugins/
→ 服务端插件,例如数据库连接、日志处理。 📝 讲道理这块我没有用到,因为我搭了一个简单的springboot的后台,直接调用api,包括联系我们的提交和获取商品的列表和明细直接通过封装的api方法去请求,看介绍说server/
是 服务端扩展目录 ,用于自定义 API 和插件。不是必需,尤其是纯前端、静态或只依赖外部API的Nuxt3项目。只有在你需要服务端逻辑(如数据库、日志、缓存、邮件)时,才需要使用,这块有待各位进一步探索,没使用不敢妄言。
10. .nuxt/
- Nuxt 内部生成目录,存放编译产物和自动生成代码。
- 不需手动修改,通常加入
.gitignore
。
11. nuxt.config.ts
nuxt.config.ts
是 Nuxt 3 项目的核心配置文件,负责定义整个项目的全局行为和配置。主要功能包括:
功能模块 | 说明 |
---|---|
🏷️ 页面信息与 HTML Head | 配置网站标题、meta 信息、favicon、外部脚本等,确保 SEO 与页面基础信息完整 |
🎨 全局样式与 PostCSS 配置 | 引入全局 CSS/SCSS 文件,配置 PostCSS 插件(如 TailwindCSS、Autoprefixer)及自定义选择器前缀,统一样式规范 |
⚙️ 模块、插件与国际化 | 配置 Nuxt 模块(Tailwind、Pinia、i18n、Element Plus 等),支持国际化选项,包括语言、浏览器语言检测和消息管理 |
🌐 运行时环境变量 | 使用 runtimeConfig 管理开发与生产环境的 API 地址及公共变量,实现环境隔离和安全性 |
🚀 Vite 构建优化 | 配置 Vite 插件(如 SVG Loader)、依赖优化、代码拆分等,提高构建速度与性能 |
🔗 Nitro 服务端开发代理 | 配置 API 代理,用于本地开发环境调试后端接口,模拟服务端行为 |
12. package.json
- 项目依赖与脚本。
- 常用脚本:
dev
:开发模式build
:打包preview
:预览
13.其它(根据个人和项目需要)
- constants/ 存放项目常量
- types/ typescript生命定义
- stores/ pinia modules定义
- utils/ 工具类和方法
- directives/ 自定义指令(如数字滚动效果)
- app.vue 项目入口(全局loading可以在其中实现)
-
.env .env.development .env.production\] 相关环境变量定义
- tailwind.config.ts tailwindcss配置文件
- tsconfig.json ts配置文件
📦 Windows 服务器部署 Nuxt3(pm2 + Node.js)
在 Windows 服务器上,我们使用 pm2 运行 Nuxt3 构建后的 .output/server/index.mjs
。
-
Node.js ≥ 18
-
全局安装pm2,使用pm2管理项目
🌟 问题及解决方案
Nuxt3 数据请求封装总结
在 Nuxt3 中,useAsyncData
、useFetch
、$fetch
三者的区别与使用场景总结如下,掌握它们可以避免常见坑。
API | 类型 | SSR 支持 | 响应式 | 内部调用 | 适用场景 |
---|---|---|---|---|---|
$fetch |
请求工具 | ✅ 可在 SSR/CSR | ❌ 普通 Promise,不响应式 | 原生 ohmyfetch |
灵活调用 API,可在服务端、插件、组合函数中使用 |
useAsyncData |
数据获取组合式 API | ✅ SSR 缓存、响应式 | ✅ data/pending/error | 内部可用 $fetch |
获取异步数据并绑定组件,支持 SSR/客户端复用、缓存 |
useFetch |
useAsyncData 封装 |
✅ 同上 | ✅ 同上 | 内部直接调用 $fetch |
简化写法,GET 请求绑定模板最常用 |
⚠️ 注意:
useFetch
本质上是useAsyncData(() => $fetch(...))
的语法糖。
TailwindCSS + Bootstrap冲突:
xml
1. 在 `layouts` 中目录下定义了`bootstrap.vue`,给使用bootstrap布局的区域包一层 `.bootstrap-wrapper.bootstrap-scope`:
```vue
<template>
<div class="bootstrap-wrapper bootstrap-scope">
<TheHeader />
<div class="wrapper">
<slot />
<TheFooter />
</div>
</div>
</template>
<script setup>
import TheHeader from "~/components/TheHeader.vue";
import TheFooter from "~/components/TheFooter.vue";
</script>
```
2. 配合 PostCSS 插件 `postcss-prefix-selector` 给 Bootstrap 样式加前缀,只作用于 `.bootstrap-wrapper.bootstrap-scope` 内部:
```ts
postcss: {
plugins: {
tailwindcss: {},
autoprefixer: {},
"postcss-prefix-selector": {
prefix: ".bootstrap-wrapper.bootstrap-scope",
transform(prefix: string, selector: string, prefixedSelector: string): string {
if (selector === "html" || selector === "body") {
return `${prefix} ${selector}`;
}
return prefixedSelector;
},
includeFiles: [/bootstrap-prefixed\.css$/],
},
},
},
```
3. Tailwind 保持全局自由发挥,不影响 Bootstrap。`html` 和 `body` 特殊处理,避免基础样式被限制。
- 效果:两套 CSS 各玩各的,不踩地盘。Tailwind 是"自由派设计师",Bootstrap 是"规矩老板",加个前缀就能让他们和平共处,同时还可以保证布局一致性。
🤔 Reflect
🌟 这是我第一次用 Nuxt3 打造公司官网,整个过程充满了各种曲折与探索。
从配置环境、封装 API,到处理服务端渲染和部署,每一步都像在解谜,踩过不少坑,也学到了很多新技能。
如果文章里有任何不准确或者可优化的地方,非常欢迎大家指正和交流。
希望我的这次实战经验,能给同样第一次尝试 Nuxt3 的你一些参考和启发。
让我们一起探索,让官网不仅上线,更一步步完善成长吧!