前段时间对项目作了 SEO 优化,到如今才来写总结。咱们知道,常规用 Vue/React 开发的是 SPA 应用,可是自然的单页面应用 SEO 就是很差,虽说如今也有各类技术能够改善了,好比使用预渲染,但也都存在各类缺点。可是即便这样,也抵不住 Vue/React 这类框架的潮流,不少产品也能够经过其余亮点而不依赖 SEO 普及开,也有须要登陆才能用的使用 SEO 也没有什么意义。javascript
若是项目中真的对 SEO 和首屏加载速度有刚性需求,又使用 Vue/React 这类技术,且想尽可能减小代码开发附加的难度,有一种比较直接的方式,就是直接使用服务端渲染的框架,Vue 的 Nuxt.js,React 的 Next.js/Gatsby。html
不过,其实学习一门新框架也是一项附加成本啊哈哈,可是 SSR 渲染不过实际开发用不用,起码都要了解一下。我当前以 React 技术栈为主,因此目前只了解的是关于 React 的 SSR 渲染框架,有兴趣的能够看下我这两篇文章:前端
因此本文不讨论单页面应用的 SEO 优化,讲的是基于服务端渲染(SSR)/静态生成(SSG)网站 SEO 的优化。java
本文会回顾传统的 SEO 的优化方式,以及基于 Gatsby SEO 的优化。react
服务端是指客户端向服务器发出请求,而后运行时动态生成 html 内容并返回给客户端。
静态站点的解析是在构建时执行的,当发出请求时,html 将静态存储,直接发送回客户端。git
一般来讲,静态站点在运行时会更快,由于不须要服务端作处理,但缺点是对数据的任何更改都须要在服务端进行彻底重建;而服务端渲染则会动态处理数据,不须要进行彻底重建。github
对于 Vue/React 来讲,对于它们的 SSR/SSG 框架出现的缘由就是主要就是 SEO 和首屏加载速度。web
在搜索引擎网站的后台会有一个很是庞大的数据库,里面存储了海量的关键词,而每一个关键词又对应着不少网址,这些网址是被称之为“搜索引擎蜘蛛”或“网络爬虫”程序从互联网上收集而来的。
这些"蜘蛛"在互联网上爬行,从一个连接到另外一个连接,对内容进行分析,提炼关键词加入数据库中;若是蜘蛛认为是垃圾或重复信息,就舍弃继续爬行。当用户搜索时,就能检索出与关键字相关的网址显示给用户。算法
当用户在搜索引擎搜索时,好比搜索"前端",则跳出来全部含有"前端"二字关键字的网页,而后根据特定算法给每一个含有"前端"二字的网页一个评分排名返回搜索结果。而这些包含"前端"的内容,能够是文章标题、描述、关键字、内容甚至能够是连接。固然,也有多是广告优先置顶,你懂的。数据库
一个关键词对用多个网址,所以就出现了排序的问题,相应的当与关键词最吻合的网址就会排在前面了。在“蜘蛛”抓取网页内容,提炼关键词的这个过程当中,就存在一个问题:“蜘蛛”可否看懂。若是网站内容是 flash 和 js 等,那么它是看不懂的,会犯迷糊,即便关键字再贴切也没用。相应的,若是网站内容能够被搜索引擎能识别,那么搜索引擎就会提升该网站的权重,增长对该网站的友好度。这样一个过程咱们称之为 SEO(Search Engine Optimization),即搜索引擎优化。
让网站更利于各大搜索引擎抓取和收录,增长对搜索引擎的友好度,使得用户在搜索对应关键词时网站时能排在前面,增长产品的曝光率和流量。
咱们这里主要讲前端能参与和作的优化方式。好比不少 SEO 优化方式都有介绍:控制首页连接数量,扁平化目录层次,优化网站结构布局,分页导航写法这些等,但实际上,平常前端开发也充当不了网站总体设计的角色,只能是协调,这些大部分都是一开始就定好的东西。
好比新闻媒体类等网站比较重视 SEO 的,一般公司还会设有 SEO 部门或者是 SEO 优化工程师岗位,像上面说的,还有网页关键词、描述的就交给他们参与和提供,有些优化方式咱们难以触及的就不细谈了,有兴趣的能够去了解。
每一个页面的 TDK 都不同,这个须要根据产品业务提炼出核心关键词。
那么页面的 TDK 都不同,咱们就须要对它进行动态设置,react 的话有react-helmet
插件,用于设置头部标签。
import React from 'react' import { Helmet } from 'react-helmet' const GoodsDetail = ({ title, description, keywords }) => { return ( <div className='application'> <Helmet> <title>{title}</title> <meta name='description' content={`${description}`} /> <meta name='keywords' content={`${keywords}`} /> </Helmet> <div>content...</div> </div> ) }
上面是演示,实际项目作法仍是会把 Helmet 里的内容单独抽离出来作组件。
在 Next.js 里面,是自带 Head 组件的:import Head from 'next/head'
根据内容的结构化,选择合适的 HTML5 标签尽可能让代码语义化,如使用 header,footer,section,aside,article,nav 等等语义化标签可让爬虫更好的解析。
一个页面中只能最多出现一次h1
标签,h2
标签一般做为二级标题或文章的小标题。其他h3
-h6
标签如要使用应按顺序层层嵌套下去,不能够断层或反序。
好比一般在首页的 logo 上加h1
标签,但网站设计只展现 logo 图无文字的状况下,h1 的文字就能够设置font-size
为零来隐藏
<h1> <img src="logo.png" alt="jacky" /> <span>jacky的我的博客</span> </h1>
通常来讲,除非是图片仅仅是纯展现类没有任何实际信息的话,alt
属性能够为空。不然使用img
标签都要添加alt
属性,使"蜘蛛"能够抓取到图片的信息。
当网络加载不出来或者图片地址失效时,alt
属性的内容才会代替图片呈现出来,
<img src="dog.jpg" width="300" height="200" alt="哈士奇" />
同理,a 标签的 title 属性其实就是提示文字做用,当鼠标移动到该超连接上时,就会有提示文字的出现。经过添加该属性也有微小的做用利于 SEO。
<a href="https://github.com/Jacky-Summer/personal-blog" title="了解更多关于Jacky的我的博客" >了解更多</a >
404 页面首先是用户体验良好,不会莫名报一些其余提示。其次对蜘蛛也友好,不会由于页面错误而中止抓取,能够返回抓取网站其余页面。
<meta name="robots" content="nofollow" />
<a href="https://www.xxxx?login" rel="nofollow">登陆/注册</a>
一般用在 a 标签比较多,它主要有三个做用:
rel='nofollow'
告诉"蜘蛛"不要爬,来避免爬虫抓取一些无心义的页面,影响爬虫抓取的效率;并且一旦"蜘蛛"爬了外部连接,就不会再回来了。robots.txt 文件由一条或多条规则组成。每条规则可禁止(或容许)特定抓取工具抓取相应网站中的指定文件路径。
User-agent: * Disallow:/admin/ SiteMap: http://www.xxxx.com/sitemap.xml
关键词:
User-agent: *
表示对全部的搜索引擎有效User-agent: Baiduspider
表示百度搜索引擎,还有谷歌 Googlebot 等等搜索引擎名称,经过这些能够设置不一样搜索引擎访问的内容参考例子的话好比百度的 robots.txt,京东的 robots.txt
robots 文件是搜索引擎访问网站时第一个访问的,而后根据文件里面设置的规则,进行网站内容的爬取。经过设置Allow
和Disallow
访问目录和文件,引导爬虫抓取网站的信息。
它主要用于使你的网站避免收到过多请求,告诉搜索引擎应该与不该抓取哪些页面。若是你不但愿网站的某些页面被抓取,这些页面可能对用户无用,就经过Disallow
设置。实现定向 SEO 优化,曝光有用的连接给爬虫,将敏感无用的文件保护起来。
即便网站上面全部内容都但愿被搜索引擎抓取到,也要设置一个空的 robot 文件。由于当蜘蛛抓取网站内容时,第一个抓取的文件 robot 文件,若是该文件不存在,那么蜘蛛访问时,服务器上就会有一条 404 的错误日志,多个搜索引擎抓取页面信息时,就会产生多个的 404 错误,故通常都要建立一个 robots.txt 文件到网站根目录下。
空 robots.txt 文件
User-agent: * Disallow:
若是想要更详细的了解 robots.txt 文件,能够看下:
通常涉及目录比较多的话都会找网站工具动态生成 robots.txt,好比 生成 robots.txt
当网站刚刚上线的时候,连往该网站的外部连接并很少,爬虫可能找不到这些网页;或者该网站的网页之间没有较好的衔接关系,爬虫容易漏掉部分网页。这个时候,sitemap 就派上用场了。
sitemap 是一个将网站栏目和链接归类的一个文件,让搜索引擎全面收录站点网页地址,了解站点网页地址的权重分布以及站点内容更新状况,提升爬虫的爬取效率。Sitemap 文件包含的网址不能够超过 5 万个,且文件大小不得超过 10MB。
sitemap 地图文件包含 html(针对用户)和 xml(针对搜索引擎)两种,最多见的就是 xml 文件,XML 格式的 Sitemap 一共用到 6 个标签,其中关键标签包括连接地址(loc)、更新时间(lastmod)、更新频率(changefreq)和索引优先权(priority)。
爬虫怎么知道网站有没有提供 sitemap 文件呢,也就是上面说的路径放在了 robots.txt 里面。
先找网站的根目录里找 robots.txt,好比腾讯网下的 robots.txt 以下:
User-agent: * Disallow: Sitemap: http://www.qq.com/sitemap_index.xml
就找到了 sitemap 路径(只列出一部分)
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <sitemap> <loc>http://news.qq.com/news_sitemap.xml.gz</loc> <lastmod>2011-11-15</lastmod> </sitemap> <sitemap> <loc>http://finance.qq.com/news_sitemap.xml.gz</loc> <lastmod>2011-11-15</lastmod> </sitemap> <sitemap> <loc>http://sports.qq.com/news_sitemap.xml.gz</loc> <lastmod>2011-11-15</lastmod> </sitemap> <sitemap> </sitemapindex>
通常网站开发完后,这个 sitemap 通常都是靠自动生成,好比 sitemap 生成工具
结构化数据(Structured data)是一种标准化格式,使用它向 Google 提供有关该网页含义的明确线索,从而帮助理解该网页。通常都 JSON-LD 格式,这格式长什么样呢,看谷歌官方的示例代码:
<html> <head> <title>Party Coffee Cake</title> <script type="application/ld+json"> { "@context": "https://schema.org/", "@type": "Recipe", "name": "Party Coffee Cake", "author": { "@type": "Person", "name": "Mary Stone" }, "nutrition": { "@type": "NutritionInformation", "calories": "512 calories" }, "datePublished": "2018-03-10", "description": "This coffee cake is awesome and perfect for parties.", "prepTime": "PT20M" } </script> </head> <body> <h2>Party coffee cake recipe</h2> <p> This coffee cake is awesome and perfect for parties. </p> </body> </html>
列明了网页页面种类属于"食谱",做者和发布时间,描述和烹饪时间等等。这样谷歌搜索出来就有机会含有这些提示或者你带着关键信息去搜索更有利于找到结果。
官方提供了各类字段用来描述"食谱",你只要去查阅相关字段,就能够直接按格式来使用了。
由于该 SEO 优化针对谷歌搜索引擎特有的,因此有设置该方式的网站一般是用户是不限于国内的,不只是结构化数据特有,还有一种 SEO 优化方式是 AMP 网页,感兴趣的能够了解看看 —— AMP
谷歌还提供了测试工具 Structured Data Testing Tool,能够输入测试网站网址来查看该网站有没有结构化数据设置。
好比减小 http 请求,控制页面大小,懒加载,利用缓存等等,这方式就不少了,都是为了提升网站的加载速度和良好用户体验,这个也不是专指 SEO 的问题,是开发中都要作的事情。
由于当网站速度很慢时,一旦超时,"蜘蛛"也会离开。
自己 Gatsby 就采起静态生成的方式,SEO 已经是能够,但依然仍是要作 SEO 优化。
知道了上述的 SEO 优化方式后,Gatsby 该如何实战优化呢?这个,因为 Gatsby 社区比较强大,插件不少,因此上面几个依靠插件就能够快速配置生成。
在 gatsby-config.js 里面配置
module.exports = { siteMetadata: { siteUrl: 'https://www.xxxxx.com' }, plugins: ['gatsby-plugin-robots-txt'] };
在 gatsby-config.js 里面配置
{ resolve: `gatsby-plugin-sitemap`, options: { sitemapSize: 5000, }, },
Gatsby 标准脚手架和有官方文档都有一个 SEO.js 文件,里面就是给咱们设置 TDK 提供了方法
import React from 'react' import PropTypes from 'prop-types' import { Helmet } from 'react-helmet' import { useStaticQuery, graphql } from 'gatsby' function SEO({ description, lang, meta, title }) { const { site } = useStaticQuery( graphql` query { site { siteMetadata { title description author } } } ` ) const metaDescription = description || site.siteMetadata.description return ( <Helmet htmlAttributes={{ lang, }} title={title} meta={[ { name: `description`, content: metaDescription, }, { property: `og:title`, content: title, }, { property: `og:description`, content: metaDescription, }, { property: `og:type`, content: `website`, }, { name: `twitter:card`, content: `summary`, }, { name: `twitter:creator`, content: site.siteMetadata.author, }, { name: `twitter:title`, content: title, }, { name: `twitter:description`, content: metaDescription, }, ].concat(meta)} /> ) } SEO.defaultProps = { lang: `en`, meta: [], description: ``, } SEO.propTypes = { description: PropTypes.string, lang: PropTypes.string, meta: PropTypes.arrayOf(PropTypes.object), title: PropTypes.string.isRequired, } export default SEO
而后在页面模板文件中引入 SEO.js,并传入页面的变量参数,便可设置 TDK 等等头部信息。
好比说项目是新闻文章展现的,能够设置三种结构化数据(数据类型和字段不是凭空捏造的,这个须要去 Google 查符合对应匹配的)——文章详情页,文章列表页,再加个公司的介绍。
在项目根目录下新建
./src/components/Jsonld.js
import React from 'react' import { Helmet } from 'react-helmet' function JsonLd({ children }) { return ( <Helmet> <script type="application/ld+json">{JSON.stringify(children)}</script> </Helmet> ) } export default JsonLd
./src/utils/json-ld/article.js
- 文章详情结构化数据描述const articleSchema = ({ url, headline, image, datePublished, dateModified, author, publisher, }) => ({ '@context': 'http://schema.org', '@type': 'Article', mainEntityOfPage: { '@type': 'WebPage', '@id': url, }, headline, image, datePublished, dateModified, author: { '@type': 'Person', name: author, }, publisher: { '@type': 'Organization', name: publisher.name, logo: { '@type': 'ImageObject', url: publisher.logo, }, }, }) export default articleSchema
./src/utils/json-ld/item-list.js
- 文章列表结构化数据描述const itemListSchema = ({ itemListElement }) => ({ '@context': 'http://schema.org', '@type': 'ItemList', itemListElement: itemListElement.map((item, index) => ({ '@type': 'ListItem', position: index + 1, ...item, })), }) export default itemListSchema
./src/utils/json-ld/organization.js
- 公司组织结构化数据描述const organizationSchema = ({ name, url }) => ({ '@context': 'http://schema.org', '@type': 'Organization', name, url, }) export default organizationSchema
而后再分别引入页面,好比咱们在文章详情页面,引入对应类型文件,大概就是这么个用法:
// ... import JsonLd from '@components/JsonLd' import SEO from '@components/SEO' import articleSchema from '@utils/json-ld/article' const DetailPage = ({ data }) => { // 处理 data,拆开相关字段 return ( <Layout> <SEO title={meta_title || title} description={meta_description} keywords={meta_keywords} /> <JsonLd> {articleSchema({ url, headline: title, datePublished: first_publication_date, dateModified: last_publication_date, author: siteMetadata.title, publisher: { name: siteMetadata.title, logo: 'xxx', }, })} </JsonLd> <Container> <div>content...</div> </Container> </Layout> ) }
上面的代码要是迷迷糊糊却是正常,由于没有了解过结构化数据的内容,但看文档就大概能够了解清楚了。
能够去谷歌商店安装LightHouse
,打开 F12,进入你的网站,点击Generate report
,就会生成网站对应的报告
在它下面有一些提示,针对性能和 SEO 等,你能够根据提示去改善你的代码。
文章的介绍到这里就结束了,但愿对你们了解 SEO 有一点帮助。SEO 的摸索并非以上举例完就差很少没了,其实有各类各样的方式能够优化。上面列举的是比较常见的,事实上,我以为 SEO 优化无非是想吸引更多的用户点击和使用网站,但若是网站的内容优质用户体验良好,加性能好,那么有用户使用后就自带推广性,那么无疑比 SEO 简单的优化强多了。