因為用了vue等js的資料繫結機制來展示頁面資料,爬蟲獲取到的html是模型頁面而不是最終資料的渲染頁面,搜尋引擎是不回去執行請求到的js。vue的專案都是ajax請求資料,引擎爬蟲進入頁面獲取不到文字內容,現在大多數解決方案是不採用ajax渲染資料,而是採用server端渲染,也就是所謂的SSR。
目前基於vue的方案是Nuxt.js,同型別的也有React版的Nuxt.js所以伺服器端渲染就是儘量在伺服器傳送到瀏覽器前,頁面上是有資料可讓爬蟲進行爬取
傳統的vue通過vue-cli腳手架搭建完成後要通過npm run build來打包生成最後的要放到線上的html程式碼。
vue搭建的單頁面專案有各種優點,易維護、程式碼簡潔、開發體驗好等等。但是對於一些傳統的網際網路公司,vue單頁面卻有一個很致命的問題就是seo優化的問題。下面是正常打包的vue單頁面目錄以及index.html的程式碼。
目錄只有一個index.html檔案並且這個html檔案裡面是沒有任何內容的只有一個id為app的用來掛載vue範例的div。
谷歌搜尋引擎已經可以很好地支援單頁面的資訊爬取,但是谷歌是國外的國內使用要翻牆所以不作考慮,百度是國內最主要的搜尋引擎,百度並不能爬取單頁面的資料所以這樣的專案如果上線了別人在百度搜尋的時候很難找到這個專案。由於我目前公司的大部分專案都是需要做seo優化的所以這個問題就丟到了我這裡。
解決辦法
這裡先提一下如果打包的時候報錯可能你需要npm安裝一下puppeteer(這東西有點大大概300多M)
第一步通過prerender-spa-plugin來進行vue.config.js的設定
npm isntall prerender-spa-plugin --save
這個東西是vue用來將單頁面應用打包成多頁面的第三方外掛,安裝完成之後在vue.config.js設定設定如下
const PrerenderSPAPlugin = require('prerender-spa-plugin');
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer;
const webpack = require('webpack');
const path = require('path');
module.exports = {
configureWebpack: config => {
if (process.env.NODE_ENV !== 'production') return;
return {
plugins: [
new PrerenderSPAPlugin({
// 生成檔案的路徑,也可以與webpakc打包的一致。
// 下面這句話非常重要!!!
// 這個目錄只能有一級,如果目錄層次大於一級,在生成的時候不會有任何錯誤提示,在預渲染的時候只會卡著不動。
staticDir: path.join(__dirname,'dist'),
// 對應自己的路由檔案,比如a有引數,就需要寫成 /a/param1。
routes: ['/','/about','/store_vuex','/cssAnimate','/connectMongoDB','/childParent','/child1','/elementUI'],
// 這個很重要,如果沒有設定這段,也不會進行預編譯
renderer: new Renderer({
inject: {
foo: 'bar'
},
headless: false,
// 在 main.js 中 document.dispatchEvent(new Event('render-event')),兩者的事件名稱要對應上。
renderAfterDocumentEvent: 'render-event'
})
})
],
};
}
}
然後要將vue路由的模式改成history
最後mian.js入口檔案中要加入這段程式碼。其中render-event要和vue.config.js中的renderAfterDocumentEvent對應
new Vue({
router,
store,
render: h => h(App),
mounted () {
document.dispatchEvent(new Event('render-event'))
}
}).$mount('#app')
npm run build現在打包之後的目錄結構就變成了這樣了,以及每個資料夾的index.html程式碼,
現在的html程式碼就有了.vue檔案中的template相關程式碼,但是卻多了一個問題就是每個資料夾中的index.html程式碼都參照了所有的js和css檔案這是不利於seo優化的。因此還沒有結束。
為什麼會有這麼多js和css呢,因為vue-cli在打包的時候每個.vue檔案的script和style標籤都會打包成一個對應的js和css,即使你標籤裡面什麼都沒有寫。
第二步我是壓縮合並體積比較小的js和css檔案
找了vue-cli的檔案沒有搜尋到相關的資料,因此轉戰webpack
這個api可以用來設定一個最小的合併檔案體積,在上邊的webpack設定中的plugins中加入這段程式碼目測是10000=1kb
const webpack = require('webpack');
new webpack.optimize.MinChunkSizePlugin({
minChunkSize: 10000 // 通過合併小於 minChunkSize 大小的 chunk,將 chunk 體積保持在指定大小限制以上
}),
然後npm run build
還是那個目錄,但是js和css縮減了很多。
方法二、Vue SSR (伺服器端渲染)
簡而言之就是將本來要放在瀏覽器執行建立的元件,放到伺服器端先建立好,然後生成對應的html將它們直接傳送到瀏覽器,最後將這些靜態標記"啟用"為使用者端上完全可互動的應用程式。
Vue SSR 相比 SPA(單頁應用)好處及壞處
1、好處
更好的 SEO,由於搜尋引擎爬蟲抓取工具可以直接檢視完全渲染的頁面。
更快的內容到達時間(time-to-content),特別是對於緩慢的網路情況或執行緩慢的裝置。
2、壞處
1)開發條件所限。瀏覽器特定的程式碼,只能在某些生命週期勾點函數(lifecycle hook)中使用;一些外部擴充套件庫(external library)可能需要特殊處理,才能在伺服器渲染應用程式中執行。
2)涉及構建設定和部署的更多要求。與可以部署在任何靜態檔案伺服器上的完全靜態單頁面應用程式(SPA)不同,伺服器渲染應用程式,需要處於 Node.js server 執行環境。
3)更多的伺服器端負載。在 Node.js 中渲染完整的應用程式,顯然會比僅僅提供靜態檔案的 server 更加大量佔用 CPU 資源(CPU-intensive - CPU 密集),因此如果你預料在高流量環境(high traffic)下使用,請準備相應的伺服器負載,並明智地採用快取策略。