最近在整理 Nuxt 项目的基础结构,顺手把全局样式和 app.head 的配置方式记录一下。
1. 取消 body 默认 margin
全局样式我直接放在:
app/assets/styles/global.scss
例如:
html,
body {
margin: 0;
padding: 0;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
然后在 nuxt.config.ts 里全局引入:
export default defineNuxtConfig({
css: [
'~/assets/styles/global.scss'
]
})
Nuxt 的 css 配置会把对应样式注入整个应用,所以像 Reset、字体、基础排版、CSS Variables 这类全局样式,都可以统一从这里管理。
如果项目使用 SCSS,也可以直接:
export default defineNuxtConfig({
css: [
'~/assets/styles/global.scss'
]
})
前提是安装了 Sass:
pnpm add -D sass
我目前比较倾向于把样式结构拆成:
app/
└─ assets/
└─ styles/
├─ reset.scss
├─ variables.scss
└─ global.scss
然后统一引入:
export default defineNuxtConfig({
css: [
'~/assets/styles/reset.scss',
'~/assets/styles/variables.scss',
'~/assets/styles/global.scss'
]
})
这样页面和组件里的 <style scoped> 只负责局部样式,全局规则不会到处散。
2. app.head 是干什么的
除了 css,nuxt.config.ts 里还有一个比较常用的:
app: {
head: {}
}
它主要负责整个应用固定的 HTML Head 配置。
例如:
export default defineNuxtConfig({
app: {
head: {
title: 'My Website',
htmlAttrs: {
lang: 'zh-CN'
},
meta: [
{
name: 'description',
content: 'My Nuxt Website'
}
],
link: [
{
rel: 'icon',
href: '/favicon.ico'
}
]
}
}
})
app.head 属于静态全局配置,比较适合放不会随着页面变化的内容,比如默认标题、语言、favicon 等。Nuxt 当前使用 Unhead 管理这些 Head 信息。
3. app.head 常用配置项
比较常见的配置基本是这些:
| 配置 | 用途 |
|---|---|
title |
页面默认标题 |
titleTemplate |
标题模板 |
htmlAttrs |
设置 <html> 属性 |
bodyAttrs |
设置 <body> 属性 |
meta |
Meta 标签 |
link |
favicon、stylesheet、preconnect 等 |
script |
外部或内联脚本 |
style |
内联样式 |
noscript |
<noscript> |
base |
<base> 标签 |
charset |
字符编码 |
viewport |
viewport |
Nuxt 默认已经提供:
charset: utf-8
viewport: width=device-width, initial-scale=1
一般不需要重复配置。
一个稍完整点的例子:
export default defineNuxtConfig({
app: {
head: {
title: 'ARON WANG',
htmlAttrs: {
lang: 'zh-CN'
},
bodyAttrs: {
class: 'app-body'
},
meta: [
{
name: 'description',
content: 'Personal portfolio website'
}
],
link: [
{
rel: 'icon',
type: 'image/x-icon',
href: '/favicon.ico'
},
{
rel: 'preconnect',
href: 'https://fonts.googleapis.com'
}
],
script: [
{
src: 'https://example.com/sdk.js',
defer: true
}
]
}
}
})
4. css 和 app.head.style 不要混着用
app.head 本身也支持:
style: []
例如:
export default defineNuxtConfig({
app: {
head: {
style: [
{
innerHTML: `
body {
margin: 0;
}
`
}
]
}
}
})
当然能生效,但普通项目样式没必要这么写。
我自己的区分方式很简单:
项目样式
→ css
HTML Head 信息
→ app.head
也就是说:
body {
margin: 0;
}
这种东西就放 SCSS。
而:
<meta>
<link>
<script>
这些再交给 app.head。
Nuxt 官方也将 css 作为全局本地样式的直接配置入口。
5. 页面自己的 Head 用 useHead
app.head 更适合全局固定配置。
如果某个页面需要自己的标题:
<script setup lang="ts">
useHead({
title: 'Works'
})
</script>
或者:
<script setup lang="ts">
useHead({
title: 'About',
meta: [
{
name: 'description',
content: 'About page'
}
]
})
</script>
useHead() 支持响应式数据,所以更适合页面级或者动态内容。
比如:
const project = ref({
name: 'Nuxt Portfolio'
})
useHead({
title: computed(() => project.value.name)
})
6. SEO 可以直接用 useSeoMeta
如果只是处理 SEO Meta,写起来还可以更简单:
useSeoMeta({
title: 'Nuxt Portfolio',
description: 'My personal portfolio',
ogTitle: 'Nuxt Portfolio',
ogDescription: 'My personal portfolio',
twitterCard: 'summary_large_image'
})
相比手动维护:
meta: [
{},
{},
{}
]
可读性会好很多,而且有类型提示。
最后整理一下
目前我的 Nuxt 项目里会按下面这个方式分:
全局 CSS / SCSS
→ nuxt.config.ts → css
全局固定 Head
→ nuxt.config.ts → app.head
页面级 Head
→ useHead()
SEO Meta
→ useSeoMeta()
例如最基础的配置:
export default defineNuxtConfig({
css: [
'~/assets/styles/global.scss'
],
app: {
head: {
title: 'My Website',
htmlAttrs: {
lang: 'zh-CN'
},
link: [
{
rel: 'icon',
href: '/favicon.ico'
}
]
}
}
})
global.scss:
*,
*::before,
*::after {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
}
基础配置基本到这里就够用了,后面项目变复杂再继续拆 Reset、变量、字体和主题。