正在開發(fā)中的項(xiàng)目是采用vue樟蠕,Vue+router搭建的單頁面應(yīng)用贮聂,因2C項(xiàng)目有SEO的需求,就需要把當(dāng)前的項(xiàng)目改為多頁面+服務(wù)端渲染寨辩,調(diào)研之后使用了easywebpack-cli腳手架吓懈,基于Egg + Vue + Webpack4多頁面服務(wù)端渲染項(xiàng)目開發(fā)模板進(jìn)行改造。
一:為什么要做SEO
提高網(wǎng)站搜索排名靡狞,從而吸引更多的潛在客戶來瀏覽網(wǎng)站耻警,目的是增加網(wǎng)站訪問量,提升企業(yè)的銷售業(yè)績甸怕,獲得效益搜索網(wǎng)站通過爬蟲爬取網(wǎng)頁內(nèi)容甘穿,SEO讓爬蟲更好的理解網(wǎng)頁內(nèi)容(主要是文本)
二:為什么單頁面無法做SEO
一般的單頁面是發(fā)送一個(gè)“空白”的HTML到瀏覽器,瀏覽器通過再獲取頁面對應(yīng)的js文件梢杭, js操作dom展示頁面温兼,但是SEO無法去解析js的內(nèi)容派近,爬蟲所“看到”的案疲,其實(shí)是一個(gè)空白的頁面磕诊,SEO中重要的TDK爷贫,在單頁面應(yīng)用中只能設(shè)置固定的TDK诗茎,或者通過js去設(shè)置的锭环,再次設(shè)置的實(shí)際爬蟲也是無法獲取的驮肉,再者涣雕,單頁面應(yīng)用在訪問跳轉(zhuǎn)頁面時(shí)全释,實(shí)際只是替換了中間變化的模板部分装处,整體模板頭部尾部是不變的,這就造成了對瀏覽器而言恨溜,實(shí)際我們訪問的一直都是一個(gè)地址只是后面的參數(shù)在變化符衔,對于很多網(wǎng)站分析工具就無法做針對用戶訪問路徑的優(yōu)化分析單頁面的模式,在切換頁面糟袁,訪問URL上體驗(yàn)好判族,流暢度高,對于部署也較簡單项戴,但是對有SEO需求的就不是很友好了
多頁面單頁面對比
單頁面 | 多頁面 | |
---|---|---|
模式 |
|
|
用戶體驗(yàn) | 加載快辩撑,切換流暢度高界斜,用戶體驗(yàn)好 | 切換加載較慢,流暢度不高 |
適用場景 | 追求操作流暢合冀,用戶體驗(yàn)的應(yīng)用 | 高度支持搜索引擎的應(yīng)用 |
部署維護(hù) | 部署實(shí)現(xiàn)簡單各薇,維護(hù)簡單 | 部署維護(hù)相對復(fù)雜 |
三:改造過程
1、路由
原路由采用vue-router君躺,egg.js不支持這種方式峭判,需要把路由轉(zhuǎn)化為對應(yīng)的路由easywebpack-cli腳手架地址/app/router.js
module.exports = app => {
app.get('/home', app.controller.home.index);
}
在控制器中/app/controller/home.js設(shè)置路由對于的模板或接口
module.exports = app => {
return class HomeController extends app.Controller {
async index() {
const {ctx} = this;
await ctx.render('home/index.js');
}
}
}
上例渲染了一個(gè)模板返回到頁面,模板地址/app/web/page/home/index.vue路由配置支持/home/:id params參數(shù)棕叫,控制器通過ctx.params可獲取林螃,在控制器也可以返回模板帶入?yún)?shù)數(shù)據(jù)
module.exports = app => {
return class HomeController extends app.Controller {
async index() {
const {ctx} = this;
await ctx.render('home/index.js', {
id: ctx.params.id,
data: [1, 2, 3]
});
}
}
}
在瀏覽器端vue模板內(nèi),可通過this.data直接獲取到控制器傳回的參數(shù)路由代理俺泣,使用egg-http-proxy配置路由代碼疗认,更新包之后,在config/plugin.js里配置中間件伏钠,
exports.httpProxy = {
enable: true,
package: 'egg-http-proxy'
};
// 在config/config.default.js里引用并配置地址
exports.httpProxy = {
'/oldServer': 'http://xxx.com',
'/otherServer': 'http://xxx.com'
};
返回指定文件横漏,例如favicon.ico,sitemap.xml等熟掂,可在config/config.default.js siteFile里配置
exports.siteFile = {
'/favicon.ico': fs.readFileSync(path.join(app.baseDir, 'app/web/asset/images/favicon.ico')),
'/sitemap.xml': fs.readFileSync(path.join(app.baseDir, 'app/web/asset/sitemap/sitemap.xml'))
};
2绊茧、模板
項(xiàng)目有兩套模板,/app/web/component/layout/index.js 服務(wù)器端模板打掘,/app/web/view/layout.html 瀏覽器端模板,當(dāng)服務(wù)端渲染出現(xiàn)錯(cuò)誤鹏秋,js報(bào)錯(cuò)或在created中調(diào)用window尊蚁,localStorage等,導(dǎo)致服務(wù)端無法正常渲染時(shí)侣夷,就會(huì)調(diào)用備用的瀏覽器端渲染模板横朋,也可通過controller控制根據(jù)不同場景渲染返回不同的模板,下例通過判斷不同設(shè)備PC或wise百拓,返回不同的模塊
if (isMobile(ctx.get('user-agent'))) {
await ctx.render('home/index.js');
} else {
await ctx.render('home/indexPc.js');
}
3琴锭、TDK的改造
title
- 每個(gè)頁面單獨(dú)的title;
- 主題明確衙传,涵蓋頁面主旨內(nèi)容
- 不羅列關(guān)鍵詞决帖,使用戶能夠快速分辨出主題,最好不超過17個(gè)中文漢字蓖捶,否則在搜索結(jié)果中會(huì)被折行
- 重要內(nèi)容往左放地回,保持語義通順
- 使用用戶熟知或習(xí)慣用語
- 如果品牌名高,最好能展示出來名牌詞
keywords
- 高度概括網(wǎng)站主題服務(wù)的一至三個(gè)關(guān)鍵詞
- 關(guān)鍵詞的同義詞
- 網(wǎng)站所屬的上一級別關(guān)鍵詞(不一定能有),避免過于寬泛
- 品牌詞或服務(wù)詞
- 用戶潛在需求相關(guān)關(guān)鍵詞(比如保險(xiǎn)的可能涉及到投資)
- 關(guān)鍵詞相關(guān)的長尾關(guān)鍵詞刻像,一般比較長畅买,如“百年人壽保險(xiǎn)怎么樣”
- 考慮用戶可能會(huì)通過什么樣的關(guān)鍵詞查找到我們的網(wǎng)站
description
- 對title的補(bǔ)充,準(zhǔn)確描述頁面內(nèi)容细睡,不堆砌關(guān)鍵詞(否則會(huì)被搜索引擎判定作弊嫌疑)
- 每個(gè)頁面要有不同的description谷羞,盡量不適用默認(rèn)一樣的
- 適當(dāng)?shù)拈L度,超出會(huì)被截?cái)?/li>
四:SEO改造
Sitemap:網(wǎng)站地圖溜徙,告知搜索引擎那些頁面可供抓取湃缎,有利于隱藏層級較深的頁面
一般為xml格式,設(shè)置成功之后需在站長平臺(tái)提交
robots.txt :爬蟲協(xié)議萌京,爬蟲訪問的第一個(gè)文件雁歌,告知那些頁面可以訪問,那些禁止訪問
兩個(gè)文件都被放置在網(wǎng)站跟目錄并可直接訪問知残,配置config/config.default.js siteFile
exports.siteFile = {
'/favicon.ico': fs.readFileSync(path.join(app.baseDir, 'app/web/asset/images/favicon.ico')),
'/sitemap.xml': fs.readFileSync(path.join(app.baseDir, 'app/web/asset/sitemap/sitemap.xml')),
'/robots.txt': fs.readFileSync(path.join(app.baseDir, 'app/web/asset/sitemap/robots.txt'))
};
五:其他優(yōu)化
1靠瞎、語義化
- 文檔類型統(tǒng)一使用HTML5 doctype <!DOCTYPE HTML>
- meta標(biāo)簽優(yōu)化,主要有title求妹、description乏盐、keywords三個(gè)地方,結(jié)束不要使用“ />”制恍,應(yīng)該直接寫“>”
- css文件最好使用一個(gè)父能,放在頭部<head>標(biāo)簽里面
- js文件最好放在底部,避免因加載js文件阻塞HTML的渲染
- 使用外聯(lián)文件净神,避免在HTML直接寫css和js的代碼
- 引入文件時(shí)使用絕對地址何吝,絕對地址包括了網(wǎng)站的域名
- img標(biāo)簽加上alt關(guān)鍵字,利于SEO優(yōu)化鹃唯,盡量不要使-用“的”爱榕、“上”、“好”坡慌、“等等”等黔酥,搜索引擎數(shù)據(jù)庫默認(rèn)不收錄的字
- 當(dāng)圖片過多時(shí)使用懶加載
- logo處加h1標(biāo)簽,搜索引擎默認(rèn)h1標(biāo)簽這個(gè)標(biāo)題是網(wǎng)頁中最重要的信息洪橘,所以我們把最重要信息入在<H1>標(biāo)簽內(nèi)
2跪者、json+ld
2011年Google,Bing熄求,Yahoo渣玲!和Yandex共同努力為網(wǎng)絡(luò)創(chuàng)建統(tǒng)一的結(jié)構(gòu)化數(shù)據(jù)詞匯表(但是,Bing和其他搜索引擎尚未正式聲明他們支持Schema.org的JSON-LD實(shí)現(xiàn))弟晚,結(jié)構(gòu)化數(shù)據(jù)是用于提供關(guān)于頁面的信息并分類頁面內(nèi)容的標(biāo)準(zhǔn)化格式柜蜈,例如文章標(biāo)題仗谆,簡介,作者淑履,圖片等信息隶垮,基于json格式,簡單易懂秘噪,更方便搜索引擎理解頁面內(nèi)容狸吞,詳細(xì)結(jié)構(gòu)可參考初學(xué)者JSON-LD指南