博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
首屏预渲染方案
阅读量:7119 次
发布时间:2019-06-28

本文共 2816 字,大约阅读时间需要 9 分钟。

该方案主要是为了解决,前端 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(  
, 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 (    
静态ui
{ data === null ?
骨架ui
:
动态数据ui
}
)}复制代码

转载地址:http://mesel.baihongyu.com/

你可能感兴趣的文章
javascript中的链表结构—双向链表
查看>>
POJ 2586 Y2K Accounting Bug(枚举大水题)
查看>>
java高级工程师(二)
查看>>
NavMesh动态碰撞
查看>>
asp.net core中的razor页面
查看>>
JS获取子节点、父节点和兄弟节点的方法实例总结
查看>>
Design Your Own Protocol In Five Minutes
查看>>
[Debug] Diagnose a Slow Page Using Developer Tools
查看>>
7 个最好的.Net开源CMS系统
查看>>
[转]xna 3.1 to xna 4.0
查看>>
[转]Android SurfaceView 绘图覆盖刷新及脏矩形刷新方法
查看>>
NYOJ-305 表达式求值
查看>>
hdu 4427 Math Magic
查看>>
linux内核--内存管理(二)
查看>>
原生andriod浏览器回退后dom(click)事件全体失效问题探究
查看>>
IPHONE 开发 1 -- 体系介绍
查看>>
邮箱验证
查看>>
python小知识
查看>>
用位运算求一个数的绝对值
查看>>
settimeout vs setinternal
查看>>