woodpecker 性能

检查运行时性能

检查pecker.oa.com, Performance 和 Memory面板

运行时性能未发现明显问题

在页面上点击交互, 切换路由, 查询, 内存占用平稳. 检查Memory标签未发现明显内存泄漏问题.
图中上方帧数降低主要出现在在页面触发submit事件后大规模重新计算样式与重排时.

运行时性能还不错, 主要优化方向集中在打包, 加载与网络优化.

文件加载优化

目前打包size图

来看这个图, 可以看到chunk.js 在 gziped 后单文件太大, 占了 1.2Mb. 三五百kb的大小应该比较合理.

最左侧的antd必须引入. 而图中间一列, recharts和highcharts也占了不小的空间, moment的国际化也占了不小.

大js带来的问题是下载单文件与解析会变慢, 见图:


通过Lighthouse的测试, FCP 略慢 (超过2s). 上图说明此文件在本机上的执行所用CPU时间占了1.2秒. 应缩减此js文件大小.

目前应该先不用太在意Skipping Effects: 指 React.memo, useEffect, PureComponent, shouldComponentUpdate, redux 这种运行时性能优化.

当前打包出来的大 js-bundle, 没有做代码拆分, 初次打开得等下载解析完才会加载出页面, 比较影响性能。

考虑使用 React.lazy + Suspense

React.lazy方法是内置的code-splitting工具, 可以像渲染一个普通组件那样去渲染一个动态引入组件. 可以方便地将独立的组件分离为单独的js-chunk.

// 修改前
import OtherComponent from './OtherComponent';
// 修改后
const OtherComponent = React.lazy(() => import('./OtherComponent'));

第一次渲染这个组件时, 这个方法将自动加载包含OtherComponent的js-bundle, React.lazy结合动态import相应的js会被webpack拆分, 在使用时才加载. React.lazy接受个函数, 函数中必须调用一个动态import(), 动态import()会返回一个Promise, 这个Promis会"resolve"出一个export default React组件的 module.

这种用 lazy() 加载的组件, 可以渲染在Suspense组件中, 通过fallback属性, 可以方便的去管理它loading时, 以及加载失败时要展示的组件:

import React, { Suspense } from 'react';

const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    
Loading...
}>
); }

因此大概从下面三个方向进行动态 import

1. 路由懒加载

老生常谈的路由懒加载. 在项目中的路由部分使用lazy也比较合理, 因为浏览传统网站的逻辑就是点击链接时要等待一定时间来加载. 下方是一个例子.

import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));

const App = () => (
  
    Loading...
}> );

另一个例子

function lazyload(loader: () => Promise<{ default: React.ComponentType }>) {
  const LazyComponent = React.lazy(loader)
  const Lazyload: React.FC = (props: any) => {
    return (
      }>
        
      
    )
  }
  return Lazyload
}

const Login = lazyload(() => import('src/pages/Home'))

不过现在有一个问题, 我们用的路由是 rsf 中的 ConfigRouters, 其中的Route组件中的属性值是用变量使用的, 但动态import不允许使用变量.

2. React 组件懒加载

使用这几个工具可以更轻松地从组件层面对进行代码进行拆分.
下面是一个使用了 React.lazy 但没用 Suspense 的例子

import React, { lazy } from 'react';

const AvatarComponent = lazy(() => import('./AvatarComponent'));

const DetailsComponent = () => (
  
)

这里有个将React.lazySuspense结合起来的演示: react-lazy-suspense, 打开开发者工具可以看到, 当点了 Click Me 按钮后, 会加载要展示组件单独的js文件.

目前的想法是将 CommonPage 组件中, 除了QueryForm, 下方查询的 Container 部分用这种方法处理.

3. 第三方库与本地文件懒加载

对于某些引入的不太常用的第三方js, 可用import()在用到时动态加载

async function encrypt(value: string): Promise {
  // 改为 import() 的方式引入第三方库
  const module = await import('jsencript')
  // expor default 导出的模块
  const JSEncrypt = module.default
  // 配合引入的 JSEncrypt 加密
  const encrypt = new JSEncrypt()
  encrypt.setPublicKey(PUBLIC_KEY)
  const encrypted = encrypt.encrypt(value)
  return encrypted
}

这可以用来懒加载项目中的 JSON 文件等,通过 import() 方式懒加载的代码或者 JSON 文件,同样会经过 webpack 处理, 例如项目中用到了存储展示状态的大号JSON文件, 就可以像这样动态导入:

const module = await import('./errorStatus.json')
console.log(module.default)

项目中用到的high-chartrecharts, 应该是比较适用于这种处理方式, 但这种已经被封装在shared-component中的该如何懒加载? 这俩第三方库占的空间不小了, 懒加载对于提升首屏加载速度应该效果明显.

参考链接:
react code splitting
reactlazy官方文档

http/2

服务器目前在用http/1.1, 启用 http/2 应该会加快多个请求资源的速度. 不过现在查询接口较慢, 查询条件又比较灵活, 接口侧不太容易做优化. 配置方式:

Nginx

server {
    listen 443 http2;
    server_name xxx.xxx;
}

moment优化

我们可能不需要加载整个moments, 比如moment/locale/*.js中的国际化文件, 除了英语和zh-cn可以都不要
可以借助webpack.ignorePlugin排除.

new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),

Webpack官网此插件的介绍就是用moment举例的: Webpack-ignore-plugin

lodash优化

其实lodash占得空间并不大, 优化后减小文件效果应该不会很明显, 稍微带过.
保证引入时为

import debounce from 'lodash/debounce'

而不是

import lodash from 'lodash'
// 或者
import { debounce } from 'lodash'

即可.

image.png
image.png
image.png
image.png

你可能感兴趣的:(woodpecker 性能)