背景
前幾天應需求做了一個網頁測速小工具,經過考慮,進行了一些選型,由於在公司一直用react搬磚,所以這次決定提高全方面能力,接觸並使用vue構建一個小型專案,vue用gizp壓縮後僅有約33KB,加上axios和prerender-spa-plugin以及業務程式碼,壓縮後僅不到50KB,使用者體驗比較良好。
由於使用vue次數不多,所以各種查閱資料,但是感覺過程中非常不順暢,從我的感受看,網上vue平均提供的資料遠不如react提供的資料,踩過一些坑,特別是prerender-spa-plugin外掛遇到了很多網上沒有提及的問題,於是把自己的收穫分享出來,給vue貢獻一份力量。
源起
先讀了vue官方的指南,說的很清晰,如果圖省事,而且是小型展示專案的話,用預渲染再好不過,可以解決SEO和使用者載入體驗兩大痛點,聽上去很棒,很符合我現在的需求,於是就開始動手吧!增加一處說明 : 預渲染是編譯時提前渲染一次,伺服器端渲染ssr是使用者每次請求伺服器,伺服器把相應的內容填進去(這兩者本質的不同,特此說明 !)
安裝
安裝這個外掛是第一個坑點,由於這個小專案是獨立的,所以不需要考慮npm包的版本,直接上最新的vuecli3.0跑整個環境,但是說實話,vuecli3這個腳手架給我的體驗很糟糕,原有的webpack配置被隱藏了,換成了vue.config.js,但是網上資料不多,配置多花了些時間 安裝prerender-spa-plugin時用了nrm切到cnpm,但是總是卡在安裝puppeteer這個地方,prerender-spa-plugin外掛是需要依賴puppeteer的,這個外掛會下載最新版的chromium---谷歌出品的無頭(headless)瀏覽器核心(大約200M+),所以如果不能科學上網,下載的時候就報錯了。我是用的lantern等了很長一段時間,才下載完,版本是72,所以說,經常翻牆很重要啊?
原理
puppeteer是谷歌出品的一個外掛,可以完成很多的操作,廣泛使用在爬蟲、測試自動化等瀏覽器自動化方向的應用,而prerender-spa-plugin這個外掛正是依賴puppeteer操作chromium這個真正的瀏覽器核心對SPA跑了一遍,生成一個靜態的HTML,裡面是已經填好的dom節點和資料,就是這麼簡單粗暴,為了給使用者直接返回有內容的xhtml文件,提前在一個瀏覽器裡跑了一遍,生成了跑過js和css之後index.html(跟路由)和其他文件。這樣的話有兩個缺陷,第一個:無法展示使用者自身的內容,第二個:不適合動態路由多的大型專案。理解了原理,就可以放心使用了?
配置
如果開始使用,第一個要注意的點是要把引入的vue-router模式設定為history(平時我也是推薦用history模式,hash有#很醜,只是history多配置一下回到根目錄),不過如果本身就是一個根路徑,沒有下級路由,那麼不引入vue-router也是會給編譯的。。。
在vuecli3.0中,所有的原webpack配置都被放到vue.config.js
裡面。
如果時間富裕,建議從頭讀一下github的官方MD
在vue.config.js
裡面先引入
const PrerenderSPAPlugin = require('prerender-spa-plugin');
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer;
複製程式碼
然後module.exports
configureWebpack: {
plugins: [
new PrerenderSPAPlugin({
staticDir: path.join(__dirname,'dist'),
routes: ['/'],
renderer: new Renderer({
inject: {
foo: 'bar'
},
headless: false,
renderAfterDocumentEvent: 'render-event',
//renderAfterTime: 5000,
//renderAfterElementExists: 'my-app-element'
}),
}),
..............
複製程式碼
- staticDir裡面的dist是輸出資料夾名字,不用多說了
- routes配置的是你想實現預渲染的路由,這裡我只有根路由需要預渲染,還有其他的路由可以在陣列中繼續新增
- renderer預渲染提供了三種時機實現,renderAfterDocumentEvent、renderAfterTime、renderAfterElementExists
常用的是renderAfterDocumentEvent和renderAfterTime,意思很簡單,就是一個是在某個事件之後開始預渲染,另一個是在載入後幾秒之後開始預渲染,
如果用
renderAfterDocumentEvent
要配合在vue生命週期中實現
mounted: function(){
document.dispatchEvent(new Event('render-event'));
},
複製程式碼
這樣配置過後,每次打包build,外掛就會自動呼叫chromium核心把路由中的html裡面填上內容,想觀察區別可以通過chrome的preview檢視 沒有經過預渲染(類似效果,百度做了很多處理):
經過預渲染之後這樣就大功告成了,水平所限,寫的不夠深刻,感謝大家閱讀!