Nuxt服务器端渲染框架
标题Nuxt基本介绍
基于 Vue、Webpack 和 Babel Nuxt.js 集成了以下组件/框架,用于开发完整而强大的 Web 应用:
- Vue 2 / Vue3
- Vue-Router
- Vuex
- Vue 服务器端渲染
- Vue-Meta
注意:
- Nuxt不是Vue官方提供的
- Nuxt是基于Vue的服务端渲染的框架
- Nuxt.js 预设了利用 Vue.js 开发服务端渲染的应用所需要的各种配置。
next.js : react 服务器渲染框架
nuxt.js : vue 服务器渲染框架
使用脚手架工具创建项目
第一步:全局安装脚手架工具
npm i -g create-nuxt-app
----------------------------------
C:\Users\fanyoufu\AppData\Roaming\npm\create-nuxt-app -> C:\Users\fanyoufu\AppData\Roaming\npm\node_modules\create-nuxt-app\lib\cli.js
> ejs@2.7.4 postinstall C:\Users\fanyoufu\AppData\Roaming\npm\node_modules\create-nuxt-app\node_modules\ejs
> node ./postinstall.js
Thank you for installing EJS: built with the Jake JavaScript build tool (https://jakejs.com/)
npm WARN notsup Unsupported engine for create-nuxt-app@3.1.0: wanted: {"node":">=10.20.0"} (current: {"node":"10.16.3","npm":"6.13.4"})
npm WARN notsup Not compatible with your version of node/npm: create-nuxt-app@3.1.0
+ create-nuxt-app@3.1.0
added 38 packages from 4 contributors, removed 3 packages and updated 162 packages in 61.806s
第二步:创建项目
# 格式: create-nuxt-app 项目名
create-nuxt-app nuxt-demo
本示例中的采用的方案
如果你选择了某个ui框架,则在创建项目时,就会自动给你配置好。
第三步:安装完成
第四步:启动项目
- 进入目录。脚手架在创建项目时,会给我们创建一个文件夹。
- 运行命令。
运行启动命令npm run dev
启动成功:
在浏览器查看效果:
目录结构
|--components:组件
|--layouts:布局
|--middleware: 中间件
|--plugins:插件
|--static:静态资源
|--store: vuex
|--nuxt.config.js
最重要的就是pages!
运行项目
npm run dev
如果没有什么错误,你应该可以在localhost:3000中看到代码运行的效果了。
- 此时访问的是pages下的index.vue的内容。
创建第二个页面
在pages文件夹,新建一个普通的page1.vue文件。
/pages/page1.vue
<template>
<div>
<h1>page1</h1>
<p>{{title}}</p>
<nuxt-link to="/">首页</nuxt-link>
</div>
</template>
<script>
export default {
data() {
return {
title:"剑客"
}
}
}
</script>
注意:
- nuxt-link 用来进行页面跳转。
- 在地址栏中输入http://localhost:3000/page1来访问这个页面
小结
- 项目中只有一个包nuxt,而其它的vue,vue-router,webpack等都集成了。
- 页面全写在pages目录下(layout下面的default.vue 是默认的模板)。
- 不需要额外去设计路由。
- 是单页的:路由跳转,页面是不会刷新
认识单页应用和服务端渲染
服务端渲染
上面的例子中,http://localhost:3000/page1 得到的内容是
也就是说,从服务器取回来的是包含数据的网页。
单页应用
在从地址:http://localhost:3000/page1 转到 http://localhost:3000/ 时,页面并不刷新。
这就是典型的单页应用特点。
服务器渲染的能力
在我们前面学习的vue项目中,都是在客户端渲染:
- 先把页面(不带数据的)取回来
- 再发ajax去求接口,获取数据,在浏览器端渲染数据
服务器端渲染是:
- 请求页面
- 服务器收到这个接求,去请求数据,生成页面(带数据的)
- 返回给客户端(有数据的)
讨论发ajax取数据的过程。
回顾客户端渲染的情况
由于在创建项目时,已经选择了axios,所以,在vue的实例中,可以直接通过this.$axios来使用axios.
- 在page1.vue中改写代码如下。
就是一个最简单的ajax请求,并用v-for渲染数据的例子。
<template>
<div>
<h3>{{ title }}</h3>
<div>
<p v-for="item in books" :key="item.id">
{{ item.bookname }}
</p>
</div>
<!-- 在页面之间跳转 -->
<nuxt-link to="/">
主页
</nuxt-link>
</div>
</template>
<script>
export default {
name: 'MyComponent',
components: { },
props: { },
data () {
return {
title: '剑客',
books: [],
list: [
'html', 'css', 'js'
]
}
},
created () {
this.loadData()
},
methods: {
async loadData () {
const result = await this.$axios({
method: 'GET',
url: 'http://www.liulongbin.top:3006/api/getbooks '
})
// eslint-disable-next-line no-console
console.log(result)
this.books = result.data.data
}
}
}
</script>
- 运行代码。并在浏览器中观察数据的请求来源。
created中的代码是会在浏览器发出ajax请求的。
其它测试用的接口也可以使用的。
https://github.com/typicode/jsonplaceholder
这里还是一个典型客户端渲染的效果。
服务器端渲染asyncData
特点
- asyncData是Nuxt中额外增加的 vue 生命周期的钩子函数。在这个钩子函数中,代码可以在服务端执行。
- 没有 Vue 实例的 this,this 指向 undefined
- 发请求,以获取数据。数据要求以对象格式返回,并最终会附加到vue组件的data数据项中,可以正常在template中使用。
<template>
<div>
<h3>{{ title }}</h3>
<div>
<p v-for="item in serList" :key="item">
{{ item }}
</p>
</div>
<div>
<p v-for="item in books" :key="item.id">
{{ item.bookname }}
</p>
</div>
<!-- 在页面之间跳转 -->
<nuxt-link to="/">
主页
</nuxt-link>
</div>
</template>
<script>
export default {
name: 'MyComponent',
components: { },
props: { },
asyncData () {
// eslint-disable-next-line no-console
console.log('asyncData 是在服务器端执行的')
return {
serList: ['服务器端数1', '服务器端数2']
}
},
data () {
return {
title: '剑客',
books: [],
list: [
'html', 'css', 'js'
]
}
}
}
</script>
上例是获取同步数据。
获取接口数据
目标:
在asyncData钩子函数中,去发ajax请求,获取数据。
<template>
<div>
<h3>{{ title }}</h3>
<div>
<p v-for="item in newBooks" :key="item.id">
{{ item.bookname }}
</p>
</div>
<!-- 在页面之间跳转 -->
<nuxt-link to="/">
主页
</nuxt-link>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'MyComponent',
components: { },
props: { },
async asyncData () {
// 在asyncData中发ajax请求
const result = await axios({
method: 'GET',
url: 'http://www.liulongbin.top:3006/api/getbooks '
})
// eslint-disable-next-line no-console
// 获取到的数据,通过return {} 的格式 把数据附加在当前Vue实例中的data上。
return {
newBooks: result.data.data
}
},
data () {
return {
title: '剑客',
books: [],
list: [
'html', 'css', 'js'
]
}
}
}
</script>
<style scoped lang='less'></style>
- asyncData 它是一个特殊的钩子函数,它可以在服务器端运行。
- 上面的代码中,产生出页面就已经有数据了,不像在created中的代码是会在浏览器发出ajax请求的。
工作过程:
同构
在asyncData()中的写的代码会在服务器端执行,也会在客户端执行(路由切换)。
假设在pages/index.vue这个页面中使用asyncData钩子函数,在这个函数中去请求接口,获取数据,并交给vue来渲染。
- 用户第一次请求这个http://localhost:3000/index页面,asyncData()中的代码会在服务器端执行,获取完成数据后,渲染好html再返回。
- 用户在页面上进行路由跳转:
- 从http://localhost:3000/index跳到http://localhost:3000/otherpage。
- 再从http://localhost:3000/otherpage回到http://localhost:3000/index页,此时
- asyncData()中的代码会在客户端执行。
生命周期
在服务器端执行
按如下顺序执行这三个钩子
- asyncData
- beforeCreate
- created
在客户器端执行
vue的中的钩子函数正常执行。
- asyncData 也会执行:只在路由切换时
- beforeCreate
- created
- beforeMount
- mounted
- beforeUpdate
- updated
- …
重点:
- asyncData在不同的时机,可以在服务器和浏览器都执行。
发请求取数据的操作:
- 如果 需要SEO,写在asyncData中
- 如果不需要SEO,则可以写到mounted中,
- 不要写在created中,因为它会在服务器端和客户端渲染时都执行,如果这里写调用接口取数据,则会请求两次。
Nuxt与vuecli做一个对比
我们学习的vue知识,可以直接在这两个脚手架创建的项目中使用。
区别:
- nuxt 创建项目,是看重了它的服务器端渲染的功能。同时,要付出代价:布置上线需要服务器端的支持。
vuecli 打包之后得到的是一个dist 目录,就是index.html,.js,css… 。是可以双击打开的(不包含服务器代码,与服务器没有任何的关系,它就是发ajax,获取数据,并显示)。
nuxt项目打包之后会得到客户端与服务器端的代码,在上线时,需要把服务器代码也上线。
spa-vue-cli: 客户端渲染, 缺点:首屏比较慢(路由懒加载,… 图片…,打包优化), 对SEO不友好。
- 打包进入原生的app,h5应用
- 预渲染:prerender-spa-plugin 把一些页面提前生成对应的.html
ssr-nuxt.js: 服务器端渲染, 缺点:复杂,成本高。