服务端渲染(回答vue为啥子不支持seo优化,如何解决)

整体目标:

  • 理解服务端渲染的概念
  • 会用vue的SSR
  • Nuxt中的async

一、基本概念

页面的两种生成方式

用户从浏览器地址栏中输入地址访问服务器上的页面时,服务器可以用两种不同的策略来生成这个页面,对应着程序员写的不同的实现方式。

打开给出的示意代码,观察效果。

(1)服务器端渲染Server Side Render

  • 渲染是指:从数据到dom的过程(从json到html结构)

  • 数据到dom的过程是发生在服务器端

  • 客户端浏览器在地址栏中输入网页的地址,取回来的就是html页面。

  • 理解:浏览器发送请求到服务器,服务器端获取数据库数据,进而编译成html,返回给浏览器,这一过程叫服务器段渲染
    在这里插入图片描述
    在这里插入图片描述

(2)客户器端渲染 Client Side Render

  • 渲染是指:数据到dom的过程 (从json到html结构)

  • 数据到dom的过程是发生在客户端浏览器

  • 客户端浏览器在地址栏中输入网页的地址,取回来的只是html骨架,

  • 再去发ajax请求,取回来数据,再显示到页面上(用vue,arttemplate,模板字符串等技术)
    在这里插入图片描述
    在这里插入图片描述

小结

  • ssr:服务器端渲染。数据组装(从json—>dom结果)的过程是发生在服务器上的。客户端取回来的是有数据页面。
  • csr:客户端渲染。数据组装(从json—>dom结果)的过程是发生客户端(浏览器)的。主要是通过ajax取数据,再用模板技术(arttemplate,vue…)来渲染。

SEO与爬虫

客户端渲染技术对SEO不友好,爬虫无法获取有效内容!

什么是SEO

Search Engine Optimization ,搜索引擎优化。

加入我们有个学习JavaScript网页,希望被更多人的知道,而推广自已的网页的方式之一是借助搜索引擎的力量,让其它人在百度中搜索某个关键字时就能找到你的网页。

那么,百度是如何得知http://xxxx.com/abc·········这个页面中有关键字javascript的呢?

百度服务器会使用一些程序来获取网页的内容,分析内容,以提取出关键字,便 于在搜索时能找到网页。 这个过程一般称为爬虫。
在这里插入图片描述

SEO的目标是更明确地告诉百度,你的网页上的内容,以便更好地被收录。

爬虫

我们平常上网都是在浏览器中请求网页地址,而爬虫代码是通过代码的方式去请求网页地址。

下面就是一个简陋的爬虫:

步骤:

  1. 创建一个.js文件(假设名字是spider.js)内容如下:
// 引入http模块
const http = require("http")

// 定义要爬虫程序 访问的 网页
let url = "http://localhost:8080/index_csr.html"

// let url = "http://localhost:8080/index_ssr.html"

// 用http模块中的get方法去请求 url 这个网页,把请求到的结果显示出来。
http.get(url, (res) => {
  let result = ""
  res.setEncoding('utf8');
  res.on('data', (chunk) => {
	  result += chunk
  });
  res.on('end', () => {
    console.log(`爬虫得到的数据是: ${result}`);
  });
});
  1. 运行js文件

    node spider.js
    

    这一段代码会去请求代码中url指定的网页(可在这里下载运行示例代码),并打印出结果。

  2. 小结

    对于采用客户端渲染的网页:爬虫程序无法获取有效的数据。(因为有效的数据是通过ajax在客户端发出来,去取回来的) 所以客户端渲染对seo不友好,这就是为什么vue单页面应用不利于seo优化的原因

    对于采用服务器端渲染的网页:爬虫程序可以获取有效的数据。(因为获取的内容就已经包含数据)
    在这里插入图片描述

客户端渲染与服务器端渲染的区别

在网页开发的初期 (2000-2010年),没有前后端的概念的,也没有前端工程师的概念。所有的网页上的内容:html,css,js,数据 , 包括提供数据的服务器代码 全是程序员写的。

我们的技术全是属于SSR范筹。 (php,asp,asp.net, jsp…)

优点缺点
客户器渲染(通过ajax求数据)适合前后端分离开发,方便维护,单页应用(Singe Page Application)中几乎都是客户端渲染首屏加载慢,不利于 SEO
服务器渲染响应速度快,有利于 SEO前后端代码混合在一起,难以开发和维护,不适合进行前后端分离开发

我们使用vue开发的项目都是典型的SPA(单页面应用程序single page application),是标准的前后端分离的,很显然是属于客户端渲染的范畴。

  • 好处:页面导航不用刷新整个页面,体验好,有利于前后端分离开发
  • 缺点:不利于 SEO(因为单页面应用中都是使用客户端渲染的方式),还有首次响应慢(第1次要加载大量的公共资源)

是否有相对折中的解决方案,或者是两全其美的解决方案呢?
即vue做的项目也可以达到seo优化等实现服务器端渲染的优点的实现

二、Vue的SSR介绍及示例演示

Vue的SSR文档

