阅读 2124

vue预渲染之prerender-spa-plugin插件应用

背景

前几天应需求做了一个网页测速小工具,经过考虑,进行了一些选型,由于在公司一直用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的官方MDvue.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查看 没有经过预渲染(类似效果,百度做了很多处理):

经过预渲染之后

这样就大功告成了,水平所限,写的不够深刻,感谢大家阅读!

关注下面的标签,发现更多相似文章
评论