闲来无事水文章系列
注:此文章只是想简单阐述一下SSR和preRender各自做SEO的处理思路。选择一个东西还是要根据当前业务、时间成本、技术的熟悉程度来进行选择
前言
前些日子,在处理低代码的同时接手了一个要做SEO的官网。官网的技术栈是我用vue搭起来的,众所周知对于现代的js框架来说,要做SEO首先要处理的就是要让蜘蛛可以爬到你页面上的所有内容。
怎么处理呢?
比较传统的两个方案
- 做SSR
- 做预渲染
因为我也是第一次接触这种东西,又赶上我亲爱的老大跑路了,所以我开始自己瞎鼓捣。总的来说就是爬了一堆坑,所以上面这两种主流方案我也都试了一个遍。
首先来说一下比较火的SSR,SSR其实是比较简单的,因为无论是React还是Vue都有一个对应next或者nuxt做对应(当然还有一个开源的egg做的也蛮强的)。
简单说一下它的基本原理:拿一个spa的React举例,就是要想办法将app这个根组件在服务器端就转成html串传给浏览器(比如可以借助react-dom/server下面的renderToString方法)。当然服务端绑定不了事件,还有同时维护一个客户端的代码。再处理客户端服务端store数据不一致问题(脱水注水)。
虽然细看好像东西很多,但是说来说去主要就是想把html在服务器生成好了再返回去,且SSR的轮子也很成熟。有轮子嘛,用就完事了。但是好像预渲染就没有那么出名了。所为这篇文章我们来玩一玩预渲染。
预渲染原理
1. 使用预渲染服务器(爬虫的应用)
首先项目没做处理时
不做任何处理的时候项目基本流程是这样的(如下图)。客户端访问index.html,服务器返回。
没有做处理的时候肯定获取的html是这样的
这时候,浏览器肯定先得解析js。才能把对应的dom挂到id为root的div上,浏览器完成渲染,页面显示
但是蜘蛛不会看js执行完后的结果,它看到的东西就是上图中啥信息都没有的骨架。
给他加一个预渲染服务器
此时的架构变成了这个样子(ps:实际上判断是否是蜘蛛直接用react所在的服务器就可以了,这里只是看的清晰一点)
如果普通用户访问,那没有必要处理。如果是蜘蛛访问,那就要走一下预渲染服务器了
这个预渲染中主要干了点什么东西呢?
主要它模拟了一下这样的操作
就类似于这种操作:当我们F12时,元素面板里面的东西已经是chunkjs执行完毕之后的了。所以是不是可以把这里的html copy一份返给蜘蛛呢?
看到这里,不知道小伙伴是不是有点对这个预渲染服务器的工作有些好奇,不晓得它是怎么做到的。
但是遗憾的是,小白当初对它也基本没有花费精力。所以我也没有具体去看看它实现思路,不过小白在这里提供一下我自己的一个思路
按上面的模拟操作,看起来我们可以采用爬虫的思路。这里我简单的用Puppeteer
,按上面的架构简单实现一下
步骤一:首先可以用cra新启一个react项目
此时页面当然是客户端渲染的,源码上看不到任何主要内容(如Learn React)
步骤二:搭建我们的预渲染服务器(当然是用前端最熟悉的node了)
可以看到这里新开了一个pup_server
因为只是简单模仿,那么我们就可以这么干。开一个浏览器,再开一个页面打开上面那个react项目(假设端口在3000)。然后爬取它的代码copy一份
核心代码如下
const puppeteer = require('puppeteer')
const fs = require('fs')
const start = async () => {
const browser = await puppeteer.launch({
headless: false,
})
const page = await browser.newPage();
await page.goto('http://localhost:3000/', { timeout: 20000 });
const html = await page.content()
fs.writeFileSync('index.html', html)
}
start()
复制代码
打开一下copy来的html,可以看到这份已经有了内容。
预览这份文件好像有点问题,但是它只是给蜘蛛的,view效果我们又不cure
有兴趣的小伙伴可以也看一下这个Prerender
2. 再来说一下使用prerender-spa-plugin
说实话,上面的架构有一点复杂。这里webpack提供了一个插件prerender-spa-plugin
。其实原理还是那个原理。
首先使用这个东西处理一般的SPA项目,它要求你的路由模式得是history
。因为它要按照路由进行打包。什么意思呢?
来看一下打出的目录结构你就明白了
简单介绍一下,我的这个项目有四个路由,分别是about
index
intro
study
原本的正常打出来的包是不会有这四个文件夹的,这里多出来的这四个文件夹是什么东西呢?有了上面的基础我们很快就能想到了。这就是在本来SPA包构建完成之后他又搞了个模拟浏览器,打开对应路由的页面拿到其中的源码copy出来,又依次在放到以各个路由命名的文件夹下
可以看到这些文件夹下,都是copy过来的html。这个东西就是要给蜘蛛的。从用户的角度其实是没有变化的,还是从根的index.html开始。和以往的流程是一样的。只是为了seo专门处理了一些需要给蜘蛛的东西
SSR和preRender到底是有什么不同呢?
从思想上看:
先说现代框架要做SEO的主要矛盾是什么呢?
答:就因为现在框架的主要内容区域的dom(<div id='root'></div>
)。它就是需要浏览器执行js去创建去挂载,可是蜘蛛就是拿不到这些内容。
针对这个问题
SSR想的是:好你拿不到是吧,那我就在服务器端把html都整好了发给你。
preRender想的是:客户端有两种角色,1是普通用户2是蜘蛛。只是你蜘蛛拿不到是吧,那我就想方法给你蜘蛛想要的,用户那块逻辑我不动。
要用哪个呢,处理看当前业务,也要看他们分别有什么不足是吧?
比如:SPA项目的通病就是首屏慢,这个时候你用SSR不仅处理了SEO还处理了首屏问题
但是,你boss突然给你了一个你对他业务完全不熟悉的项目让你做SEO,给你一两天时间。你总不能直接就把它拿过来开始往next或者nuxt上迁移吧(我惊了)
好了今天先去吃饭了,这篇先简单说下思想。后面有机会再好好整理一篇出来…