Vue预渲染插件prerender-spa-plugin使用全记录

前端大学

共 2963字,需浏览 6分钟

 ·

2020-04-24 23:21

前端大学加星标,提升前端技能.

作者:红烧牛肉面

https://github.com/masterkong/blog/issues/14

服务器端渲染 vs 预渲染 (SSR vs Prerendering)

如果你调研服务器端渲染 (SSR) 只是用来改善少数营销页面(例如 /, /about, /contact 等)的 SEO,那么你可能需要预渲染。无需使用 web 服务器实时动态编译 HTML,而是使用预渲染方式,在构建时 (build time) 简单地生成针对特定路由的静态 HTML 文件。优点是设置预渲染更简单,并可以将你的前端作为一个完全静态的站点。

预渲染页面方式由于不需要web服务器的参与,设置比SSR更简单,特别适合用来展示一些静态页面,比如根据页面UI来自动生成骨架屏。

安装

  1. npm install prerender-spa-plugin --save-dev

prerender-spa-plugin本身的安装非常简单,但是它所依赖的 puppeteer 却有可能让你吃苦头。由于网络原因,直接从npm安装puppeteer有可能会失败,解决办法网络上有很多,最简单就是设置淘宝的镜像源npm config set registry https://registry.npm.taobao.org。

puppeteer的介绍可以参考之前的文章 Puppeteer入门简介

验证puppeteer

顺利安装完prerender-spa-plugin后,提前在环境中验证 puppeteer能让你少走点弯路。这点可能在自己开发用的电脑上不明显,但是在部署环境中就有可能踩坑。

本文用了一个简单的node脚本来验证puppeteer,如果成功生成了百度的截屏baidu.png,预渲染插件的使用就成功一大半了。

  1. const puppeteer =require('puppeteer');


  2. (async()=>{

  3. const browser =await puppeteer.launch({args:['--no-sandbox','--disable-setuid-sandbox']});

  4. const page =await browser.newPage();

  5. await page.goto('https://www.baidu.com');

  6. await page.screenshot({path:'baidu.png'});

  7. await browser.close();

  8. })();

在 CentOS 7.2 环境中验证就遇到了缺少了依赖库的错误。

  1. /chrome-linux/chrome: error while loading shared libraries: libXss.so.1: cannot open shared object file: No such file or directory

  2. TROUBLESHOOTING: https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md

按照 TROUBLESHOOTING 的提示 安装相应的依赖库

  1. > yum install

  2. pango.x86_64

  3. libXcomposite.x86_64

  4. libXcursor.x86_64

  5. libXdamage.x86_64

  6. libXext.x86_64

  7. libXi.x86_64

  8. libXtst.x86_64

  9. cups-libs.x86_64

  10. libXScrnSaver.x86_64

  11. libXrandr.x86_64

  12. GConf2.x86_64

  13. alsa-lib.x86_64

  14. atk.x86_64

  15. gtk3.x86_64

  16. ipa-gothic-fonts

  17. xorg-x11-fonts-100dpi

  18. xorg-x11-fonts-75dpi

  19. xorg-x11-utils

  20. xorg-x11-fonts-cyrillic

  21. xorg-x11-fonts-Type1

  22. xorg-x11-fonts-misc -y


  23. > yum update nss -y

如果在上述依赖库的安装过程还遇到类似以下报错

  1. Error: Protected multilib versions: libXcursor-1.1.15-1.tl2.x86_64 != libXcursor-1.1.14-2.1.el7.i686

  2. Error: Protected multilib versions: libXi-1.7.9-1.tl2.x86_64 != libXi-1.7.4-2.el7.i686

  3. Error: Protected multilib versions: libXtst-1.2.3-1.tl2.x86_64 != libXtst-1.2.2-2.1.el7.i686

那么先可以删除报错的依赖库再安装

  1. > yum remove

  2. libXcursor-1.1.14-2.1.el7.i686

  3. libXi-1.7.4-2.el7.i686

  4. libXtst-1.2.2-2.1.el7.i686 -y

预渲染配置

prerender-spa-plugin的用法在官方文档有着很详细的说明,这里挑几个主要的配置项说下。(如果webpack中有用到 html-webpack-plugin 插件,一般是在此之后再配置 prerender-spa-plugin)

  1. const path =require('path')

  2. constPrerenderSPAPlugin=require('prerender-spa-plugin')

  3. constRenderer=PrerenderSPAPlugin.PuppeteerRenderer


  4. module.exports ={

  5. plugins:[

  6. ...

  7. newHtmlWebpackPlugin(),

  8. ...

  9. newPrerenderSPAPlugin({

  10. // 必填 - webpack输出用于预渲染的html文件的路径.

  11. staticDir: path.join(__dirname,'dist'),

  12. // 必填 - 需要预渲染的vue-router路由.

  13. routes:['/','/about'],

  14. // 可选 - 预渲染的html文件路径。默认为 path.join(staticDir, 'index.html')

  15. indexPath: path.join(__dirname,'dist/index.html'),

  16. // 可选 - 对html文件内容以及生成的最终路径进行自定义处理

  17. postProcess(renderedRoute){

  18. // 删除html中的空白字符

  19. renderedRoute.html = renderedRoute.html.split(/>[\s]+gmi).join('><');

  20. // 将生成的html重命名为prerender.html

  21. renderedRoute.outputPath = path.join(__dirname,'dist', renderedRoute.route,'prerender.html');

  22. return renderedRoute

  23. },

  24. // The actual renderer to use.

  25. renderer:newRenderer({

  26. // puppeteer配置参数

  27. args:['--no-sandbox','--disable-setuid-sandbox'],

  28. // 当设置为false时,可以看到渲染时调用的浏览器,在调试页面时非常有用

  29. headless:true,

  30. // 可选 - 当 document 触发以下事件时才开始渲染页面,使用vue组件时建议配置

  31. renderAfterDocumentEvent:'render-event'

  32. })

  33. })

  34. ]

  35. }

配置了 renderAfterDocumentEvent: 'render-event'时,vue组件需要进行相应的修改

  1. newVue({

  2. el:'#app',

  3. ...

  4. mounted(){

  5. // 通知 prerender-spa-plugin 可以渲染了

  6. document.dispatchEvent(newEvent('render-event'));

  7. }

  8. });

踩坑

经过上面的步骤,prerender-spa-plugin插件的配置算是完成了,但并不代表就一切顺利,下面就记录几个遇到的问题。

渲染的页面成功生成,但是页面运行后却是静态页面,相应的 js 不起作用

这个问题是 Vue主组件模板也需要设置跟el配置项一样的 id。

  1. // App.vue