官网:Nuxt:直观的 Vue 框架 · Nuxt - Nuxt 中文 (nuxtjs.org.cn)
视频教程 Vue_SSR(服务端渲染)/Nuxt3全栈开发19分钟极速上手教程,vue-ssr服务端渲染入门教程,2023年最新Nuxt3全栈开发快速入门教程哔哩哔哩bilibili
什么是nuxt
nuxt是一个js开发框架,提供了响应式和组件,是基于vue的
nuxt使用vue作为框架的"视图引擎"
nuxt还具有服务端能力
是基于
nitro伺服器引擎,一个为达高效能与可移植性目标而构建的最小http框架
nuxt是一个兼具前端开发与后端开发的全栈开发框架
客户端渲染和服务端渲染
客户端渲染不能看到源代码,服务端可以看到源代码
优缺点
服务端利于seo,能够更快的首屏加载
spa 客户端渲染:
缺点:首屏加载所有资源,拖慢加载时间
优点:后续访问和页面切换速度快,而服务器压力小
ssr 服务端渲染:
优点:首屏加载快
缺点:后续访问的页面切换加大服务器压力,高并发时更明显
nuxt安装与使用
打开需要创建项目的目录,打开终端输入
npx nuxi@latest init <project-name>
- Node.js -
v18.0.0或更高版本 确保使用偶数版本号(18、20 等)- 文本编辑器 - 我们推荐使用 Visual Studio Code,并安装 官方 Vue 扩展(以前称为 Volar)
- 终端 - 用于运行 Nuxt 命令
PS F:\nasGit\study\nuxtjs> npx nuxi@latest init one
✔ Which package manager would you like to use?
npm
◐ Installing dependencies... 11:12:27
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'cssnano@7.0.6',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'cssnano-preset-default@7.0.6',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'cssnano-utils@5.0.0',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-calc@10.0.2',
npm WARN EBADENGINE required: { node: '^18.12 || ^20.9 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-colormin@7.0.2',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-convert-values@7.0.4',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-discard-comments@7.0.3',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-discard-duplicates@7.0.1',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-discard-empty@7.0.0',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-discard-overridden@7.0.0',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-merge-longhand@7.0.4',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-merge-rules@7.0.4',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-minify-font-values@7.0.0',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-minify-gradients@7.0.0',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-minify-params@7.0.2',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-minify-selectors@7.0.4',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-normalize-charset@7.0.0',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-normalize-display-values@7.0.0',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-normalize-positions@7.0.0',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-normalize-repeat-style@7.0.0',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-normalize-string@7.0.0',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-normalize-timing-functions@7.0.0',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-normalize-unicode@7.0.2',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-normalize-url@7.0.0',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-normalize-whitespace@7.0.0',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-ordered-values@7.0.1',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-reduce-initial@7.0.2',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-reduce-transforms@7.0.0',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'postcss-unique-selectors@7.0.3',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'stylehacks@7.0.4',
npm WARN EBADENGINE required: { node: '^18.12.0 || ^20.9.0 || >=22.0' },
npm WARN EBADENGINE current: { node: 'v18.0.0', npm: '8.19.2' }
npm WARN EBADENGINE }
npm WARN deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm WARN deprecated rimraf@3.0.2: Rimraf versions prior to v4 are no longer supported
npm WARN deprecated glob@8.1.0: Glob versions prior to v9 are no longer supported
npm WARN deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported
npm WARN deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported
npm WARN deprecated npmlog@5.0.1: This package is no longer supported.
npm WARN deprecated are-we-there-yet@2.0.0: This package is no longer supported.
npm WARN deprecated gauge@3.0.2: This package is no longer supported.
> postinstall
> nuxt prepare
ℹ Compiled plugins/server.mjs in 5967.01ms 11:15:16
ℹ Compiled plugins/client.mjs in 6080.57ms 11:15:16
ℹ Compiled types/plugins.d.ts in 6112.61ms 11:15:16
✔ Types generated in .nuxt 11:15:17
added 644 packages in 3m
128 packages are looking for funding
run `npm fund` for details
✔ Installation completed. 11:15:17
✔ Initialize git repository?
No
11:16:50
✨ Nuxt project has been created with the v3 template. Next steps:
› cd one 11:16:50
› Start development server with npm run dev
使用vscode打开项目,打开app.vue
响应式
修改代码如下,验证响应式
<script setup lang="ts">
let aa = ref(777)
</script>
<template>
<div>
<NuxtRouteAnnouncer />
<!-- <NuxtWelcome /> -->
<h1>78979</h1>
<h2>{{ aa }}</h2>
<input type="text" v-model="aa">
</div>
</template>
组件
在根目录下面创建components,这是Nuxt约定的组件位置,默认会是全局组件
创建一个test.vue文件
<script setup lang="ts">
defineProps({
msg: {
type: String,
default: 'Hello nuxt.js'
}
});
</script>
<template>
<div>测试</div>
<div>{{ msg }}</div>
</template>
<style lang="scss">
</style>
在app.vue里面使用
<test msg="7897987"></test>
如果项目没有更新,直接重启项目就可以
路由
在根目录下面创建/pages,nuxt约定的路由放置目录,创建此目录之后,系统将在底层调用vue-router进行路由
创建
/pages目录之后开启了路由,/app.vue会影响路由和页面,建议删掉或更改名称,但是app.vue也是主页入口,所以删除之后,建议创建新的主页删除之后再
/pages目录下创建index.vue文件当做新的主页
经过以上操作,主页就变成了index.vue页面
在/pages目录下创建one.vue并编写内容保存,在地址栏中添加/one路径就能看到one.vue文件中的内容,如果输入一个不存在的地址就会返回404
总结
基本上和使用vue3没有什么区别,相当于省略了全局组件的配置和导入、路由的配置、省略了ref等的导入
nuxt服务端
路由
在项目根目录创建/server,nuxt约定的服务端目录名称,用于后端开发
/server目录下可以有api、router、middleware、plugin等,教程中只说了api
api用于存放接口; 内的文件在它们的路由中会自动加上/api前缀。要添加没有/api前缀的服务器路由,请将它们放入routes目录中middleware中间件 中间件处理程序将在任何其他服务器路由之前运行,以添加或检查标头、记录请求或扩展事件的请求对象pluginsNuxt 会自动读取中的任何文件,并将它们注册为 Nitro 插件。这允许扩展 Nitro 的运行时行为并挂钩到生命周期事件。utils服务器路由由 unjs/h3 提供支持,它附带了一套方便的助手函数。目录中可以添加更多助手函数。
export default defineEventHandler((event) => {
})
api 路由 中间件均需要此函数
在api目录下创建csapi.js
export default defineEventHandler((event) => {
// 通过return 的方式进行返回数据 可以直接返回json对象
return {
status:1,
msg:"hello world"
}
})
启动项目之后访问接口地址是localhost:3000/api/csapi
localhost:3000项目启动的地址api表示请求的后台的apicsapi/server/api中创建的接口文件名
接口传参
在地址栏中添加一个参数localhost:3000/api/csapi?id=1
在文件中获取参数使用nuxt提供的getQuery()方法
总结
使用起来还算可以,项目分工明确,应该会比较好用,具体的还有在后面学习
扩展
前端页面调用接口
在上面有了前端的页面,也有了后端的接口,那么在前端界面如何调用后端的接口在教程中并没有说
参考文章Nuxt3数据请求及封装_nuxt3 请求封装-CSDN博客
Nuxt3提供了多种方法来处理应用程序中的数据获取:
- $fetch
- useFetch
- useLazyFetch
- useAsyncData
- useLazyAsyncData
Nuxt3 不推荐也没必要使用Axios进行网络请求,Axios本来是对 XMLHttpRequest 的封装,而现如今网络请求这种功能由 XMLHttpRequest 逐渐被 Fetch API 代替,浏览器已支持原生支持fetch,Node v17.5也引入了对fetch的原生支持。Nuxt3的官方团队将fetch进一步封装,封装的项目叫做ofetch,并且将其集成到Nuxt3中($fetch)
useAsyncData
根据参考文章修改
<script setup lang="ts">
let data = ref()
const getData = async () => {
const { data, pending, error, refresh } = await useAsyncData(
"mountains",
() => $fetch("http://localhost:3000/api/csapi")
);
console.log('data, pending, error, refresh',data.value, pending.value, error.value, refresh.value);
};
</script>
<template>
<div>首页</div>
<button @click="getData">请求</button>
<div></div>
</template>
<style lang="scss"></style>
data: 传入的异步函数的结果。pending: 一个布尔值,指示数据是否仍在获取中。refresh/execute: 一个函数,可用于刷新handler函数返回的数据。error: 如果数据获取失败,则为一个错误对象。status: 一个字符串,指示数据请求的状态 ("idle","pending","success","error")
data、pending、status和error是 Vue 引用,它们应该在<script setup>中使用时使用.value访问,而refresh/execute是用于重新获取数据的普通函数。
useFetch
此可组合项提供了一个围绕 useAsyncData 和 $fetch 的便捷包装器。它会根据 URL 和获取选项自动生成一个键,为基于服务器路由的请求 URL 提供类型提示,并推断 API 响应类型。
useFetch 是一个可组合项,旨在直接在 setup 函数、插件或路由中间件中调用。它返回响应式可组合项,并处理将响应添加到 Nuxt 负载中,以便在页面水合时,可以将它们从服务器传递到客户端,而无需在客户端重新获取数据。
总结
由于是初步学习, 就先简单试一下,参考文章中的封装看着挺不错,后面再具体研究
打包部署
既然我们需要使用nuxtjs做项目,那么就需要让用户使用,需要打包部署到服务器才行
执行命令
npm run build
会得到文件夹.output,将文件夹.output放到服务器中
在服务器中安装nodejs和pm2
使用pm2启动pm2 server/index.mjs文件就可以了
我在本地使用的是nodemon启动的
具体的可以参考文章 Nuxt3 项目部署在 Ubuntu 服务器(Node 服务 + pm2 + Nginx 反向代理) (jsnoteclub.com)
其他
查看nuxt官网中集成模块有很多插件可以集成,说明nuxt的社区还是挺好的