服务端渲染--nuxtJS框架

3/16/2021 Vue

# 为什么要用服务器端渲染?

SEO(Search Engine Optimization),搜索引擎优化。比如谷歌、百度需要抓取你所发布的网站信息来进行自然排序,是通过爬虫进行的。

怎么实现页面爬虫?

使用superagent发送http请求,把整个页面(文档对象)爬下来,包括head, body等,然后用cheerio进行解析,然后抓取页面节点元素以及关键信息。

SPA应用的SEO为什么不好?

爬虫爬到的页面就是一个初始化的纯静态页面,spa应用body中可能就一个id为app的节点。

客户端通过ajax请求到然后插入到dom元素中的,爬虫获取不到

因此,需要让页面在服务器端就已经被渲染完成,传给客户端的时候已经是一个具有数据信息的静态html文档

  • 优点
    • 有利于SEO。 首屏加载速度快。因为SPA引用需要在首屏获取所有资源,而服务器端渲染直接拿了成品展示出来就行了。
    • 无需占用客户端资源。解析模板工作交给服务器完成,对于客户端资源占用更少,尤其是移动端,也可以更省电。
  • 缺点
    • 占用服务器资源。服务器端完成html模板解析,如果请求较多,会对服务器造成一定的访问压力。而如果是前端渲染,就是把这些压力分摊给了前端。
    • 不利于前后端分离。

# 生命周期

    • nuxtServerlnit(store, context){}, 类似于vue.js的main.js,在这个生命周期中获取token并存储。store--vuex上下文;context--nuxt上下文;【1.服务器初始化;2.只能够在store/index.js中使用;3.用于在渲染页面之前存储数据到vuex中】
    • Moddleware({store, route, redirect, params, query, req, res}){},类似于vue.js中的导航守卫,可以是全局的,路由的,组件的。可在这个生命周期中进行用户是否登录判断;
    • validate({params, query}){return: true} --校验做url参数对不对的。主要在页面中使用;
    • asyncData() 限于页面组件(pages)中使用个,components中不能使用,每次加载之前被调用。一般在这个函数中发送请求;在渲染组件之前异步获取数据
    • fetch() 可以在页面、组件中都能使用;fetch 方法的第一个参数是页面组件的上下文对象 context,我们可以用 fetch 方法来获取数据填充应用的状态树。为了让获取过程可以异步,你需要返回一个 Promise,Nuxt.js 会等这个 promise 完成后再渲染组件。
  • 服务端和客户端公用个的生命周期 (el还没有被渲染) :beforeCreate()、created()

  • 客户端的生命周期:beforeMount()、mounted()

<template> <h1>Stars: {{ $store.state.stars }}</h1> </template>
<script>
  export default {
    async fetch({ store, params }) {
      // 在fetch中调用并操作store,用store.dispatch,用async/await等待操作结束
      // await store.dispatch('GET_STARS')
      return axios.get('http://my-api/stars').then(res => {
        store.commit('setStars', res.data)
      })
    }
  }
</script>
1
2
3
4
5
6
7
8
9
10
11
12

# 运行流程

Nuxt.js 是一个基于 Vue.js 的通用应用框架。预设了服务器端渲染所需的各种配置,如异步数据,中间件,路由

nuxt提供的context对象,快速帮助服务端获取对应的数据,如app,store,router, env等,达到两个客户端数据相通的目的。

  1. nuxtServerInit服务器初始化:状态管理中actions中的nuxtServerInit函数。
  2. middleware的中间件函数,此时,还没有进行数据获取和页面渲染,所以我们可以在中间件函数中执行一些进入路由前的逻辑,比如用户权限判断。
  3. 之后开始获取页面数据,asyncData和data的结果基本相同,我们可以直接调用server的接口,比如理由axios发送http请求获取页面所需的原始数据,然后以对象的形式return出去,此时,Vue对象还没有实例化,所以asyncData里无法调用到this。
  4. fetch里主要用作填充状态树(store)数据。
  5. 这些全部做完以后,开始实例化Vue对象,这里的逻辑和单页应用是一样的,在组装好整个页面应用之后,nuxt.js会将这个应用返回至前端。注意,这里返回的不是单纯的页面,而是应用。此时的页面局部spa应用的一些性质,比如数据监听双向绑定。
  6. 页面来到前端后,开始执行mount的相关逻辑

# 目录结构

  • layouts 放页面布局。
  • middleware

放一些中间件,在页面组件中可引用这些中间件,在执行页面逻辑会先执行其中的逻辑。

全局middleware与布局middleware,布局匿名middleware,页面middleware,以及页面匿名middleware。

他们的执行顺序是:全局(config) > 布局(layout) > 页面(page)

  • pages 放页面组件,nuxt里的page会根据文件和文件夹结构生成对应的路由

  • plugins集中放置一些插件,比如axios等。

  • store是集中定义状态树。nuxt.js已经集成了vuex,这里只需要定义一个index.js,然后对外暴露一个Vuex.Store实例即可。

# 配置

layouts用于放置页面布局。 middleware用于放置一些中间件,我们在页面组件中可以引用这些中间件,在执行页面逻辑的时候会先执行其中的逻辑。 pages就是放置我们的所有页面组件啦,但是,与spa应用不同的是,nuxt里的page会根据文件和文件夹结构生成对应的路由

# validate()校验参数

在动态路由对应的页面组件中配置一个校验方法用于校验动态路由参数的有效性。

比如对路由参数验证失败,判定为一个非法参数后,跳转到404页面或者一个提醒页面。

# asyncData()和fetch()

head部分可以自定义当前页面的头部信息,比如title, meta之类的。当然,如果需要定义全局head可以在nuxt.config.js中配置。

scrollToTop用于页面跳转时将页面滚动置顶。

transition用于页面间跳转的过渡动画。