SEO 在 SPA 站点中的实践

SEO 在 SPA 站点中的实践

观察基于 create-react-doc 搭建的文档站点, 发现网页代码光秃秃的一片(见下图)。这显然是单页应用 (SPA) 站点的通病 —— 不利于文档被搜索引擎搜索 (SEO)。

SEO 在 SPA 站点中的实践

难道 SPA 站点就无法进行 SEO 了么, 那么 Gatsby、nuxt 等框架又为何能作为不少博主搭建博客的首选方案呢, 此类框架赋能 SEO 的技术原理是什么呢? 在好奇心的驱动下, 笔者尝试对 creat-react-doc 进行赋能 SEO 之旅。

搜索引擎优化

在实践之前, 先从理论上分析为何单页应用不能被搜索引擎搜索到。核心在于 爬虫蜘蛛在执行爬取的过程中, 不会去执行网页中的 JS 逻辑, 所以隐藏在 JS 中的跳转逻辑也不会被执行。

查看当前 SPA 站点打包后的代码, 除了一个根目录 index.html 外, 其它都是注入的 JS 逻辑, 因此浏览器自然不会对其进行 SEO。

SEO 在 SPA 站点中的实践

此外, 搜索引擎详优化是一门较复杂的学问。如果你对 SEO 优化比较陌生, 建议阅读搜索引擎优化 (SEO) 新手指南 一文, Google 搜索中心给出了全面的 17 个最佳做法, 以及 33 个应避免的做法, 这也是笔者近期在实践的部分。

SEO 在 SPA 站点中的实践案例

在轻文档站点的背景前提下, 我们暂不考虑 SSR 方案。

对市面上文档站点的 SEO 方案调研后, 笔者总结为如下四类:

静态模板渲染方案

404 重定向方案

SSG 方案

预渲染方案

静态模板渲染方案

静态模板渲染方案以 hexo 最为典型, 此类框架需要指定特定的模板语言(比如 pug)来开发主题, 从而达到网页内容直出的目的。

404 重定向方案

404 重定向方案的原理主要是利用 GitHub Pages 的 404 机制进行重定向。比较典型的案例有 spa-github-pages、sghpa。

但是遗憾的是 2019 年 Google , 因此此类重定向方案在当下是无利于 SEO 的。spa-github-pages 作者也表示如果需要 SEO 的话, 使用 SSG 方案或者付费方案 Netlify。

SEO 在 SPA 站点中的实践

SSG 方案

SSG 方案全称为 static site generator, 中文可译为路由静态化方案。社区上 nuxt、Gatsby 等框架赋能 SEO 的技术无一例外可以归类此类 SSG 方案。

以 nuxt 框架为例, 在约定式路由的基础上, 其通过执行 nuxt generate 命令将 vue 文件转化为静态网页。

例子:

-| pages/ ---| about.vue/ ---| index.vue/

静态化后变成:

-| dist/ ---| about/ -----| index.html ---| index.html

经过路由静态化后, 此时的文档目录结构可以托管于任何一个静态站点服务商。

预渲染方案

经过上文对 SSG 方案的分析, 此时 SPA 站点的优化关键已经跃然纸上 —— 静态化路由。相较于 nuxt、Gatsby 等框架存在约定式路由的限制, create-react-doc 在目录结构上的组织灵活自由。它的建站理念是文件即站点, 同时它对存量 markdown 文档的迁移也十分便捷。

以 blog 项目结构为例, 其文档结构如下:

-| BasicSkill/ ---| basic/ -----| DOM.md -----| HTML5.md

静态化后应该变成:

-| BasicSkill/ ---| basic/ -----| DOM -------| index.html -----| HTML5 -------| index.html

经过调研, 该构思与 prerender-spa-plugin 预渲染方案一拍即合。预渲染方案的原理可以见如下图:

SEO 在 SPA 站点中的实践

至此技术选型定下为使用预渲染方案实现 SSG。

预渲染方案实践

create-react-doc 在预渲染方案实践的步骤简单概况如下(完整改动可见 mr):

改造 hash 路由为 history 路由。因为 history 路由结构与文档静态化目录结构天然匹配。

export default function RouterRoot() { return ( - <HashRouter> + <BrowserRouter> <RoutersContainer /> - </HashRouter> + </BrowserRouter> ) }

在开发环境、生成环境的基础上新增预渲染环境, 同时对路由进行环境匹配。其主要解决了资源文件与主域名下的子路径的对应关系。过程比较曲折, 感兴趣的同学可以见 。

const ifProd = env === 'prod' + const ifPrerender = window.__PRERENDER_INJECTED && window.__PRERENDER_INJECTED.prerender + const ifAddPrefix = ifProd && !ifPrerender <Route key={item.path} exact - path={item.path} + path={ifAddPrefix ? `/${repo}${item.path}` : item.path} render={() => { ... }} />

兼容 prerender-spa-plugin 在 webpack 5 的使用。

官方版本当前未支持 webpack 5, 详见 issue, 同时笔者存在对预渲染后执行回调的需求。因此当前 fork 了一份版本 出来, 解决了以上问题。

经过上述步骤的实践, 终于在 SPA 站点中实现了静态化路由。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsfxgf.html