Vue.js 是构建客户端应用程序的框架。默认情况下,可以在浏览器中输出 Vue 组件,进行生成 DOM 和操作 DOM。然而,也可以将同一个组件渲染为**服务器端的 HTML 字符串**,将它们直接发送到浏览器,最后将这些静态标记"激活"为客户端上完全可交互的应用程序。

  • 学习vue-server-renderer
  • 在服务器端使用-server-renderer

创建项目( nodejs)

创建一个名为vue-ssr的空目录进入,并运行:

npm init --yes

来做初始化。

安装依赖

参考

npm install vue vue-server-renderer --save

示例:在node代码使用vue渲染数据

新建文件为01.js,内容如下:

const Vue = require('vue')
// 第 1 步:创建一个 vue实例
const app = new Vue({
  template: `<div>{{title}}</div>`,
  data:{
	  title:"hello,vue ssr!"
  }
})

// 第 2 步:创建一个 renderer
const renderer = require('vue-server-renderer').createRenderer()

// 第 3 步:将 Vue 实例渲染为 HTML
// 方法一:回调函数
renderer.renderToString(app, (err, html) => {
  if (err) throw err
  console.log(html)
  // => <div data-server-rendered="true">Hello World</div>
})

运行结果:

node 01.js

输出结果如下:

<div data-server-rendered="true">hello,vue ssr!</div>
<div data-server-rendered="true">hello,vue ssr!</div>

小结:

  • vue-server-renderer就可以把Vue实例解析成 它对应的dom结构

示例:与服务器功能集成

在这里插入图片描述

目标:

请求网页http://localhost:3000/index.html,在服务器端使用vue-server-renderer来渲染生成html文档,并返回。

涉及npm包:

  • express(安装express) npm i express
  • vue, vue-server-renderer

创建02.js,代码如下:

/**
 * 目标: 用户输入http://localhost:3000/index.html
 * 在服务器使用vue-server-renderer来把vue实例渲染生成html文档,并返回
 *
 * 1) 先安装express
 */

const express = require('express')

const app = express()
const Vue = require('vue')
app.get('/index.html',(req, res) => {
  // 1. 创建vue实例
  const vm = new Vue({
    template: `
      <div>
        <h2>{{title}}</h2>
        <div v-for="item in list">
          {{item.author}} - {{item.content}}
        </div>
      </div>
    ` ,
    data: {
      title: 'vue ssr',
      list: [{author:"李白",content:"举杯邀明月"},
        {author:"杜甫",content:"喝酒不开车"},
        {author:"杜甫",content:"喝酒不开车"}]
    }
  })
  // res.send('ok')
  // 2. 创建一个renderer
  const renderer = require('vue-server-renderer').createRenderer()

  // 3. 渲染:把vue实例渲染成HTML字符串
  renderer.renderToString(vm, (err, html) => {
    if (err) {
      console.log(err)
    } else {
      res.send(html)
    }
  })
})
app.listen(3000, ()=>{
  console.log('3000.....')
})

运行

node 02.js

访问:

http://localhost:3000/index.html
在这里插入图片描述

  • 小结:

    在服务器使用vue,通过vue-server-render包,来把vue实例转成html字符串,再返回给客户端,这就是用vue技术的ssr。

三、Nuxt服务器端渲染框架

Nuxt官网基本介绍

如果我们实际项目中需要使用vue做服务器端渲染那么我们可以使用Nuxt服务器端渲染框架完成服务器端适配
在这里插入图片描述

基于 Vue、Webpack 和 Babel Nuxt.js 集成了以下组件/框架,用于开发完整而强大的 Web 应用:

注意:

  1. Nuxt**不是Vue官方**提供的
  2. Nuxt是**基于Vue**的服务端渲染的框架
  3. 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下面的.vue文件,nuxt会自动去给它创建路由

/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钩子函数中处理请求

在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',
  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的执行时机

在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中,因为它会在服务器端和客户端渲染时都执行,如果这里写调用接口取数据,则会请求两次。

那么为什么我们还需要vuecli框架呢?直接使用nuxt框架不好么?

Nuxt与vuecli两个框架的对比

我们学习的vue知识,可以直接在这两个脚手架创建的项目中使用。

区别:

  • nuxt 创建项目,是看重了它的服务器端渲染的功能。同时,要付出代价:布置上线需要服务器端的支持。

vuecli 打包之后得到的是一个dist 目录,就是index.html,.js,css… 。是可以双击打开的(不包含服务器代码,与服务器没有任何的关系,它就是发ajax,获取数据,并显示)。

nuxt项目打包之后会得到客户端与服务器端的代码,在上线时,需要把服务器代码也上线。
在这里插入图片描述
spa-vue-cli: 客户端渲染, 缺点:首屏比较慢(路由懒加载,… 图片…,打包优化), 对SEO不友好。

  • 打包进入原生的app,h5应用,本身不需要seo
  • 预渲染插件做seo优化:prerender-spa-plugin 把一些页面提前生成对应的.html(也不是必须要nuxt框架)
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值