介绍

什么是 SEO

SEO(Search Engine Optimization)搜索引擎优化,是指通过对网站进行站内优化和修复(网站Web结构调整、网站内容建设、网站代码优化和编码等)和站外优化,从而提高网站的关键词排名以及公司产品的曝光度。

搜索引擎的原理

搜索引擎,又称爬虫或者蜘蛛,它在爬取和分析页面内容时,主要进行如下操作:

  1. 从 meta 标签中读取 keywords、description 的内容
  2. 根据语义化的html标签爬取和分析内容(h1-h6、strong、em等标签具有不同程度的强调意义;与整篇都是div构成的网页,SEO结果就相差甚远了)
  3. 读取a标签里的链接,通过a标签的链接再跳转到别的网站(深度优先:先跳转回头再爬取;广度优先:先爬取然后再依次跳转)

SEO 为啥对单页面应用不友好

  1. 爬虫在爬取过程中,不会去执行js,因此所有隐藏在js中的跳转或者数据都获取不到(vue通过js控制路由,然后渲染出对应页面,而搜索引擎是不会去执行页面的js的,导致搜索引擎只能收录index.html,而无法搜到其相关的子页面的内容)
  2. 浏览器加载页面时,首先会对页面进行渲染(包括 html的解析、dom树的构建、css的构建、javascript解析、布局、绘制),当解析到javascript的时候,才会去触发vue的渲染,将元素挂载到id为app的div上,这时候我们才能看到页面的内容。因此被搜索引擎收录的index页面,可能也毫无价值(因为没有任何数据)

导致的问题

  1. 单页面应用无法被SEO,会导致被搜索引擎收录的页面减少,从而导致点击量减少,影响产品曝光度
  2. 不能对不同页面设置不同的TDK(title, keywords, description),每个页面的title和meta标签都是一样的,不利于网络爬虫的爬取

解决方案

由于爬虫不会去执行js,因此如果需要对单页面应用做SEO,就需要预渲染。vue提供了两种方案解决该问题

  1. 使用 Nuxt.js 实现服务端预渲染(SSR) https://cn.vuejs.org/v2/guide/ssr.html
  2. 使用 prerender-spa-plugin插件实现 https://www.npmjs.com/package/prerender-spa-plugin

prerender-spa-plugin 较简单,但打包需要的时间长,适用于少量页面;而SSR虽然复杂,但更适用于大型应用的SEO

方案一:prerender-spa-plugin

这里用的是 vue-cli 4.5 + Vue2

使用 vue ui 进入图形界面,搜索并安装插件 vue-cli-plugin-prerender-spa

插件的作用

  1. 安装 prerender-spa-plugin,并记录到 package.json 的 devDependencies
  2. 修改 src/main.js 添加 mounted: () => document.dispatchEvent(new Event("x-app-rendered"))
  3. 自动配置 vue.config.js

在这里插入图片描述package.json
在这里插入图片描述

src/main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App),
  mounted: () => document.dispatchEvent(new Event("x-app-rendered")),
}).$mount('#app')

vue.config.js

module.exports = {
  lintOnSave: false,

  pluginOptions: {
    prerenderSpa: {
      registry: undefined,
      renderRoutes: [ // 需要预渲染的路由地址
        '/','/about'
      ],
      useRenderEvent: true, // 在 mounted 时,传递渲染事件通知 prerender
      headless: true, // 无界面浏览器
      onlyProduction: true // 仅在生产模式才进行spa处理
    }
  }
}

至于 src/router/index.js 不用做任何改动,也不用把 mode 设置为 history

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]

const router = new VueRouter({
  routes
})

export default router

编译报错 Chromium revision is not downloaded

仅仅做了上述配置后,执行 npm run build 还是会报错 Chromium revision is not downloaded,这是因为 prerender-spa-plugin 这个插件依赖于爬虫来抽取页面,而 puppeteer 正是这个用来实现爬虫的无界浏览器
在这里插入图片描述Puppeteer 是一个控制 headless Chrome 的 Node.js API 。它是一个 Node.js 库,通过 DevTools 协议提供了一个高级的 API 来控制 headless Chrome。它还可以配置为使用完整的(非 headless)Chrome。

在浏览器中手动完成的大多数事情都可以通过使用 Puppeteer 完成,下面是一些入门的例子:

  • 生成屏幕截图和 PDF 页面
  • 检索 SPA 并生成预渲染内容(即“SSR”)
  • 从网站上爬取内容
  • 自动提交表单,UI测试,键盘输入等
  • 创建一个最新的自动测试环境。使用最新的 JavaScript 和浏览器功能,在最新版本的 Chrome 中直接运行测试
  • 捕获网站的时间线跟踪,以帮助诊断性能问题

要安装该插件,一定要使用 cnpm 命令,从国内镜像地址下载 chrome 内核(npm从外国的地址是无法正常下载的,这会导致后面也无法正常 build )

解决办法有三种:
1.使用Chromium 国内源

npm config set puppeteer_download_host=https://npm.taobao.org/mirrors
npm i -g puppeteer

2.使用淘宝的cnpm 安装

npm install -g cnpm --registry=https://registry.npm.taobao.org
cnpm i -g puppeteer
  1. 手动下载Chromium文件,解压后放在本地
    https://npm.taobao.org/mirrors/chromium-browser-snapshots/
    放在模块的默认读取目录下
  • node_modules\puppeteer\.local-chromium\win64-848005(系统类型-版本号)\chrome-win32(下载的文件名)\
  • node_modules\puppeteer\.local-chromium\linux-848005(系统类型-版本号)\chrome-linux(下载的文件名)\
    在这里插入图片描述在这里插入图片描述

在这里插入图片描述

如果安装后依旧报上述错误,试试 cnpm uninstall puppeteer 命令。虽然字面意思上是卸载,但实际测试发现还是重装
在这里插入图片描述

在这里插入图描述

最后执行 npm run build,就会发现每个路由都在 dist 文件夹被编译成一个单独的 html 文件,这样就可以正常SEO了
在这里插入图片描述
在这里插入图片描述

vue-meta-info

使用该组件可以解决之前说的 —— SEO 的 TDK问题(不同页面设置不同的 title, keywords, description)或为某些页面设置允许缩放,而其他页面不允许等操作。

首先引入 vue-meta-info 依赖,npm install -D vue-meta-info,该插件的官方地址为 https://www.npmjs.com/package/vue-meta-info
在这里插入图片描述
之后在 src/main.js 中全局绑定

import MetaInfo from 'vue-meta-info'
 
Vue.use(MetaInfo)

最后在组件内使用即可

<template>
  ...
</template>
 
<script>
  export default {
    metaInfo: {
      title: 'My Example App', // set a title
      meta: [{                 // set meta
        name: 'keyWords',
        content: 'My Example App'
      }]
      link: [{                 // set link
        rel: 'asstes',
        href: 'https://assets-cdn.github.com/'
      }]
    }
  }
</script> 

npm run build 打包结果可看出

  1. 不同路由有不同的 title
  2. 不同路由也有自己的 meta-name 和 meta-content
    在这里插入图片描述在这里插入图片描述

方案二:Nuxt.js

优点

  1. 纯静态文件,访问速度更快
  2. 对比SSR,不涉及到服务器负载方面的问题
  3. 静态网页不易遭受黑客攻击,安全性更高

不足:

  1. 如果动态路由参数多的话不适用
  2. Nuxt.js 执行generate静态化打包时,动态路由会被忽略
Logo

前往低代码交流专区

更多推荐