搜索引擎優化(Search engine optimization,簡稱SEO),指爲了提高網頁在搜索引擎天然搜索結果中(非商業性推廣結果)的收錄數量以及排序位置而作的優化行爲,是爲了從搜索引擎中得到更多的免費流量,以及更好的展示形象。javascript
SEM(Search engine marketing,搜索引擎營銷),則既包括了SEO,也包括了付費的商業推廣優化。css
本文主要介紹的是前端如何在代碼上作SEO以及單頁項目如何實現SEO。前端
要了解SEO,首先得了解搜索引擎的工做原理,其原理是比較複雜,流程簡化以下:vue
通常爬蟲抓取頁面內容是先從一個頁面出發,從中提取出其餘頁面的連接,而後看成下一個請求的對象,一直重複這個過程。因此要有良好的SEO,須要你在各大網站上擁有外鏈,這樣會提升你的網站被搜索引擎爬蟲的概率。java
爬蟲拿到HTML以後,就會對其內容進行分析。通常須要進行去雜、分詞、簡歷索引數據庫。什麼是索引數據庫呢?簡單地說就是記錄一個詞在哪些文檔中出現、出現次數、出現的位置等等。爲何要簡歷索引數據庫呢?是爲了快速查找。node
搜索會根據你輸入的關鍵詞,分別查詢其對應的索引數據庫,並對結果進行處理和排序。webpack
網站結構要清晰。通常網站的結構是樹形的,通常分爲三個層次:首頁 → 頻道頁(列表頁) → 文章頁(詳情頁)。nginx
網站的結構要扁平。結構層數越少越好,通常不要超過三層,搜索引擎通常到了第三層就不想繼續深刻地爬取了。多數的網站,例如掘金、雪球等,他們的網站結構是兩層,他們的首頁和頻道頁是同一個頁面。git
頁面應該要有簡明的導航。導航可讓搜索引擎知道網站的結構,也可讓搜索引擎知道當前頁面在網站結構所在的層次。 建議:github
alt
屬性告知搜索引擎連接的指向。規範、簡單、易理解的URL能讓搜索引擎更好地抓取內容。建議:
Sitemap 可通知搜索引擎他們網站上有哪些可供抓取的網頁,以便搜索引擎能夠更加智能地抓取網站。
搜索引擎爬行網站第一個訪問的文件就是robots.txt。在這個文件中聲明該網站中不想被蜘蛛訪問的部分,這樣,該網站的部分或所有內容就能夠不被搜索引擎訪問和收錄了,或者能夠經過robots.txt指定使搜索引擎只收錄指定的內容。
不一樣的返回碼,搜索引擎的處理邏輯是不同的。
title是告訴搜索引擎網頁的主要內容。
百度建議描述:
description是對網頁內容的精練歸納。這個標籤存在與否不影響網頁權值,只會用作搜索結果摘要的一個選擇目標。 百度推薦作法:
HTML語義化是用標籤和屬性來描述內容。因此HTML語義化是SEO的基石。通常建議:
關於這部分的內容比較多,本人有一篇筆記《HTML語義化》
目前,對於SEO支持比較好的項目方案是採用服務端渲染。因此若是項目有SEO需求,那麼比較好的方案是服務端渲染。
若是你已經採用了先後分離的單頁項目,而你的網站內容不須要AJAX去獲取內容和展現內容,那麼能夠試試 prerender-spa-plugin 這個插件,這個插件是一個webpack插件,能夠幫助你在打包過程當中經過無頭瀏覽器去渲染你的頁面,並生成對應的HTML。固然這個方案適合你的路由是靜態的,而且路由數量非海量。
若是你的內容是AJAX動態獲取的,那麼vue單頁項目能夠試試 prerender ,這個是一個預渲染服務,能夠幫你經過無頭瀏覽器渲染頁面,並返回HTML。這個方案和prerender-spa-plugin
很類似,都是經過無頭瀏覽器去渲染頁面,不一樣的是渲染的時機,prerender-spa-plugin
是在打包過程當中渲染,註定了其只能渲染靜態路由,而prerender
是在請求時渲染,因此能夠渲染動態的路由。下面我重點介紹一下prerender
方案。
一、安裝
$ npm install prerender
複製代碼
二、啓動服務 server.js
const prerender = require('prerender');
const server = prerender();
server.start();
複製代碼
三、測試
http://localhost:3000/render?url=https://www.example.com/
複製代碼
通過上面三個步驟,你就已經啓動一個預渲染服務,而且會返回"www.example.com/"的內容,整個過程仍是比較簡單的。其github官網上面還介紹了它的許多中間件(Middleware),例如prerender-node (Express)
、nginx.conf
等,那麼這個和 prerender 是什麼關係呢?是否直接使用中間件就能夠呢?下面介紹prerender是如何工做的吧。
首先服務端接收到一個頁面的請求,而後判斷這個請求是否來自搜索引擎的爬蟲,若是不是,則直接返回單頁項目的HTML,按照普通單頁項目的工做模式(客戶端渲染),若是是,則把請求轉發給prerender服務,prerender服務會經過無頭瀏覽器進行預渲染,渲染完成把內容返回,這樣爬蟲就能夠拿到有內容的HTML了。prerender中間件就是用來判斷請求是否來自搜索引擎爬蟲和轉發請求的。
值得注意的是,prerender服務是不包含無頭瀏覽器的,因此須要自行安裝chrome瀏覽器。所以,整個方案運行須要三部分:
那麼prerender服務是怎麼知道頁面渲染已經完成的呢? Prerender服務經過計算未完成的請求數量,來肯定頁面什麼時候完成加載。一旦未完成的請求數達到零,服務會等待一段時間(默認500ms),而後保存HTML。
通過實踐,請求一個通過prerender渲染的頁面是時間,快的時候約2s,慢的時候會長達8s。通常來講,請求時間在3s之內是最好的。因此我從如下幾個方面入手,探索prerender的優化方法。
影響prerender渲染時間的資源主要有js請求資源和api請求資源,api請求時間通常由後端決定,因此我考慮的是如何減小js資源請求時間。通常prerender服務渲染的資源請求地址是由頁面請求URL決定的,因此通常是線上的地址,若是咱們把prerender服務部署在網站的服務器上,讓prerender服務請求資源走本地,那麼就能夠縮短資源的請求時間了。
若是你的線上服務是開啓了CDN的話,那麼資源走本地還有一個好處,就是能夠節省CDN流量。
prerender提供了一些自定義的選項
pageDoneCheckInterval
:這個參數是prerender檢查頁面請求是否完成的定時器時間,默認是500ms,即每500ms檢查未完成的請求數量是否爲零,我將其修改成100ms,提升其檢查的頻率。
waitAfterLastRequest
:這個參數是最後一個請求完成以後等待的時間,默認是500ms,主要是請求完成以後,頁面更新渲染須要時間,當即返回的話,可能請求的數據來不及渲染,我將時間修改成200ms。
添加httpHeaders這個插件,能夠更改返回的HTML的HTTP狀態碼,添加方式以下
var prerender = require('prerender');
var server = prerender()
server.use(prerender.httpHeaders());
server.start();
複製代碼
prerender經過識別在<head>中的<meta>標籤來設置頁面返回的HTTP狀態碼。
<meta name="prerender-status-code" content="404">
複製代碼
若是你須要設置301重定向,能夠這樣作
<meta name="prerender-status-code" content="301">
<meta name="prerender-header" content="Location: http://www.xxx.com">
複製代碼
prerender是根據未完成的請求數來判斷是否渲染結束的。可是咱們給搜索引擎返回的HTML只須要渲染經過js動態增長的DOM,其實不須要渲染css或者渲染接口返回的圖片的,咱們來看下prerender在渲染中是否會請求這些資源。 prerender能夠開啓是否打印請求,開啓方式以下:
var server = prerender({
logRequests: true
});
複製代碼
開啓以後就能夠在控制檯看到請求了,請求裏面是包含css和圖片資源的。
2019-07-17T04:34:03.180Z - 47 http://xxx.com/css/chunk-f4a02584.da8dca38.css
2019-07-17T04:34:03.180Z {
source: 'network',
level: 'error',
text: 'Failed to load resource: net::ERR_INVALID_ARGUMENT',
timestamp: 1563338043130.37,
url: 'http://xxx.com/wefid/css/chunk-f4a02584.da8dca38.css',
networkRequestId: '1000039068.65'
}
2019-07-17T04:34:03.924Z + 3 http://xxx.com/img/erweima_wx.a84d82ef.jpg
2019-07-17T04:34:03.924Z + 4 http://xxx.com/img/erweima_wb.06971584.png
複製代碼
爲何prerender要等待這些資源呢?由於prerender服務還有一個強大的功能,那就是Prerender.com
,其能夠經過一個接口給你返回以下的東西:
很明顯,這些功能是須要加載你所需的CSS或圖片資源的,否則網頁顯示有問題。這個時候,若是你只須要知足SEO需求而不須要Prerender.com
的功能的話,那麼blockResources
插件就能夠派上用場了。插件添加方式以下:
var prerender = require('prerender');
var server = prerender()
server.use(prerender.blockResources());
server.start();
複製代碼
使用blockResources
插件以後,圖片資源和字體資源會被abort(捨棄)。
若是你想更細粒化地控制prerender的返回時機,提早結束或者延後結束,那麼可使用這個標誌window.prerenderReady
。
首先須要設置window.prerenderReady
爲false,prerender在檢測到window.prerenderReady
爲false
以後,會等待你設置爲true
再返回結果。
<script> window.prerenderReady = false; </script>
複製代碼
當你渲染完成以後,通常在接口請求完成並渲染完成以後
window.prerenderReady = true;
複製代碼
這樣你就能夠更加自由地控制渲染結束的時機。
緩存這裏有兩個方面,一方面是HTTP緩存(瀏覽器緩存),另外一方面是渲染結果緩存。
首先HTTP緩存可讓prerender服務不用頻繁地發起資源請求,節省傳輸時間。這個我就不展開將,我想講的是渲染結果緩存。prerender中間件提供了兩種緩存方式, redis 或者 memcached ,以redis爲例:
$ npm install redis
複製代碼
var redis = require("redis"),
client = redis.createClient();
prerender.set('beforeRender', function(req, done) {
client.get(req.url, done);
}).set('afterRender', function(err, req, prerender_res) {
client.set(req.url, prerender_res.body)
});
複製代碼
你能夠經過 beforeRender 和 afterRender 這兩個鉤子進行細粒化地控制,對於內容變化頻繁的不緩存或緩存時間短,對於內容變化不頻繁的設置長時間緩存。開啓緩存不只能夠加速返回時間,還能夠減輕服務器的壓力。
統計和監控能夠放在中間件的 afterRender 中進行。
prerender.set('afterRender', function(err, req, prerender_res) {
if(err){
// 這裏是錯誤監控代碼
// ...
// return
}
let {headers: req_headers, originalUrl} = req
let {headers: res_headers, body} = prerender_res
// 這裏是統計代碼,能夠保存請求和返回的相關信息
})
複製代碼
經過以上的優化方法(除了自定義渲染結束時間和開啓緩存),我已經將HTML的請求時間穩定在2.5s左右。
以上就是我想講的關於前端編碼SEO的所有內容,總而言之,就是