公司項目在已在開發完成的情況下通知需要做SEO優化。因爲項目使用的是vue做的單頁面應用,頓時人都不好了,只好網上搜羅出來一些配置(其實是另一個帶我的老大哥他做的,但是他要走了,工作交接給我, 我需要掌握,所以也算是偷來一門技藝吧)。
交代一下:選用prerender-spa-plugin
插件配合vue-meta
文章目錄
一、 安裝插件
前端全家桶敲代碼前的規矩:配置好package.json
然後npm install
。或者
npm install --save prerender-spa-plugin vue-meta
但是不好意思,剛看了一眼之前寫的注意事項,直接下載太慢了,首先還不能這樣玩兒☺
安裝插件的步驟分爲兩步:
-
1.首先添加環境變量,提高puppeteer的下載速度:
PUPPETEER_DOWNLOAD_HOST=https://npm.taobao.org/mirrors
-
2.然後執行爽翻天的npm install操作
-
3.??還有3?install過程超級慢,先睡一覺吧!
不過倒是有個注意事項:下載過程中會下載一個無頭瀏覽器(這就是下載慢的原因),一看無頭瀏覽器就該知道SEO優化基本實現就靠它了吧。
要是下載失敗,不好意思,請你把prerender相關的包刪除掉再重新下載,直到下載成功!
二、配置預渲染路由
- 新建prerender相關文件
- 文件中配置預渲染路徑
1. 新建prerender
相關文件:
這話有點廢話了。就是我建了一個prerender文件夾,裏面專門存放預渲染相關配置文件。
emmm,太菜了本來想搞個局部目錄索引來的,學業不精,直接貼吧,也是做個記錄。(.md文件不用管,實際上我是看着大佬留下的README.md邊做邊寫完成了README.init.md,然後現在又看着README.init.md在寫這篇文章(手動狗頭))
- 文件中配置預渲染路徑
配置的時候要注意一點,配置時使用的
name
或path
,不是路由的name
或path
,應是真是確定的URL地址(訪問瀏覽器時顯示的真是URL)
prerender > config.js
exports.renderAfterDocumentEvent = '__PRERENDER_TRIGGER';
/**
* 需要預渲染的頁面路由
* Note: 路由 url 不能超過兩層
* @type { String[] }
**/
exports.routes = [
'/home/page', // ... 這裏請配置路由 url
'/detail/1',
];
說明:
- 此處的路由真是地址欄的 url ,是什麼樣呢,就是我們這個用在詳情頁,然後把詳情頁的id寫入了 url 中,結果就是
/detail/1
這樣的配置。很無奈- 很重要的一點是,經過測試,這裏配置的路由不能超過兩層。我們之前也是有三層的,就是詳情嘛,像
/page/detail/1
這樣,但是不行,強行把路由改成了兩級!
prerender > index.js
import Vue from 'vue';
const { renderAfterDocumentEvent } = require('./config');
const prerenderEvent = new Event(renderAfterDocumentEvent);
/** 通知開始保存預渲染頁面 */
export const emitPrerender = (timeout = 0) =>
new Promise(resolve => {
Vue.nextTick(() => {
window.setTimeout(() => {
window.document.dispatchEvent(prerenderEvent);
resolve();
}, timout);
});
});
三、vue.config.js 文件中的配置
- vue.config.js 具體定義需要變量
- 生成配置
- vue.config.js 具體定義需要變量:
const { ContextReplacementPlugin } = require('webpack');
const PrerenderSPAPlugin = require('prerender-spa-plugin');
// 此處路徑爲prerender的配置路徑
const PrerenderConfig = require('../src/prerender/config');
const simplifyMomentPlugin = new ContextPeplacementPlugin(/moment[/\\]locale$/, /zh-cn/);
// 渲染器(無頭瀏覽器)配置項,使用 `renderAfterDocument` 來確定渲染時機
const renderer = new PrerenderSPAPlugin.PuppeteerRenderer({
// headless can be false when debug, 服務器上必須設置爲true
headless: true,
renderAfterDocumentEvent: PrerenderConfig.renderAfterDocumentEvent,
defaultVireport: null,
});
const prerenderPlugin = new PrerenderSPAPlugin({
staticDir: resolve('dist'),
routes: PrerenderConfig.routes,
minify: {
minifyCSS: true,
removeComments: true,
keepClosingSlash: true,
caseSensitive: true,
},
renderer,
});
- 生成配置(重寫 configWebpack 項,此處原本有 simplifyMonmentPlugin 項,現獨立出來 ):
configureWebpack: config => {
config.plugins.push(simplifyMomentPlugin);
if (isProduction) config.plugins.push(prerenderPlugin);
}
四、頁面應用
- 在需要的頁面文件內引入
emitPrerender
- 在需要使用的地方調用
- 新增一個生命週期函數
metaInfo
- 在需要的頁面文件內引入
emitPrerender
:
import { emitPrerender } from '@/prerender';
注:路徑請自行腦補
- 在需要使用的地方調用:
// 如在 mounted 中頁面賦值完成,執行
await emitPrerender();
注:拿產品詳情頁來說,一定要等到需要的數據渲染完成之後再執行函數。
- 新增一個生命週期
metaInfo
:
// 這裏注意是一個新增的生命週期函數
metaInfo() {
return this.createMetaInfo();
}
// methods
createMetaInfo() {
const appTitle = '呂小胖紙的測試appTitle'; // 配置的項目名稱
const siteURL = this.$app.siteURL; // 項目網址
const SITE_DESCRIPTION = '呂小胖紙的測試描述';
return {
title: appTitle,
meta: [
{ name: 'description', content: SITE_DESCRIPTION },
{ name: 'keywords', content: 'keywords' },
{ property: 'og:type', content: 'website'},
{ property: 'og:title', content: appTitle },
{ property: 'og:site_name', content: appTitle },
{ property: 'og:url', content: siteURL },
{ property: 'og:description', content: SITE_DESCRIPTION },
],
};
}
emmm,命名啊還有內容什麼的別太在意了。
五、將meta信息整合進入項目
main.js
引用
import vueMeta from 'vue-meta';
vue.use(vueMeta);
六、打包
運行npm run build
注:如遇到打包失敗,報Puppeteer未安裝等錯誤,需將已安裝的包刪除,或者嘗試重啓電腦再重新
npm install
等之後操作。
(emmmm,所以我上文是不是說錯了,安裝失敗?打包失敗?算了,反正都刪掉再重新安裝總是沒錯的)
七、其他注意
- 需將路由模式改爲hash模式
- 修改打包後路徑
-
路由模式改爲hash模式:
// routes -> index.js new Router 加入屬性 const router = new Router({ mode: 'history', routes: [xxx], });
-
修改打包後路徑
vue.config.js
:
// 路由改爲了hash模式,則vue.config.js中publicPath路徑修改
publicPath : '/';
八、其他注意事項
emmm,這裏我就懶了,我的文件重定向了一下(皮一下),詳見README.MD(主要尋找服務器配置參考)哈哈!
還是貼出來吧,也是記錄大佬的文件!簡潔。話說要不是我知道他肯定會整我,在他走之前把這個的配置流程過了一遍,我不得被他整死,給大家欣賞欣賞高冷風
大佬交接資料之 —— README.md
emmm,話說直接插入md格式咋個搞(哭笑不得)那我就以js文本格式寫吧
// ### 預渲染
爲實現較完善的 SEO ,對部分頁面進行渲染,使用 headless brower 渲染頁面,保存生成後的靜態 HTML 文件,便於搜索引擎爬取。
// #### 安裝說明
* 添加環境變量,提高[`Puppeteer`](https://github.com/puppeteer/puppeteer)的下載速度
PUPPETEER_DOWNLOAD_HOST=https://npm.taobao.org/mirrors
* 若在服務器上打包,出現問題個查看[問題排查](https://github.com/puppeteer/puppeteer/blob/master/docs/troubleshooting.md)
// #### 已知限制
* 路由需要使用 `history` 模式
* 需要預渲染的頁面的 URL 不能超過兩級(v3.4.0)
// #### 使用說明
1. 將需要預渲染的頁面 URL 加入 `config.js` 的 `routes` 配置中
> 注意:不是路由的 `name` 或 `path`,應是真實確定的 URL 地址
2. 在頁面組件中引入本模塊的 `emitPrerender` 方法
```js
import { emitPrerender } from '@/prerender';
```
3. 在合適的時機(例如頁面所有數據均已獲取完成時),調用執行 `emitPrerender` 方法
老規矩,寫文章是爲了記錄,畢竟以後可能會用到,另外,隔一段時間再回來看也是鞏固知識啦!有任何不同聲音探討,我一定虛心請教其他人
完。