8 服务端渲染技术SSR
8.1 什么是SSR服务端渲染
广义的说,只要是在服务器端生成完整的html的方式,都可以算作服务器端渲染。只是这种说法,在前后端完全分离之前,似乎也没人提及。因为很普遍嘛。后来前后端完全分离了,完整的html是在前端生成,后端不管了。于是产生一个小问题,搜索引擎不识别!如果项目还必须支持SEO,那么怎么办?写两套代码?还是放弃前后端分离的方案?于是前后端分离的方案里面,出现了一种“后端渲染”的技术方案。你用前后端分离的方式做项目,一般情况下完整的html是由前端实现,特殊情况(比如支持SEO或者加快首页显示速度)下可以由后端实现。(摘自:https://www.zhihu.com/question/379563505/answer/1079823117)
简单理解是将组件或页面通过服务器生成html字符串,再发送到浏览器,最后将静态标记"混合"为客户端上完全交互的应用程序。
服务端渲染的特点:
在服务端生成html网页的dom元素
客户端(浏览器)只负责显示dom元素内容
客户端渲染的特点
在服务端只是给客户端响应的了数据,而不是html网页
客户端(浏览器)负责获取服务端的数据生成dom元素
两种方式各有什么优缺点
客户端渲染优缺点
缺点:不利于网站进行SEO,因为网站大量使用javascript技术,不利于搜索引擎抓取网页。
优点:客户端负责渲染,用户体验性好,服务端只提供数据不用关心用户界面的内容,有利于提高服务端的开发效率。
适用场景:对SEO没有要求的系统,比如后台管理类的系统,如电商后台管理,用户管理等。
服务端渲染优缺点
优点:有利于SEO,网站通过href的url将搜索引擎直接引到服务端,服务端提供优质的网页内容给搜索引擎。
缺点:服务端完成一部分客户端的工作,通常完成一个需求需要修改客户端和服务端的代码,开发效率低,不利于系统的稳定性。
适用场景:对SEO有要求的系统,比如:门户首页、商品详情页面等。
8.2 Nuxt.js
8.2.1 Nuxt简介
移动互联网的兴起促进了web前后端分离开发模式的发展,服务端只专注业务,前端只专注用户体验,比如流行的vue.js实现了功能强大的前端渲染。 但是,对于有SEO需求的网页如果使用前端渲染技术去开发就不利于SEO了,有没有一种即使用vue.js 的前端技术也实现服务端渲染的技术呢?
Nuxt.js 是一个基于 Vue.js 的轻量级应用框架,可以用来创建服务端渲染 (SSR) 应用,也可充当静态站点引擎生成静态站点应用,具有优雅的代码结构分层和热加载等特性。
1)用户打开浏览器,输入网址请求到Node.js中的前端View组件
2)部署在Node.js的应用Nuxt.js接收浏览器请求,并请求服务端获取数据
3)Nuxt.js获取到数据后进行服务端渲染
4)Nuxt.js将html网页响应给浏览器
8.2.2 Nuxt环境初始化
在github下载好nuxt,把nuxt里面的内容全部复制到自己的项目中,修改pakage.json和nuxt.config里面的基本配置信息。
在终端执行命令yarn install安装相关依赖(根据配置文件里面的dependence自动下载,也可以用npm管理环境,yarn更好用)
yarn install
其他依赖引入:
1.下载element-ui
npm install element-ui
2.在plugins文件夹下创建myPlugin.js文件
3.在myPlugins中引入依赖
import Vue from 'vue'
import ElementUI from 'element-ui' //element-ui的全部组件
import 'element-ui/lib/theme-chalk/index.css'//element-ui的css
Vue.use(ElementUI) //使用elementUI
import VueQriously from 'vue-qriously'
Vue.use(VueQriously)
4.在nuxt.config文件中加入自己的插件:
plugins: [
{ src: '~/plugins/myPlugin.js', ssr: false }
]
5.测试启动
yarn run dev 或者npm run dev
yarn run dev
8.2.3 项目结构
**assets:**存放静态资源css和image
layout:页面布局
pages:内容页面
8.2.4 封装axios
在vue项目中,和后台交互获取数据这块,我们通常使用的是axios库,它是基于promise的http库,可运行在浏览器端和node.js中。他有很多优秀的特性,例如拦截请求和响应、取消请求、转换json、客户端防御cSRF等。所以我们的尤大大也是果断放弃了对其官方库vue-resource的维护,直接推荐我们使用axios库。axios相关初始化配置移步https://www.cnblogs.com/chaoyuehedy/p/9931146.html(作者:小小公举)
新建文件夹utils,创建request.js文件,复制内容到request.js中
import axios from "axios";
import { MessageBox, Message } from "element-ui";
import cookie from "js-cookie";
// 创建axios实例
const service = axios.create({
// baseURL: "http://localhost",
baseURL: "http://localhost",
timeout: 15000 // 请求超时时间
});
// http request 拦截器
service.interceptors.request.use(
config => {
//判断cookie是否有token值
if (cookie.get("token")) {
//token值放到cookie里面
config.headers["token"] = cookie.get("token");
}
return config;
},
err => {
return Promise.reject(err);
}
);
// http response 拦截器
service.interceptors.response.use(
response => {
// 访问的资源需要登录
if (response.data.code === 208) {
// 弹出登录框
loginEvent.$emit("loginDialogEvent");
return;
} else {
if (response.data.code !== 200) {
Message({
message: response.data.message,
type: "error",
duration: 5 * 1000
});
return Promise.reject(response.data);
} else {
return response.data;
}
}
},
error => {
return Promise.reject(error.response);
}
);
export default service;
8.3 开始工程
8.3.1 根据后端的接口写api
- 创建api文件夹,新建js文件(对应接口),引入axios
import request from '@/utils/request'
- api中编写接口
const api_name = `/api/hosp/hospital`
export default {
// 获取分页信息
getPageList(page, limit, searchObj) {
return request({
url: `${api_name}/${page}/${limit}`,
method: 'get',
params: searchObj
})
}
//省略....
}
3.服务端渲染,在page目录下的index页面中
export default {
//服务端渲染异步,显示医院列表
asyncData({ params, error }) {
//调用
return hospApi.getPageList(1, 10, null).then(response => {
return {
list: response.data.content,
pages: response.data.totalPages
};
});
},
data() {
//省略...
}
//省略...
}
8.3.2 nuxt路由跳转(规范命名)
-
固定路由跳转:在pages里创建一个同名文件夹 文件夹里创建index.vue页面 如: /course 创建course文件夹 文件夹里创建index.vue
-
动态路由跳转:路由地址带参数 会随着参数的值变化而变化 在pages的同名文件夹里创建 _参数名称.vue。如: /course/id id值会因课程的不同而变化 则在course文件夹里创建页面 _id.vue 下划线加参数名称。
此处:
windows.location.href='/hospital/notice/booking' //为固定路由
windows.location.href='hospital/notice'+hoscode //为动态路由