前端prerender-spa-plugin預渲染

prerender-spa-plugin預渲染:構建階段生成匹配預渲染路徑的 html 文件(注意:每個需要預渲染的路由都有一個對應的
html)。構建出來的 html 文件已有部分內容。
prerender-spa-plugin使用
  • 安裝prerender-spa-plugin

    npm install prerender-spa-plugin --save

  • webpack.prod.config.js中引入

    const PrerenderSPAPlugin = require('prerender-spa-plugin')
    const Renderer = PrerenderSPAPlugin.PuppeteerRenderer

    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:代碼打包目錄

indexPath:模板頁面

routes:要預渲染的頁面路由

inject:默認掛在window.__PRERENDER_INJECTED對象上,可以通過window.__PRERENDER_INJECTED.foo在預渲染頁面取值

headless:渲染時顯示瀏覽器窗口。對調試很有用。

renderAfterDocumentEvent:等到事件觸發去渲染,此處我理解爲是Puppeteer獲取頁面的時機

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元素出現時去渲染

renderAfterTime:5000ms後去渲染

  • webpack打包編譯

結合項目,執行打包編譯命令

npm run build:prod

在dist目錄下生成以下頁面,雖然生成了兩層目錄,但是還是映射到'/mobile/home.html', '/mobile/doctor_team.html', '/mobile/about.html'

clipboard.png

查看打包以後的頁面,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下的代碼來看

clipboard.png

圖片描述(最多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

clipboard.png

總結

結合項目實踐了下這個插件,也有不少坑

1.在config/index.js中assetsPublicPath原先寫的是/dist,導致預渲染的頁面body沒有渲染出來,是空白頁面,改成/就能預渲染出來,但是這樣導致不需要預渲染的頁面資源路徑不對

2.該插件在webpack此版本下不支持路由懶加載,

"webpack": "^4.6.0",

網上提到npm i [email protected]可以解決,果然升級了webpack版本後支持路由懶加載

3.在需要請求動態數據的頁面中,預渲染只能保證靜態部分不更改,如果不想寫死,要做動態數據代理,webpack的devserver代理數據無效,需要用nginx或者其他代理工具代理線上數據

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章