前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用预渲染提升SPA应用体验

使用预渲染提升SPA应用体验

作者头像
Javanx
发布2019-09-05 16:31:06
2.8K0
发布2019-09-05 16:31:06
举报
文章被收录于专栏:web秀web秀

前言

在目前的前端领域,单页web应用(SPA)已经有了比较高的占有率,比较主流的web框架React、Angular、Vue几乎已经统治了前端市场。

单页应用确实带来了更好的前后端分离,以及用户体验好、快,内容的改变不需要重新加载整个页面等等的优点,喜忧参半,SPA应用首屏加载慢、白屏以及 SEO 等问题也就慢慢显露出来。

问题的来源是SPA应用采用的是客户端渲染,DOM节点要等待JS文件加载完毕后才会生成,所以就浮现了以上几个问题。

为了解决以上问题,目前有两个比较主流的解决方案:

1、 服务端渲染(SSR) 2、 预渲染Prerender

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

什么是服务端渲染(SSR)?

当服务器接收到请求后,它把需要的组件渲染成 HTML 字符串,然后把它返回给客户端(这里统指浏览器)。之后,客户端会接手渲染控制权。

优势: 更好的 SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面。 更快的内容到达时间 (time-to-content),特别是对于缓慢的网络情况或运行缓慢的设备。

问题: 涉及构建设置和部署的更多要求。 更多的服务器端负载。 目前已经有了比较成熟的服务端渲染应用框架,React有Next.js,Vue有Nuxt.js(文档十分详细,社区也挺丰富?),它们都是由zeit.co 背后的团队发布的,当然你也可以自己构建一套服务端渲染。

什么是预渲染(Prerender)?

无需使用web 服务器实时动态编译 HTML,而是使用预渲染方式,在构建时 (build time) 简单地生成针对特定路由的静态HTML 文件。

如果项目中使用 webpack,你可以使用 prerender-spa-plugin 轻松地添加预渲染,后面将会具体实现。

是否需要?哪个更适合?

在对你的应用程序使用服务器端渲染 (SSR) 之前,你应该问的第一个问题是,是否真的需要它。这主要取决于内容到达时间 (time-to-content) 对应用程序的重要程度。如果并不太重要,这种情况下去使用服务器端渲染 (SSR) 将是一个小题大作之举。

如果假设你需要更好SEO和内容到达时间 (time-to-content) ,如果你使用服务器端渲染 (SSR) 只是用来改善少数页面,那么这个时候你可能更需要预渲染,优点是设置预渲染更简单,你可以获得SSR的几乎所有优点,无需更改代码或添加服务器端就能轻松实现的解决方案。

在项目中加入预渲染(Prerender)

用prerender-spa-plugin可以给现有项目加入预渲染,我们就以Vue为实例进行预渲染优化。

先用Vue官方提供的脚手架3.0搭建一个简单的Vue项目,步骤就不写了,具体实现可以参照官方文档。

1. 安装prerender-spa-plugin依赖

代码语言:javascript
复制
yarn add prerender-spa-plugin --dev

1.1 坑点 因为这个组件需要依赖Puppeteer,它是是 Google Chrome 团队官方的无界面(Headless)Chrome 工具,它是一个 Node 库,提供了一个高级的 API 来控制 DevTools协议上的无头版 Chrome 。也可以配置为使用完整(非无头)的 Chrome。

鉴于 Puppeteer 需要 Chromium,但是即便你的上网姿势足够科学,也同样会遇到安装失败的问题,尝试了很多解决方案,提供一个成功率较高的解决方案。

在你的项目根目录创建一个.npmrc的文件,当然你也可以直接修改你本机的.npmrc配置。

代码语言:javascript
复制
// .npmrc
puppeteer_download_host = https://npm.taobao.org/mirrors

然后再尝试安装。

2. 创建vue.config.js

代码语言:javascript
复制
// vue.config.js
const path = require('path')
const PrerenderSPAPlugin = require('prerender-spa-plugin')
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer

