首屏预渲染方案

栏目: Node.js · 发布时间: 4年前

内容简介:该方案主要是为了解决,前端 spa (单页面应用),首屏渲染慢,白屏时间过长问题。通过 webpack 的 prerender-spa-plugin 编译应用中的静态页面,并将其输出到对应的索引目录。prerender-spa-plugin 利用了 Puppeteer 的爬取页面的功能。 Puppeteer 是 Google Chrome 团队官方的无界面(Headless)Chrome 工具,它是一个 Node 库,提供了一个高级的 API 来控制 DevTools 协议上的无头版 Chrome 。pre

该方案主要是为了解决,前端 spa (单页面应用),首屏渲染慢,白屏时间过长问题。

实现方法

通过 webpack 的 prerender-spa-plugin 编译应用中的静态页面,并将其输出到对应的索引目录。

prerender-spa-plugin 插件原理介绍

prerender-spa-plugin 利用了 Puppeteer 的爬取页面的功能。 Puppeteer 是 Google Chrome 团队官方的无界面(Headless)Chrome 工具,它是一个 Node 库,提供了一个高级的 API 来控制 DevTools 协议上的无头版 Chrome 。prerender-spa-plugin 原理是在 Webpack 构建阶段的最后,在本地启动一个 Puppeteer 的服务,访问配置了预渲染的路由,然后将 Puppeteer 中渲染的页面输出到 HTML 文件中,并建立路由对应的目录。

在 create-react-app 中配置 prerender-spa-plugin

create-react-app 配置未 eject 的情况:

在项目根目录添加 config-overrides.js 配置文件,参考配置如下:

const PrerenderSpaPlugin = require('prerender-spa-plugin');
const path = require('path');

module.exports = (config, env) => {
  if (env === 'production') {
    config.plugins = config.plugins.concat([
      new PrerenderSpaPlugin({
        staticDir: path.join(__dirname, 'build'),
        routes: ['/'],
        renderer: new PrerenderSpaPlugin.PuppeteerRenderer({
          injectProperty: '__PRERENDER_INJECTED',
          inject: {
            prerender: true
          },
          // 这个是监听 document.dispatchEvent 事件,决定什么时候开始预渲染
          // document.dispatchEvent(new Event('render-event'))
          renderAfterDocumentEvent: 'custom-render-trigger',
        })
      })
    ]);
  }

  return config;
};
复制代码

create-react-app 配置已经 eject 的情况:

修改 config 文件夹下的 webpack.config.js ,参考代码如下:

plugins: [
  // 预渲染插件
  isEnvProduction && new PrerenderSpaPlugin({
    staticDir: path.join(__dirname, '../build'),
    routes: ['/'],
    renderer: new PrerenderSpaPlugin.PuppeteerRenderer({
      injectProperty: '__PRERENDER_INJECTED',
      inject: {
        prerender: true
      },
      renderAfterDocumentEvent: 'custom-render-trigger',
    })
  }),
  ...
]
复制代码

prerender-spa-plugin 详细配置参考 官方文档

页面中使用方案推荐

纯静态页面,无接口数据情况:

在首页 react 组件的 didMount 事件中调用 document.dispatchEvent(new Event('custom-render-trigger'))

非静态页面,有接口数据情况:

方案一:

修改入口文件 index.js,

//判断是否是预渲染环境
if(window.__PRERENDER_INJECTED && window.__PRERENDER_INJECTED.prerender){
  // loading 组件
  import('./skeleton/index.js');
}else{
  // 原先的入口文件
  import('./page.js');
}
复制代码

skeleton/index.js 将骨架组件或者 loading 组件输出到 index.html,参考代码如下:

// 创建loading容器
const container = document.createElement("div");
container.className = 'prerender-loading';
document.body.appendChild(container);

// 渲染骨架组件或者 loading 组件
ReactDOM.render(
  <div style={{padding: '16px'}}>
    <Skeleton/>
  </div>, 
container);
复制代码

在首页组件中,当数据加载完成后,调用:

// 移除 loading 或者骨架组件
document.querySelector('.prerender-loading').remove();
// 展示首页
...
复制代码

方案二:

首页数据未加载前,静态部分显示,动态部分显示骨架组件,参考代码如下:

export default function Index() {
  const [data, setData] = useState(null)

  useMount(() => {
    document.dispatchEvent(new Event('custom-render-trigger'));
  });

  // 模拟getdata
  useTimeout(() => {
    setData({...});
  }, 200)

  return (
    <div className='Index'>
      <div>静态ui</div>
      {
        data === null
        ? <Skeleton>骨架ui</Skeleton> 
        : <div>动态数据ui</div>
      }
    </div>
  )
}
复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

C语言从入门到精通

C语言从入门到精通

王娣//韩旭 / 清华大学 / 2010-7 / 49.80元

《C语言从入门到精通》从初学者的角度出发,以通俗易懂的语言,丰富多彩的实例,详细介绍了使用C语言进行程序开发应该掌握的各方面知识。全书共分17章,包括C语言概述,算法,数据类型,运算符与表达式,常用的数据输入、输出函数,选择结构程序设计,循环控制,数组,函数,指针,结构体和共用体,位运算,预处理,文件,存储管理,网络套接字编程和学生成绩管理系统等。所有知识都结合具体实例进行介绍,涉及的程序代码给出......一起来看看 《C语言从入门到精通》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

URL 编码/解码
URL 编码/解码

URL 编码/解码

SHA 加密
SHA 加密

SHA 加密工具