同构渲染--Nuxt

1,098 阅读5分钟

什么是渲染?

我们通常所说的就是把数据HTML模版拼接在一起,然后呈现给用户就叫做渲染。

渲染通过页面渲染的终端被分为两类。即客户端渲染服务端渲染

什么是服务端渲染呢?

就是数据和HTML模版结合是在服务端完成的。如下图所示,是传统的服务端渲染流程: image.png 传统的服务端渲染有很多问题。比如:

1.前后端代码混在一起,难以维护。
2.服务端压力大,所有的事情都是在服务端完成的。
3.体验也不够好,在网速缓慢的情况下,切换页面的响应速度很慢。

随着ajax技术的发展,使得客户端有能力获取数据,所以就有了客户端渲染的诞生。

什么是客户端渲染呢?

通过ajax技术把页面所需的数据拿到客户端,然后在客户端把数据HTML组合在一起完成视图渲染。如下图所示:

image.png

虽然客户端渲染实现了前后端代码分离,但是他也有自己的缺点:

1.不利于SEO。SEO说白了就是搜索引擎对网站的收录情况。因为客户端渲染的时候返回是一个空白的HTML文件和一堆数据,搜索引擎在抓去网站的时候,网站还没有把HTML和数据组装在一起,所以一个空白的HTML没有任何的参考价值,所以不利于SEO。

2.首屏渲染速度缓慢。对于客户端渲染应用来说,首次请求数据量很大,而且会出现串行数据链的请求,这一套流程走下来就会非常缓慢。服务端渲染则不会,他只会拿一个完整的HTML文件回来,所以他比服务端首屏渲染速度要慢。

那有没有一种方法同时集成客户端和服务端渲染的优点呢?

答案是有的。那就是同构渲染。什么是同构渲染呢?

基于react,vue等框架,服务端渲染和客户端渲染相结合。在服务端执行一次,用于首屏直出,然后由客户端渲染接管页面,用户的操作都走客户端渲染。这样既满足了seo和首屏直出的需求,又满足了先后端分离

image.png

vue和react官方提供的同构渲染解决方案比较麻烦,需要搭建环境。但是有利于理解远原理,对于业务来讲,建议使用第三方的解决方案Next和Nuxt.

当然同构渲染也是有一些缺点的:

1.浏览器特定的代码只能在某些生命周期钩子函数中使用。
2.一些外部的库可能要经过特殊的处理才能在服务端渲染中使用。
3.不能在服务端渲染期间操作DOM。 4.某些代码需要区分运行环境。

对于同构渲染而言,构建和部署都有要求,如下图 image.png

接下来我们就来学习一下Nuxt。Nuxt是一个基于vue生态的第三方开源的服务端渲染框架。我们可以轻松的使用vue的技术栈来构建我们的服务端渲染应用。

官方链接地址 www.nuxtjs.cn/guide

nuxt天生集成了vue-router,vuex,所以达到了开箱即用的程度。关于Nuxt的用法与vue高度相似,这里我们只做部分的解释;

1.nuxt的项目结构是固定的。pages文件夹下存放的就是对应的路由文件,比如about/index.vue,最终得到的路由就是localhost:xxx/about。动态路由则是_pid.vue或者 _pid/index.vue,得到的路由就是 localhost:xxx/:pid。

2.asyncData。该方法是用在服务端渲染获取数据的。比如首屏指出的数据,需要请求后台服务拿数据,那这个获取数据的方法就可以写在asyncData里,他是个异步方法,最终他会跟vue的data数据合并在一起。

3.components目录。公共组局的目录。这些组件没有asyncData方法,他们可以通过props传值获取数据。

4.layouts目录。页面的公共部分。比如header和footer这种。如图所示,如果添加了default.vue,则每个路由页面都会自动添加这个组件。别忘了组件里有一个 标签,类似于路由视口。也可以自定义布局组件,例如layouts/hot.vue。那在需要者莪组件的路由页面加上,

image.png

<template>
  <!-- Your template -->
</template>
<script>
  export default {
    layout: 'hot'
    // page component definitions
  }
</script>

5.plugins目录。插件允许我们使用第三方的模块。比如我们在首屏渲染时,是服务端渲染,这时候是没办法通想vue那用通过模块的引入来拿到state里的值的。但是在插件里我们就能获取到这些数据


import axios from 'axios'

export const request = axios.create({
    baseURL: 'https://api.realworld.io',
});

request.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    return response.data;
  }, function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
  })
// 插件导出一个方法,方法里能获取到vuex里的数据,允许我们做拦截器,这里为什么不可以从cookie里拿,因为是在服务端,cookie里拿不到用户信息
export default ({ store }) => {
    // // 添加请求拦截器
    request.interceptors.request.use(function (config) {
        // 在发送请求之前做些什么
        if ((config.data && config.data.isToken)) {
            const token = store.state.user.user && store.state.user.user.token;
            if (token)  config.headers.authorization = `Token ${token}`;
            delete config.data.isToken;
        }
        return config;
    }, function (error) {
        // 对请求错误做些什么
        return Promise.reject(error);
    });
}

6.nuxtSwevweInit。看方法名字就知道服务端渲染初始化函数,他是在vuex的action中被调用的,只执行一次。我们可以想到,当我们请求网址时,我们客户端的cookie被请求发送到了后端,所以后端在执行这个函数的时候是可以拿到请求体上的cookie数据的,这时候就可以把信息给组装到vuex中。

image.png

其他的基本官网都说的明白,后面再补坑!!!