function resolve (dir) {
  return path.join(__dirname, dir)
}

module.exports = {
  publicPath: './',
  configureWebpack: () => {
    if (process.env.NODE_ENV === 'production') {
      return {
        plugins: [
          new PrerenderSPAPlugin({
            staticDir: resolve('dist'),
            routes: ['/', '/about'], // 你需要预渲染的路由
            renderer: new Renderer({
              inject: {
                _m: 'prerender'
              },
              // 渲染时显示浏览器窗口,调试时有用
              headless: true,
              // 等待触发目标时间后,开始预渲染
              renderAfterDocumentEvent: 'render-event'
            })
          })
        ]
      }
    }
  }
}

更多详细的配置可以查看prerender-spa-plugin官方文档,根据需求添加。

3. 在生命周期里调用自定义事件

代码语言:javascript
复制
// main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'

Vue.config.productionTip = false

new Vue({
  router,
  render: h => h(App),
  mounted () {
    // 触发renderAfterDocumentEvent
    document.dispatchEvent(new Event('render-event'))
  }
}).$mount('#app')

4. 运行打包脚本

代码语言:javascript
复制
yarn run build

没有使用预渲染打包得到的dist文件夹目录:

使用预渲提升SPA应用体验
使用预渲提升SPA应用体验

使用预渲染后打包得到的dist文件夹目录:

使用预渲提升SPA应用体验
使用预渲提升SPA应用体验

可以看到多了一个about目录,里面有一个html文件。我们查看一下根目录的html文件,也就是首页的html文件。

没有使用预渲染得到根目录html文件:

使用预渲提升SPA应用体验
使用预渲提升SPA应用体验

使用预渲染得到根目录html文件:

使用预渲提升SPA应用体验
使用预渲提升SPA应用体验

部署后预渲染和非预渲染的差别

我把它们都部署到gh-pages上,我们来看一下差别。

没有使用预渲染请求到的Document:

使用预渲提升SPA应用体验
使用预渲提升SPA应用体验

使用预渲染请求到的Document:

使用预渲提升SPA应用体验
使用预渲提升SPA应用体验

可以看到使用预渲染时初始化的HTML文件已经有了DOM结构,这样爬虫就可以来抓取到DOM结构,SEO优化更好。

录了两个GIF点击刷新体验下差别,提前在调试工具钩上Disable cache,每次刷新都不会使用缓存,重新向服务器发起请求。没有使用预渲染:

使用预渲提升SPA应用体验
使用预渲提升SPA应用体验

使用预渲染:

使用预渲提升SPA应用体验
使用预渲提升SPA应用体验

可以看到使用预渲染之后首屏几乎没有白屏。

可以点击下面链接亲自体验一下,Demo地址:

没有预渲染Demo

预渲染Demo

不足

预渲染的只是快照页面,不适合频繁变动的页面 设置路由越多,构建时间越长 这是我使用时感觉比较遗憾的地方,并不一定全面。

总结

个人理解,插件的实现原理是在打包完成之后, 利用了 Puppeteer的爬取页面的功能,模拟浏览器访问路由,然后把JS生成的DOM结构以HTML静态文件的形式再保存下来。

确实是渐进式的解决了SPA应用潜在的一些问题,并且比较容易的就能集成到现有的项目,但也有遗憾的地方。

本文只是做了一个简单的Demo,更多的使用技巧还需要你亲手去探索。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 服务器端渲染 vs 预渲染 (SSR vs Prerender)
    • 什么是服务端渲染(SSR)?
      • 什么是预渲染(Prerender)?
        • 是否需要?哪个更适合?
        • 在项目中加入预渲染(Prerender)
          • 1. 安装prerender-spa-plugin依赖
            • 2. 创建vue.config.js
              • 3. 在生命周期里调用自定义事件
                • 4. 运行打包脚本
                • 部署后预渲染和非预渲染的差别
                • 不足
                • 总结
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档