最近公司新项目要使用SSR,浏览了下最新的一些框架,发现NuxtJS真心的非常棒,在这里把自己搭建项目的过程记录下,希望对有需要的人一些帮助。
一、初识NuxtJS
2021年10月13日,尤雨溪在微博上给Nuxt3带货了,在23日的直播分享再一次给Nuxt3带货,并且独占一页ppt,看来这个Nuxt3一定不简单!那这个框架是做啥的呢?我们就一起来看看吧。
1.简介
Nuxt 是使用简便的 Web 框架,用于构建现代和高性能的 Web 应用,可以部署在任何运行 JavaScript 的平台上。
Nuxt 3.0 于2022年11月18日正式发布了稳定版,3.0 基于 Vue 3,为 TypeScript 提供了 “一等公民” 支持,并进行了一次彻底的重构,对内核进行了精简,速度更快,体验更好。
Nuxt 3.0 的 API 已完全稳定,可用于生产环境。所有可组合项、文件系统约定和配置都确保向后兼容 Nuxt 3.0.0。Nuxt 3 目前支持 Node.js 14、16、18 和 19,建议使用最新的 Node.js LTS 版本,由于 Node.js 14 即将 EOL,开发者最好尽可能升级到最新的 18.x。
2.新特性
- 更轻量:以现代浏览器为目标的服务器部署和客户端产物最多可缩小 75 倍
- 更快:基于 nitro 提供动态代码分割能力,以优化冷启动性能
- Hybrid:增量静态生成和其他的高级功能现在都成为可能
- Suspense:在任意组件和导航前后都可以获取数据
- Composition API:使用 Composition API 和 Nuxt 3 的 composables 实现真正的代码复用
- Nuxt CLI:没有任何依赖,帮你轻松搭建项目和集成模块
- Nuxt Devtools:通过直接在浏览器中查看信息和快速修复实现更快地工作
- Nuxt Kit:具有 Typescript 和跨版本兼容性的全新模块开发
- Webpack 5:更快的构建时间和更小的包大小,无需配置
- Vite:使用 Vite 作为打包工具,体验闪电般快速的 HMR
- Vue 3:Vue 3 是你下一个 Web 应用程序的坚实基础
- TypeScript:使用原生 TypeScript 和 ESM 构建,无需额外步骤
3.Nuxt独特之处
3.1 搜索引擎优化
解决Vue构建SPA项目(单页面应用程序)的带来的不利于SEO问题。如果你还不知道什么是SEO,下面的扩展内容要认真恶补一下了。
3.2 新建项目简单,项目启动和重构非常快
Nuxt3 使用 Vue.js 作为视图引擎。Nuxt3 中提供了所有 Vue 3 功能,所以我们创建的Nuxt项目其实也是vue3项目。而且很多工具Nuxt都帮我们选好了,我们可以简化搭建项目过程而专注于开发。比如,以下是部分Nuxt的选择:
- JavaScript 框架:Vue.js
- vue项目构建工具:Vite
- 热模块化开发:webpack 5
- 代码编译,用做 JavaScript 语法的转译器:esbuild(新时代的的性能构建工具)
- 后端服务的http框架:h3(支持Serverless、Worker 和 Node,性能强大)
- 导航路由:vue-router
- 打包工具:nuxt/vite-builder 和 nuxt/webpack-builder
按照约定,提供了一些默认目录(需要自己创建,Nuxt会识别),以便于路径访问,后面介绍的时候会提到这些目录。
- assets // 静态资源
- public // 公共静态资源,可公开获得
- pages // 开发页面
- components // 组件
- layouts // 项目布局
- middleware // 中间件
- plugins // 插件
- server // 后端
3.3 静态资源地址访问
public目录结构如下:
-| public/
--| img/
----| cute.png
以静态url的方式访问,基于“约定”,直接写 public 以下的路径即可
<template>
<img src="/img/cute.png" alt="卡哇伊" />
</template>
assets目录结构如下:
-| assets/
--| scss/
----| default.scss
--| ts/
----| index.ts
--| img/
----| cute.png
必须使用~/assets/路径引用位于目录中的文件:
<template>
<img src="~/assets/img/cute.png" alt="卡哇伊" />
</template>
3.4 路由使用
它是根据文件名从目录中创建的每个组件生成路由。不用像以前vue那样去router.js配置路由了,而且它有自己的路由传参方式,类似的其他路由功能Nuxt都有对应方式,更加清楚简单,也不会很容易搞错。
此文件系统路由使用命名约定来创建动态和嵌套路由,简单举例,像这样创建页面:
-| pages/
--| about.vue
--| posts/
----| [id].vue
修改app.vue
<template>
<header>
<nav>
<ul>
<li><NuxtLink to="/about">About</NuxtLink></li>
<li><NuxtLink to="/posts/1">Post 1</NuxtLink></li>
<li><NuxtLink to="/posts/2">Post 2</NuxtLink></li>
</ul>
</nav>
</header>
</template>
js方式响应跳转也可以用vue的 router.push(),不过Nuxt建议使用 await navigateTo()
<script setup>
async function clickAction() {
const router = useRouter();
// router.push({ path: "/about" });
await navigateTo({
path: "/about",
query: {
name: "furmen",
age: 18,
},
});
}
</script>
3.5 layouts布局
layouts布局很有用,类似于父组件,但不同,优势是简单继承可重用,比如定义了一个默认框架布局,设置在app.vue中,name在其之内的路由都默认继承拥有此外部框架。当然,可以选择是否继承和控制作用范围。框架组件必须放到layouts目录。
-| layouts/
---| default.vue
---| custom.vue
default.vue
<template>
<div>
默认布局
<slot />
</div>
</template>
<script>
// This will work in both `<script setup>` and `<script>`
definePageMeta({
layout: "custom",
});
</script>
app.vue
<template>
<NuxtLayout :name="layout">
<NuxtPage />
</NuxtLayout>
</template>
<script setup>
// 不设置name属性默认使用名为 default.vue 的布局组件,可通过 name 或 :name 动态修改默认布局。可以做到切换主题的功能
const layout = "custom";
</script>
NuxtLayout是Nuxt内置的布局组件
NuxtPage是Nuxt内置的路由出口组件,相当于vue-router中的router-view
3.6 middleWare中间件
Nuxt有强大的中间件功能,很方便定制,使用也简单,可设置作用范围,匿名、局部和全局。 当然也可以设置路由中间件,类似于vue的导航守卫,不过参数只有to和form,没有next()参数,要想取消to的访问可以直接 return abortNavigation() 终止导航,想要重定向的话可以使用 return navigateTo('/') 指定重定向路由。
-| middleware/
---| auth.ts
注意,中间件定义的路由方法名必须是 defineNuxtRouteMiddleware((to, from) =>{}) ,不可更改,这是约定,文件名随意。
auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
console.log("要去那个页面:"+to.path)
console.log(to)
console.log("来自那个页面:"+from.path)
console.log(from)
if (to.params.id === '1') {
return abortNavigation() // 终止导航
}
// return navigateTo('/xxx') // 重定向路由
})
其他页面中使用,引用这个路由中间件(也必须使用 definePageMeta({}) 方法)
<template>
......
</template>
<script setup>
definePageMeta({
middleware: ["auth"]
// or middleware: 'auth'
})
</script>
3.7 plugins插件
可引入第三方插件和自定义插件,后者不说前者一定用得到,同样配置简单,几乎是npm一下然后定义声明一下就好了。 同样约定,只有目录顶层的plugins/文件(或任何子目录中的index文件)将被注册为插件。
-| plugins
| - myPlugin.ts
| - myOtherPlugin
| --- supportingFile.ts
| --- componentToRegister.vue
| --- index.ts
其中,只有myPlugin.ts和myOtherPlugin/index.ts会被注册。
server服务,提供后端功能
-| server/
--| api/
----| hello.ts
--| routes/
----| hello.ts
Nuxt 提供了后端服务器功能,性能好,但是功能性没法和前后端分离比。
4.扩展-SEO
搜索引擎优化,又称为SEO,即Search Engine Optimization,它是一种通过分析搜索引擎的排名规律,对网站进行符合规则的优化的技术。可以提高网站在搜索引擎中的自然排名,吸引更多的用户访问网站,提高网站的访问量。
4.1 搜索引擎如何收集网站信息进行排名?
搜索引擎是通过专有的蜘蛛程序(爬虫)来查找出每一个网页上的HTML代码,它会搜索网站的所有链接,分析收集网站的关键字以便搜索,通过自身不断变化的算法进行自然排名。蜘蛛程序需要访问完所有的页面,需要花费很长的时间,所以网站的导航需要便于蜘蛛程序进行索引收录。如果我们的网站设计的很方便蜘蛛进行访问,加快它的访问速度。就有利于增加搜索引擎友好度。
4.2 为什么SPA不利于SEO?
只要是单页面的内容都是动态匹配路由进行渲染的,而且很多内容都需要在一个页面显示,那么就会有很多异步操作,蜘蛛程序不会去等你完全加载完的,想要对蜘蛛程序有好一点,就需要将更多的内容转换成静态资源,更快的加载完成,SSR渲染就是这样的原理,比如NUXT(使用SSR渲染)就可以帮你做到先从后台将所有数据加载过来然后整个给你返到前端,SEO效果只会更好,首屏加载速度也会快很多。
4.3 如何提高网站排名?
- 提高网站链接的访问质量和外网引用本网站链接的数量。
- 放置优质的内容,比如博客网站的话,文章尽量保持原创度。
- 网站结构要整洁简单,不要设计的过于复杂。
4.4 关键字一般设置在哪?
- title 标签(重要)
- meta 标签(主要,里面有几个重要的属性,例如keyword、description等)
4.5 关键词设置注意
- 要与网站主题相关,不要一味的追求热门词汇;
- 避免使用含义很广的一般性词汇,越明确越好,不要把小可爱当笨蛋
- 根据产品的种类及特性,尽可能选取具体的词
- 5至10个关键词比较好
- 网页内出现频率控制住,不要太多
了解了这么多,赶紧来上手nuxt吧
二、Nuxt3的安装启动
前提,确保有Nuxt3的安装环境
Node.js(必要)
Visual Studio Code(推荐)
Volar(推荐)
node.js 版本之间有差异,安装Nuxt3目前官方推荐v16,或更高的版本。
1.安装
首先在你的Nuxt3工作空间下新建一个Nuxt3项目,打开项目空间文件夹,在项目空间文件夹路径输入 cmd 或 powershell + 回车,打开命令窗口
安装方式:
(1)方式一:npx 安装
npx 是 npm5.2 之后发布的一个命令,可以代替 npm 命令安装依赖或包。
npx nuxi init nuxt-app # nuxt-app 是项目名
(2)方式二:pnpm 安装
pnpm 是 Node.js 的替代包管理器。它是 npm 的直接替代品,但速度更快、效率更高。
pnpm dlx nuxi init nuxt-app # nuxt-app 是项目名
因为 pnpm 和 npm 不是同一个东西,需要另外安装。如果你没有,可以建议安装使用。 直接使用 npx 或 npm 安装 pnpm。
安装 pnpm
npm install -g pnpm
或
npx pnpm add -g pnpm
-
注意
命令中的 nuxt-app 就是项目包名,也就是说,你在安装nuxt3 的同时会生成一个项目包,项目可自定义,如果刚开始定义包名是这个,也可以把项目删了重新新建项目。
没错,它的安装便是新建一个 Nuxt3 项目,中间不需要你选任何工具的配置,它已经默认帮你打造了一套优质舒适的开发环境。
-
踩坑
由于需要翻墙或其他原因,在写这篇文章时,执行安装命令时会提示
Error: Failed to download template from registry: request to https://raw.githubusercontent.com/nuxt/starter/templates/templates/v3.json failed, reason: getaddrinfo ENOENT raw.githubusercontent.com我们要做的事情就是访问提示的网址后,浏览器上会展示出一个JSON
{ "name": "v3", "defaultDir": "nuxt-app", "url": "https://nuxt.com", "tar": "https://codeload.github.com/nuxt/starter/tar.gz/refs/heads/v3" }访问其中的tar地址,就可以下载一个starter-3.tar.gz的压缩包,解压后starter3这个就是我们最终要下载安装的nuxt3项目模板了。
2. 启动
进入项目目录
cd starter3
执行命令安装项目依赖
npm install
yarn install
pnpm install
上面三个命令任意一个都可以,推荐yarn或pnpm
运行命令启动项目
npm run dev
yarn dev
pnpm dev
上面三个命令任意一个都可以
访问:http://localhost:3000/,就可以看到如下界面,表示项目运行成功。
三、项目基本配置
在开发项目中我们经常会使用到一些第三方库/插件、组件来丰富项目,这里列举一些开发后台项目用到的第三方库/插件、组件。
1.naive-ui
安装 naive-ui 和 @css-render/vue3-ssr
yarn add -D naive-ui @css-render/vue3-ssr
在 nuxt.config.ts 增添下列配置
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
build: {
transpile:
process.env.NODE_ENV === 'production'
? [
'naive-ui',
'vueuc',
'@css-render/vue3-ssr',
'@juggle/resize-observer'
]
: ['@juggle/resize-observer']
},
vite: {
optimizeDeps: {
include:
process.env.NODE_ENV === 'development'
? ['naive-ui', 'vueuc', 'date-fns-tz/esm/formatInTimeZone']
: []
}
}
})
在 Nuxt 项目的 plugins 文件夹增加naive-ui插件
修改app.vue
<template>
<n-config-provider>
<NuxtPage />
</n-config-provider>
</template>
<script setup>
import { NConfigProvider } from 'naive-ui'
</script>
新建pages目录,并创建index.vue文件
<template>
<div class="">
<h1>首页</h1>
<n-button>按钮</n-button>
</div>
</template>
<script setup>
import { NButton } from 'naive-ui';
</script>
<style scoped></style>
此时就可以使用naive-ui的button组件了。
在app.vue文件中,还可以配置主题
<template>
<n-config-provider
:locale="zhCN"
:date-locale="dateZhCN"
:theme-overrides="themeOverrides"
inline-theme-disabled
>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</n-config-provider>
</template>
<script setup>
import { zhCN, dateZhCN, NConfigProvider, NDialogProvider, NMessageProvider } from 'naive-ui';
// 自定义配置主题
const themeOverrides = {
common: {
primaryColor: "#FC8952",
primaryColorHover: "#FC8952",
primaryColorPressed: "#FC8952",
primaryColorSuppl: "#FC8952",
},
Button: {
textColor: "#FC8952",
border: "1px solid #FF763B",
textColor: "#FF763B",
}
};
</script>
naive-ui 默认情况下使用 inline style 作为主题变量的载体,因此每个组件上都会挂载许多 inline CSS。如果你需要 SSR,或者想让开发者工具看起来更干净,可以打开 inline-theme-disabled 属性。
2.EsLint
ESLint 是一个代码检查工具,用来检查你的代码是否符合指定的规范,实现统一代码风格。
-
规范
- 行业推荐的规范; 在创建项目时,我们使用的是 JavaScript Standard Style 代码风格的规则
- 自定义的规范。你和你的团队可以自行约定一套规范
-
使用ESLint的好处在于:多人协作时代码风格统一
单双引号、缩进、逗号等编码风格的统一十分有必要,下面使用 ESLint + Prettier + Husky 与 Lint Staged 配置 Nuxt 实现风格统一与代码优化,让代码更简洁,比如不允许未使用的变量,也可以指让代码更严谨,比如不允许未声明的全局变量,进一步提升工程的约束能力。
项目中需要预先安装
typescript依赖,且已经初始化 Git
2.1 配置基本的ESLint
执行下列命令,通过 ESLint 自带的初始化功能:
npx eslint --init
根据自己的需求回答一系列问题即可,如:
Need to install the following packages:
eslint
Ok to proceed? (y) y
You can also run this command directly using 'npm init @eslint/config'.
Need to install the following packages:
@eslint/create-config
Ok to proceed? (y) y
√ How would you like to use ESLint? · problems
√ What type of modules does your project use? · esm
√ Which framework does your project use? · vue
√ Does your project use TypeScript? · No / Yes
√ Where does your code run? · browser, node
√ What format do you want your config file to be in? · JavaScript
Local ESLint installation not found.
The config that you've selected requires the following dependencies:
eslint-plugin-vue@latest @typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest eslint@latest
√ Would you like to install them now? · No / Yes
√ Which package manager do you want to use? · yarn
Installing eslint-plugin-vue@latest, @typescript-eslint/eslint-plugin@latest, @typescript-eslint/parser@latest, eslint@latest
yarn add v1.22.19
如果选择了使用 TypeScript,它会自动为你安装@typescript-eslint一系列工具。按上述回答问题后最终安装了这些依赖:
"devDependencies": {
...
"@typescript-eslint/eslint-plugin": "^5.55.0",
"@typescript-eslint/parser": "^5.55.0",
"eslint": "^8.36.0",
"eslint-plugin-vue": "^9.9.0",
}
2.2 配置.eslintrc.js
同时在项目根目录会自动生成.eslintrc.js文件,打开并修改文件,结果如下:
module.exports = {
root: true,
env: {
browser: true,
es2021: true,
},
extends: [
'eslint:recommended',
'plugin:vue/vue3-essential',
'plugin:@typescript-eslint/recommended',
],
overrides: [],
parser: 'vue-eslint-parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
parser: '@typescript-eslint/parser'
},
plugins: ['vue', '@typescript-eslint'],
rules: {
'vue/script-setup-uses-vars': 'error',
'vue/custom-event-name-casing': 'off',
'vue/attributes-order': 'off',
'vue/one-component-per-file': 'off',
'vue/html-closing-bracket-newline': 'off',
'vue/max-attributes-per-line': 'off',
'vue/multiline-html-element-content-newline': 'off',
'vue/singleline-html-element-content-newline': 'off',
'vue/attribute-hyphenation': 'off',
'vue/require-default-prop': 'off',
'vue/multi-word-component-names': 'off',
'vue/html-self-closing': [
'error',
{
html: {
void: 'always',
normal: 'never',
component: 'always',
},
svg: 'always',
math: 'always',
},
],
'vue/no-v-html': 'off',
},
}
2.3 配置.eslintignore
创建.eslintignore文件,根据习惯忽悠部分文件。这里只让 ESLint 检查核心代码文件,包括 js、jsx、ts、tsx文件:
*.json
*.html
*rc.js
*.svg
*.woff
*.ttf
*.css
.nuxt
.husky
.eslintrc.js
.prettierrc.js
package.json
tsconfig.ts
README.md
node_modules
*.sh
*.md
.vscode
.idea
dist
build
/public
/docs
.husky
.local
/bin
Dockerfile
在package.json中的scripts中添加以下命令:
{
"scripts": {
"eslint": "eslint . --ext .vue,.js,.jsx,.ts,.tsx --cache",
"eslint:fix": "npm run eslint -- --fix"
},
}
此时,执行npm run eslint即是仅检查,而eslint:fix则是检查同时尽可能修复错误。
虽然nuxt3默认支持了typescript,但是用eslint还是提示Cannot find module ‘typescript’,所以需要再安装typescript依赖yarn add -D typescript
3. 配置Prettier
3.1 安装
yarn add prettier eslint-config-prettier --save-dev
3.2配置.prettierrc.js
创建 Prettier 配置文件.prettierrc.js,常用配置项:
module.exports = {
// 单行最多 80 字符
printWidth: 80,
// 一个 Tab 缩进 2 个空格
tabWidth: 2,
// 每一行结尾不需要有分号
semi: false,
// 使用单引号
singleQuote: true,
// 在对象属性中,仅在必要时才使用引号,如 "prop-foo"
quoteProps: "as-needed",
// 在 jsx 中使用双引号
jsxSingleQuote: false,
// 使用 es5 风格的尾缀逗号,即数组和对象的最后一项成员后也需要逗号
trailingComma: "es5",
// 大括号内首尾需要空格
bracketSpacing: true,
// HTML 标签(以及 JSX,Vue 模板等)的反尖括号 > 需要换行
bracketSameLine: false,
// 箭头函数仅有一个参数时也需要括号,如 (arg) => {}
// 使用 crlf 作为换行符
endOfLine: "crlf",
};
为了避免和 ESLint 冲突,我们还需要通过eslint-config-prettier禁用掉部分 ESLint 规则,修改 ESLint 配置:
// .eslintrc.js
module.exports = {
extends: [
'prettier', // 新增这一行
],
}
3.3 配置忽略文件.prettierignore
新建.prettierignore
node_modules
build
dist
output
.nuxt
.husky
.eslintrc.js
.prettierrc.js
tsconfig.json
package.json
tsconfig.ts
README.md
.local
**/*.svg
**/*.sh
/public/*
# 如果不希望 prettier 检查代码文件的话
*.ts
*.tsx
*.jsx
*.js
在package.json中的scripts中新增如下命令:
{
"scripts": {
"prettier": "prettier --check .",
"prettier:fix": "prettier --write .",
"lint": "npm run eslint && npm run prettier",
"lint:fix": "npm run eslint:fix && npm run prettier:fix"
},
}
如上,npm run prettier是仅检查,而prettier:fix才是进入修改。 同时增加了lint和lint:fix来一次性执行两个工具。
4. Vue ESlint 配置
安装
yarn add -D vue-eslint-parser @vue/eslint-config-typescript
修改.eslintrc.js
{
parser: 'vue-eslint-parser',
parserOptions: {
parser: '@typescript-eslint/parser',
ecmaVersion: 'latest',
sourceType: 'module',
},
}
5. Nuxt ESLint配置
安装
yarn add -D @nuxtjs/eslint-config @nuxtjs/eslint-config-typescript
修改.eslintrc.js
extends: [
'@nuxtjs/eslint-config-typescript'
]
安装了
@nuxtjs/eslint-config-typescript后,该插件规则要求函数名称和调用它的左括号之间有空格,为防止和 ESlint 冲突,最好关闭func-call-spacing规则,即:'func-call-spacing': 'off'
6. 配置 Husky 与 Lint Staged
配置 Husky 与 Lint Staged 让每次提交代码时都自动执行一次格式化,就能确保所有人提交上去的代码风格一致。
6.1 Husky
安装
npx husky-init && yarn
添加 Git Hooks:
npx husky add .husky/pre-commit './node_modules/.bin/lint-staged'
此时根目录下自动生成.husky目录,其内有一个pre-commit文件,文件内容为:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm test
./node_modules/.bin/lint-staged
根据自己喜好修改
npm test,这里修改为yarn lint:fix
从上述文件中可以看出,实际上要执行的就是lint-staged这个命令,而 Lint Staged 的作用即是找出添加到暂存区(git add)的文件,然后执行对应的lint,下面将它添加到项目里。
6.2 lint-staged
安装
yarn add -D lint-staged
在package.json中增加如下配置,实现对暂存区的核心代码文件,先使用 ESLint 格式化,再使用 Prettier 格式化,而对于其他文件,统一使用 Prettier 进行格式化。
{
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --cache --fix",
"prettier --write --list-different"
],
"*.{json,md,html,css,scss,sass,less,styl}": [
"prettier --write --list-different"
]
}
}
至此,当git commit -m 'first commit'时就会对代码进行统一格式化。
写在最后
能力有限,如果有不妥当处,请勿喷。
技术在不断进步,作为一名程序员(日常摸鱼)要不断的刷新自己的技术栈,如果这篇文章对你有帮助,请点赞收藏关注三连,你们的支持就是我最大的动力,感谢!