prerender-spa-plugin預渲染:構建階段生成匹配預渲染路徑的 html 文件(注意:每一個須要預渲染的路由都有一個對應的
html)。構建出來的 html 文件已有部份內容。
prerender-spa-plugin使用
npm install prerender-spa-plugin --savehtml
webpack.prod.config.js中引入node
const PrerenderSPAPlugin = require('prerender-spa-plugin')
const Renderer = PrerenderSPAPlugin.PuppeteerRendererwebpack
plugins: [ new PrerenderSPAPlugin({ staticDir: path.join(__dirname, '../dist'), // outputDir: path.join(__dirname, '../prerendered'), indexPath: path.join(__dirname, '../dist', 'index.html'), routes: ['/mobile/home.html', '/mobile/doctor_team.html', '/mobile/about.html'], renderer: new Renderer({ inject: { foo: 'bar' }, headless: false, renderAfterDocumentEvent: 'render-active' // renderAfterElementExists: '.container', // renderAfterTime: 5000 }) }) ]
staticDir:代碼打包目錄nginx
indexPath:模板頁面web
routes:要預渲染的頁面路由npm
inject:默認掛在window.__PRERENDER_INJECTED對象上,能夠經過window.__PRERENDER_INJECTED.foo在預渲染頁面取值瀏覽器
headless:渲染時顯示瀏覽器窗口。對調試頗有用。app
renderAfterDocumentEvent:等到事件觸發去渲染,此處我理解爲是Puppeteer獲取頁面的時機less
renderAfterDocumentEvent 這個則很關鍵,這個是監聽 document.dispatchEvent
事件,決定何時開始預渲染。須要在鉤子函數中觸發事件,如
new Vue({ el: '#app', router, render: h => h(App), mounted () { // You'll need this for renderAfterDocumentEvent. document.dispatchEvent(new Event('render-active')) } });
renderAfterElementExists:等到dom元素出現時去渲染dom
renderAfterTime:5000ms後去渲染
結合項目,執行打包編譯命令
npm run build:prod
在dist目錄下生成如下頁面,雖然生成了兩層目錄,可是仍是映射到'/mobile/home.html', '/mobile/doctor_team.html', '/mobile/about.html'
查看打包之後的頁面,body內容已經渲染好了
啓動http-server訪問http://127.0.0.1:8080/mobile/about.html,效果跟正常訪問一致
原理
prerender-spa-plugin 利用了 Puppeteer 的爬取頁面的功能。 Puppeteer 是一個 Chrome官方出品的 headlessChromenode 庫。它提供了一系列的 API, 能夠在無 UI 的狀況下調用 Chrome 的功能, 適用於爬蟲、自動化處理等各類場景。它很強大,因此很簡單就能將運行時的 HTML 打包到文件中。原理是在 Webpack 構建階段的最後,在本地啓動一個 Puppeteer 的服務,訪問配置了預渲染的路由,而後將 Puppeteer 中渲染的頁面輸出到 HTML 文件中,並創建路由對應的目錄。
圖片描述(最多50字)
具體代碼能夠結合render-puppeteer下的代碼來看
圖片描述(最多50字)
在render.js中,啓動本地服務,經過page.goto依次訪問
http://localhost:8000/mobile/about.html,
http://localhost:8000/mobile/home.html
http://localhost:8000/mobile/doctor_team.html
經過page.content()獲取html
總結
結合項目實踐了下這個插件,也有很多坑
1.在config/index.js中assetsPublicPath原先寫的是/dist,致使預渲染的頁面body沒有渲染出來,是空白頁面,改爲/就能預渲染出來,可是這樣致使不須要預渲染的頁面資源路徑不對
2.該插件在webpack此版本下不支持路由懶加載,
"webpack": "^4.6.0",
網上提到npm i webpack@4.28.4能夠解決,果真升級了webpack版本後支持路由懶加載
3.在須要請求動態數據的頁面中,預渲染只能保證靜態部分不更改,若是不想寫死,要作動態數據代理,webpack的devserver代理數據無效,須要用nginx或者其餘代理工具代理線上數據