预渲染
# 客户端渲染、预渲染、服务器端渲染
用户请求前的服务器渲染即为「预渲染」。
用户请求后的服务器渲染即为「服务端渲染」。
客户端渲染:用户访问 url,请求 html 文件,前端根据路由动态渲染页面内容。关键链路较长,有一定的白屏时间;
服务端渲染:用户访问 url,服务端根据访问路径请求所需数据,拼接成 html 字符串,返回给前端。前端接收到 html 时已有部分内容;
服务端渲染的过程:解析执行 JS => 构建 HTML 页面 => 输出给浏览器
预渲染:构建阶段生成匹配预渲染路径的 html 文件(注意:每个需要预渲染的路由都有一个对应的 html)。构建出来的 html 文件已有部分内容
预渲染过程:直接输出 HTML 页面给浏览器
# 预渲染
预渲染基本上是在启动无头浏览器,加载应用程序的路由并将结果保存到静态 HTML 文件中。
针对单页应用,服务端渲染和预渲染共同解决的问题:
SEO:单页应用的网站内容是根据当前路径动态渲染的,html 文件中往往没有内容,网络爬虫不会等到页面脚本执行完再抓取;
弱网环境:当用户在一个弱环境中访问你的站点时,你会想要尽可能快的将内容呈现给他们。甚至是在 js 脚本被加载和解析前;
低版本浏览器:用户的浏览器可能不支持你使用的 js 特性,预渲染或服务端渲染能够让用户至少能够看到首屏的内容,而不是一个空白的网页。 预渲染能与服务端渲染一样提高 SEO 优化,但前者比后者需要更少的配置,实现成本低。弱网环境下,预渲染能更快地呈现页面内容,减少页面可见时间。
如果实例中更多是变化的数据,时效性要求比较高,不太适合预渲染的场景。如果想用预渲染来减少白屏时间,让页面反馈更及时的话,可以预渲染骨架屏。
# prerender-spa-plugin 原理
那么 prerender-spa-plugin 是如何做到将运行时的 html 打包到文件中的呢?原理很简单,就是在 webpack 构建阶段的最后,在本地启动一个 phantomjs,访问配置了预渲染的路由,再将 phantomjs 中渲染的页面输出到 html 文件中,并建立路由对应的目录。
# 预渲染不适用场景
大量路由-如果您的站点有成百上千个路由,则预渲染将非常缓慢。当然,每个更新只需要执行一次,但是可能要花一些时间。大多数人并没有最终获得数千个静态网页,而是以防万一。
动态内容-如果您的渲染页面包含特定于用户查看其内容或其他动态源的内容,则应确保拥有可以显示的占位符组件,直到动态内容加载到客户端为止。否则可能有点怪异。比如说股票代码网站,天气预报网站。因为此时的数据是动态的,而预渲染时已经生成好了 dom 节点。
经常变化的内容:如果你预渲染一个游戏排行榜,这个排行榜会随着新的玩家记录而更新,预渲染会让你的页面显示不正确直到脚本加载完成并替换成新的数据。这是一个不好的用户体验;