前端prerender-spa-plugin預渲染

prerender-spa-plugin預渲染:構建階段生成匹配預渲染路徑的 html 文件(注意:每一個須要預渲染的路由都有一個對應的
html)。構建出來的 html 文件已有部份內容。
prerender-spa-plugin使用
  • 安裝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後去渲染

  • 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 webpack@4.28.4能夠解決,果真升級了webpack版本後支持路由懶加載

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

相關文章
相關標籤/搜索