用了react 或者 vue,如何做SEO優化呢?
現在react和vue都特別火,但做網站肯定要考慮seo,如何做?
特別火你就用?市場上大部分信息類網站根本就不是SPA(Single Page Application),本來就不需要用React/Vue這些東西折騰自己。這種網站就是後台渲染,組裝頁面,對SEO最友好,其它方面的開發也要簡單許多。
用了不該用的東西,反過來就處處受限,這些技術的server side rendering不是最好的solution,而是work around,技術應該知道兩者的區別。
之前寫了一篇文章:《單頁面應用後台渲染的三次實踐》
我已經想不到一個好的關於前端分享的主題了,於是聯想到最近想要做的一件事,就想到了這個標題。或許這是一個好的主題,又或許這不是一個好的主題。但是至少我可以Share一下我的經驗:
- 基於Mustache模板引擎的前後台渲染。
- 基於PreRender方式的Angular.js應用的後台渲染
- 服務端渲染的React
開始之前,我希望即使你們需要後台渲染,你們也應該前後端分離!由後台來提供API數據,前端用自己的後台來渲染頁面。聽上去有點繞,簡單的來說就是不要把大量的業務邏輯放前台來,只把顯示邏輯放在前台上。這樣一來,即使有一天我們換了新的前端,如移動應用,那麼我們的後台也是可用的。。
為什麼需要前後端分離?
這是一個很古老的話題,對於大公司來說就是部門大了,需要拆分。因此開始之前,先提一下「康威定律」:
Organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations.
換成中文,即:設計系統的組織,其產生的設計和架構等價於組織間的溝通結構。上圖
這張圖可以解釋相當多的軟體開發過程中的問題,而我們知道軟體開發的主要問題是溝通問題。組織結構影響了我們的溝通結構,進而影響了我們的軟體系統結構。好吧,我承認可能離題有點遠。不過,我想說的是組織結構可能不允許我們做出一些好的系統架構。
如我們在《RePractise前端篇: 前端演進史》中提到的那樣:我們已經有了一個桌面版網頁,然後我們打造了一個APP。然而,總有些客戶想在手機上瀏覽但是又不想下APP,我們就需要一個移動版。為什麼會這樣?因為用戶已經被養成了這樣的習慣,大部分的網站提到了桌面版、移動版、APP。要維護這樣的三個不同的系統,對於大部分的業務公司來說成本太高了。
於是,大部分公司來說解決方案就是 後台 + 大前端 (桌面前端、移動Web、手機APP)。Angular和React就是為了解決這樣的問題,而出現了不同的解決方案——基於Angular.js的混合應用框架Ionic、以及React Native。不過在當前,我對React Native的共用UI還是持觀望態度。有人可能會提到Vue和Weex,但是我覺得並沒有那麼好用。或許是因為我接觸React比較早,我覺得Vue的語法四不像。
在這樣的情形下,我們只需要幾個後台開發人員和幾個前端開發人員就可以完成系統的設計了。這種前端開發人員就是最近幾年人們「最想要」的。
前後台渲染同一模板
我接觸的第一個SPA應用是一個基於Spring MVC和Backbone的移動網站,但是它比一般的SPA應該要複雜——由於SEO的緣故,它需要支持後台渲染。
當搜索引擎通過URL訪問我們的網站的時候,我們就需要返回相應的HTML。這意味著我們需要在後台有對應的模板引擎來支持,而由於SPA的性質又決定了,這需要使用一個純前端的模板引擎。因此,我們並不能使用兩個模板引擎來做這件事,維護兩套模板註定會是一件痛苦的事,並且當時還沒有React這種模板引擎在。不過,後來我們發現維護兩種不同的渲染方式也是一件痛苦的事。因此,我們就會有了類似於下圖的架構:
我們在後台使用Spring MVC作為基礎架構、Mustache作為模板引擎,和使用JSP作為模板引擎相比沒有多大的區別——由Controller去獲取對應的Model,再渲染給用戶。多數時候搜索引擎都是依據Sitemap來進行索引的,所以我們的後台很容易就可以處理這些請求。同樣的當用戶訪問相應的頁面的時候,也返回同樣的頁面內容。當完成頁面渲染的時候,就交由Backbone來處理相應的邏輯了。換句話來說,從這時候它就變成了一個單頁面應用。
儘管這是一個三年年前開始的項目,但是在今天看來,這種做法仍然相應地有趣: 大部分的單頁面應用只有一個首頁,並由HTTP伺服器(如Nginx)、Web框架(如Express、Koa)對路由做一些處理,可以讓用戶通過特定地URL訪問特定地頁面。而我們需要保證所有的用戶訪問地都是真實的頁面,既然JavaScript沒有載入完,用戶也能看到完整的頁面。
在這個項目里,最大的挑戰就是如何保證後台渲染和前台渲染的業務邏輯是一樣的。如當我們想要針對不同的產品顯示不同的內容時,我們就需要在JavaScript中賦予一些邏輯,我們還需要在Java在有同樣的邏輯。相比於在同一個代碼里有桌面版、移動版來說,邏輯有更加複雜的趨勢——因為在這種情況下,我們只需要維護兩個不同的模板即可。而在SPA的情況下,我們要維護兩套邏輯。後來,這個框架交由下文中的React與響應式設計重寫。
在今天你仍然可以使用這樣的方式來渲染,JDK 1.8自帶了嵌入式JavaScript引擎Nashorn,完成支持ECMAScript 5.1規範以及一些擴展。
PreRender方式
在們重新設計系統的時候,曾經考慮過類似的做法。將我們的所有頁面渲染成靜態的HTML,然後用爬蟲抓取我們的所有頁面,再上傳到AWS即可。當時我們諮詢了其他小組的做法,其中有一個小組正是採用了這種PreRender的方式——在本地運行起一個Server,由PhantomJS來渲染頁面,再保存為對應的HTML。
PreRender就是預先渲染好HTML,並針對於爬蟲返回特定的HTML。(PS:不過作為一個很有經驗的SEO開發人員,我一點不喜歡這種作法。要知道Google有時候會模擬成真實的用戶,不帶有爬蟲的那些參數和標誌,去訪問頁面。如果你返回給Google的兩個頁面差異太大——可能是你忘記更新了頻率,那麼Google可能就會認為你在作弊。)
對於一般用戶來說就不會返回後台渲染的結果了:
和上面的第一種情況相比,這種作法可以大大減少伺服器地負擔,並且可以直接交由CDN就可以了。這時我們只需要考慮要渲染哪些頁面即可,對於數據量比較少的網站來說這是一個不錯的做法,但是多了就不一樣了。
對於我們來說,有兩個問題:一個是速度的問題,他們有上萬條數據就需要近一天左右的時間來生成(渲染時間長),而我們有上百萬條數據。二是數據的實時問題,我們的產品數據每天都會更新一次。
React
對於使用React的開發人員來說,要處理後台渲染就是一種更簡單的事,畢竟React中提供了一個方法叫 renderToString()。我們所要做的就是用Express或者Koa對路由進行處理,然後返回對應的內容即可:
然後,剩下的事都可以交由React來解決,就是這麼簡單。
因為在這個時候我們在前後台使用的都是JavaScript,我們可以在這個地方直接實現對資料庫的操作,就會出現我們在開頭說到的前後台分離的問題。這樣做並不合理,後台只應該返回我們所需要的數據,並且它可以隨時被其他語言替換掉。
我就說一點,用 Vue 不代表你一定要做成 SPA。現在有些人提起 Vue 就好像一定要 CLI 全家桶,其實 Vue 從一開始就一直很注重對後端渲染的應用做漸進增強的用例,現在歐美也有很多的開發者拿 Vue 直接替代 jQuery 做常見的交互增強。
對於真正適合做成 SPA 的應用,SEO 反而通常不是問題。你針對 marketing 的頁面應該是靜態分開部署的,app 本身則要登陸才能用,SEO 沒有什麼意義。
少數既需要 SPA 強交互性,又對 SEO 和首屏速度有剛性需求的場景,這時候同構 SSR 就派上用場了。
分情況討論:
如果你這是一個新的項目。很建議你直接採用這兩個 lib 對應的 server-side rendering 框架。React 的話可以用 Next.js(zeit/next.js),零配置,完全無痛。第一屏是完全伺服器渲染的。而後續會採用 SPA 的模式,讓你擁有 React.js 開發體驗和免除了 SPA 帶來的 SEO 的煩惱,上手極快,你只要花5分鐘體驗一下就知道。Vue 有對應的 Nuxt.js(https://github.com/nuxt/nuxt.js )。
如果是已有的項目而改寫起來比較困難的話,建議你針對爬蟲的請求進行特殊處理:給伺服器加 http 中間件,識別爬蟲請求,然後返回可處理頁面給爬蟲。
事實就是這些前端框架最適應的場景就是管理平台,不需要做SEO。
展示類為主的老老實實傳統開發
首先評估下自己的站是不是非用前端框架不可,或者用前端框架比傳統開發就是快,否則還是建議傳統的開發,比如用wordpress或者dede能搞得了的東西就別往前端框架上折騰了。
如果用前端框架就是最優選擇,那就大膽的用,然後通過一些手段來進行優化,知乎專欄的文章就是最好的例子。
知乎專欄使用angular是怎麼做到seo的? - 搜索引擎優化(SEO) - 知乎
始終認為,seo或許是比較好的網站推廣方式,但絕不是唯一的推廣方式,還有其他的很多有效的辦法的,如果因為seo的一些限制而造成其他更有價值的東西沒辦法進展,那就捨棄seo唄。(彷彿是一大段廢話哈。。。)
服務端渲染可以解決這個問題,vue是支持服務端渲染的,具體可以看vue-server-renderer的官方文檔https://github.com/vuejs/vue/tree/dev/packages/vue-server-renderer
像知乎,只需要在回復窗口、更多、少數表單使用前端渲染,其他的全部後台渲染即可。
首先 react 以及 vue 是支持 伺服器渲染的 也就是我們常說的前後端同構
nodejs端完成部分業務邏輯並調用後台介面直出頁面到瀏覽器,再由瀏覽器接力執行剩下的業務邏輯
如果硬是要純前端渲染,那麼目前貌似 谷歌是支持的,百度貌似還不行.可以看這個規範 URL 中的 #! 是什麼意思?
百度不太可能只通過兩套爬蟲驗證準確性
大多數網站都是根據不同用戶提供不同體驗的
畢竟爬蟲又不需要樣式交互啊之類的東西…
畢竟…那都是流量都是錢啊……
非SPA網站確實沒太大必要用react
不過,你們可以把非SPA設計成SPA啊…
(?????)體驗更炫酷,開發更簡單
對前端框架的爬蟲了……
百度的支持……現在還不太好,
早晚的事……
首先 沒人人規定用vue和react就一定要單頁面。你不用單頁面也沒人攔著你。不用單頁面也就沒有SEO問題
如果不幸你入坑了單頁面應用,還想要seo的話,沒別的選擇只有server side render。
分兩套頁面不建議使用,搞不好就會被判作弊。
完,下一題
各扎各馬 你非讓詠春拳師踢好掃堂腿
簡單粗暴的網站,通常盈利能力都很高。會有現金流,比如各種分類信息網,甚至是一些商機網。這些網站的顯示層,通常是直接渲染的,或者乾脆就是靜態頁面。這樣方便別人爬取數據。
至於vue,只要用在後台和用戶的操作就可以了。比如發布消息,點贊,回復等。
而信息的展示,純靜態就可以了。
簡單來說就是服務端渲染(Server Side Rendering)。
Google 教程可以搜 universal app(以前都叫 isomorphic app),中文可以搜同構應用。
對 React 來說核心方法是 renderToString()。在服務端根據 url 拼出首屏內容發送給前端,到了前端之後就是 SPA 了。
我常用的套裝包括 express,react-router 和 redux。路由交給 react-router,用 redux 的 store 處理 SSR 中的前後數據交換。
import url from "url";
import express from "express";
import nunjucks from "nunjucks";
import React from "react";
import {renderToString} from "react-dom/server";
import {match, RouterContext} from "react-router";
import {createStore} from "redux";
import {Provider} from "react-redux";
import configureStore from "../../client/store/configureStore";
import reducer from "../../client/reducers";
import routes from "../../client/routes";
import {initializeState} from "../modules/state";
const router = express.Router();
router.get("*", (req, res) =&> {
match({
routes,
location: req.url
}, async(error, redirectLocation, renderProps) =&> {
if(error)
res.status(500).send(error.message);
else if(redirectLocation)
res.status(302).redirect(redirectLocation.pathname + redirectLocation.search);
else if(!renderProps)
res.status(404).send("Not found");
// initializeState() 提供你需要同時交給前端的首屏數據
const state = await initializeState(req);
const store = configureStore(state);
// JSON 化後植入 HTML 模版供前端解析使用
const initialState = JSON.stringify(store.getState());
const assets = require("../../../build/assets.json");
const content = renderToString(
&
);
const html = nunjucks.render("index.html", {
content,
assets,
initialState,
})
res.status(200).send(html);
});
});
export default router;
如果不用 redux,也有辦法實現前後數據交換。原理是把數據拼成一個 JSON 字元串給前端去解析。
話說原來 SSR 不是做 React 的標配么?我從入門時看到的教程都是同構的,所以從來沒做過沒有 SSR 的項目…
我在 GitHub 上還有一個 Isomorphic App 的新手教程坑了半年…找時間拾起來…答案是SSR
https://github.com/nuxt/nuxt.js
https://github.com/surmon-china/surmon.me
我們的做法是針對bot有一套view
vue-server-renderer,官方的基礎支持,嫌麻煩可以用這個vue-easy-renderer,https://github.com/leaves4j/vue-easy-renderer
《也談React服務端渲染》
最近在使用next.js做React服務端渲染,遇到了一些問題,所以才有了這邊文章。希望對你有用
移動網站還是沒成為主流
有seo需求的頁面,貿然全部採用react vue重構肯定是想法錯誤。對於即想保留seo友好,又想將頁面上部分重交互的功能用react重構的需求,只需要將前端代碼構建方式重寫了,就可以繼續保留原來的server render方案,以最小的代價來切換到react生產力環境。
大致思路就是將頁面上的js託管到webpack-dev-server上,然後就可以爽快的進行react es6開發了。具體做法webpack文檔里也有寫,應該是在關於webpack dev server相關的最後面,可以去找找看。如果已經用了webpack、wds,那就是改造下server端的 template里對前端資源的引入地址就好
推薦閱讀:
※零基礎轉前端是怎樣一種體驗?
※網站的美術設計和前端工程師如何溝通?
※有C/C++ 基礎的學生學習網頁開發最好選擇哪門語言?
※Web 開發的前端、後端的入門門檻是不是比較低?
※Flash, Flex, Air, Flashplayer之間的相互關係是什麼?