一、引言
Nuxt.js 是一个基于 Vue.js 的通用应用框架,一个用于Vue.js 开发SSR应用的一站式解决方案。它的优点是将原来几个配置文件要完成的内容,都整合在了一个nuxt.config.js,封装与扩展性完美的契合。
在接触nuxt.js之前,首先需要明白两个概念:Vue开发的客户端单页面应用程序(SPA)、服务端渲染框架(SSR)
传统的SPA应用是将bundle.js 从服务端获取,然后再客户端解析并挂载到dom身上。
-
优点:
-
缺点:
- 首屏加载缓慢
- 很明显,不利于SEO(搜索引擎优化),因为爬虫无法爬取到具体的html页面(因为SPA采用的大多是单页面组件,这些都不是html代码形式)
-
优化:
- 组件 / 路由的懒加载、异步组件
- 对打包后的资源进行压缩,减轻入口压力
- 对打包后的资源进行压缩
- 采用更高层的SSR服务端渲染
-
SSR:服务端渲染 可以将其理解为:在node服务器中来运行Vue程序,然后在服务器中处理好页面渲染的问题,最后直接将页面html的展示传递给客户端,客户端仅仅只需要进行渲染即可;这样大大的减少了加载的时间,提高了加载的效率 即:网页是通过服务端渲染生成后输出给客户端 在SSR中,前端分成两部分:前端客户端、前端服务端
现在理解一下Nuxt.js 完整的SSR流程
- Nuxt将代码项目程序封装为
- Webpack将这两个包进行打包为
- Server bundle.js —— 提供给node服务器使用,在node服务器中负责进行数据处理,然后得到渲染后的页面(不能绑定js事件,只能是html+css)
- Client bundle.js —— 接收服务器的纯静态html代码,然后进行
Hydrate 混入。此时客户端的virtual-dom 进行预渲染,和服务端返回的静态页面惊醒比对,比对两边渲染的内容是否为一致的。如果不一致将会报错Hydrate..... ;如果一致则会对DOM元素的事件进行绑定处理
二、测试服务端渲染
2.1 搭建项目
创建:
npm init nuxt-app <project-name>
然后一步一步选择配置即可
运行:
npm run dev
访问:
http://localhost:3000
项目结构:
目录名称 | 描述 |
---|
assets | 资源目录,用于存放需要编译的静态资源(打包后的资源),引用assets资源时可以使用~或@简写形式,比如<img src=“~assets/13.jpg”/> | components | vue组件目录,Nuxt.js 不会增强该目录,即不支持SSR | layouts | 布局组件目录 | pages | 页面目录,所有的vue视图,nuxt根据目录结构自动生成对应的路由。 | plugins | 插件目录 | static | 静态文件目录,不需要编译的文件,引用static资源时可以使用 / 简写形式,比如<img src=“/12.jpg”/> | server | 服务端代码编写在这个文件夹内 | store | vuex目录 | nuxt.config.js | nuxt个性化配置文件,内容将覆盖默认 | package.json | 项目配置文件 |
2.2 编写服务端接口
在这里我采用express 来编写一个接口,这个接口目的是返回所有的学生数据。
接口结构:
|server/
|--| students/
|-----| student_info.js
|--| index.js
student_info.js文件代码:
const express = require('express')
const router = express.Router()
router.get('/info', (req, res)=>{
return res.status(200).json([
{
id: '1902',
name: 'neko_z'
},
{
id: '1903',
name: 'neko_k'
},
{
id: '1904',
name: 'neko_m'
}
])
})
module.exports = router
向index.js文件中挂载student相关的api接口:
const express = require('express')
const consola = require('consola')
const { Nuxt, Builder } = require('nuxt')
const student = require('./students/student_info')
const app = express()
app.use('/api/student',student)
现在我们在电脑上面访问一下http://localhost:3000/api/student/info 试试,可以发现数据成功的渲染在了页面上:
2.3 编写客户端页面
2.3.1 SPA渲染
// students展示界面
<template>
<div>
<div
v-for="item in infoList"
:key="item.id"
>
<li>{{item.id}}</li>
<span>{{item.name}}</span>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
// If you don't add a layout property to your page,
// e.g. layout: 'blog', then the default.vue layout will be used.
// 在这里需要添加一个 layout 属性表明需要展示的是什么页面,否则会展示默认页面
layout: 'student',
data() {
return {
infoList: []
}
},
created() {
this.getStudentsList()
},
methods:{
getStudentsList(){
axios.get('http://localhost:3000/api/student/info').then(res=>{
this.infoList = res.data
})
}
}
}
</script>
此时我们已经成功的将数据渲染到了页面上,但是,打开页面源代码来看看:页面源代码中并未出现页面上的数据
这是因为单页面应用是从服务端取得数据进行渲染,html文件中并未接触这些数据,这个例子也很好的说明了为何SPA应用难以进行SEO,这是因为爬虫无法爬到页面中的关键数据
2.3.2 SSR渲染
<template>
<div>
<div
v-for="item in infoList"
:key="item.id"
>
<li>{{item.id}}</li>
<span>{{item.name}}</span>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
layout: 'student',
data() {
return {
infoList: []
}
},
async asyncData() {
let list = await axios.get('http://localhost:3000/api/student/info')
return {
infoList: list.data
}
}
}
</script>
现在再来看看网页源代码,会发现后台数据渲染到了页面上:
参考文章
Nuxt详解 + 案例
|