React项目加载性能优化

版权声明: https://blog.csdn.net/huangpb123/article/details/81490046

一、了解页面加载过程

1. 打开页面

    这个时候页面是完全空白的。

2. 首屏渲染

    Html 和引用的 Css 加载完毕,浏览器进行首次渲染,有可见的内容出现。

    我们把首次渲染需要加载的资源体积称为“首屏体积”。

3. 首次内容渲染

    react、  react-dom、业务代码加载完毕,应用第一次渲染,页面主要内容出现。

4. 可交互

    然后应用的代码开始执行,拉取数据、进行动态 import、响应事件等,完毕后页面进入可交互状态。

5. 内容加载完毕

    接下来 lazyload 的图片等多媒体内容开始逐渐加载完毕。

6. 页面加载完毕

    然后直到页面的其他资源加载完毕。

接下来,我们分别讨论这些步骤中,有哪些优化的点。

二、首屏渲染优化

React 项目中的 Html 都会提供一个 root 节点

<div id='root'></div>

我们可以在这个 root 节点中加点内容,使第一步打开页面时的空白时间尽可能减少(页面崩溃也会显示这些内容)。

我们可以使用 html-webpack-plugin 自动给 root 节点插入内容。

// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const fs = require('fs');

// 读取要自动插入root节点的 html 和 css
var loading = {
    html: fs.readFileSync(path.join(__dirname, './src/components/loading/index.html')),
    css: '<style>' + fs.readFileSync(path.join(__dirname, './src/components/loading/index.css')) + '</style>'
}

module.exports = {
    ...
    plugins: [
        new HtmlWebpackPlugin({
            favicon: path.resolve(config.srcPath, 'favicon.ico'),
            inject: 'body',
            template: path.join(config.srcPath, 'index.tmpl.html'),
            loading
        }),
    ]
}

然后在模板中引用即可:

// html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <%= htmlWebpackPlugin.options.loading.css %>
</head>
<body>
    <div id="root">
        <%= htmlWebpackPlugin.options.loading.html %>
    </div>
</body>
</html>

三、首次内容渲染优化

使用 react-loadable 动态 import React 组件,让首次加载时只加载当前路由匹配的组件。

import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Loadable from 'react-loadable'
import Loading from './components/loading'

let Home = Loadable({
    loader: () => import('@/pages/home'),
    loading: Loading
})
let User = Loadable({
    loader: () => import('@/pages/user'),
    loading: Loading
})
let Others = Loadable({
    loader: () => import('@/pages/others'),
    loading: Loading
})

export default class RootRouter extends React.Component {
    render() {
        return (
            <Router>
                <Switch>
                    <Route exact path="/" component={Home}/>
                    <Route path="/user" component={User}/>
                    <Route path="/others" component={Others}/>
                    <Route component={Home}/>
                </Switch>
            </Router>
        )
    }
}

上面代码在首次加载时,会先展示一个 Loading,等到页面组件代码加载完毕后,便会替换掉 Loading。

四、编译到 ES2015+

把 ES2015+ 的代码编译成 ES5,体积会增大好几倍,运行速率也会减慢。在当下2018年,大部分现代浏览器已经支持 ES6 语法。我们要做的,就是把代码编译到 ES2015+,然后给少数的老旧浏览器留一份 ES5 的代码即可。

具体的做法就是使用 <script type="module"> 标签。

支持这个标签的浏览器必然支持 async/await, Promise, Class, 箭头函数, Map/Set, fetch 等等。

<script type="module" src="main.js"></script>
<script type="nomodule" src="main.es5.js"></script>

现代主流浏览器能识别 type="module",就加载第一条 ES2015+ 的代码。老旧浏览器不能识别 type="module" 和 type="nomodule",就会加载第二条 ES5 的代码。

五、Placeholder

我们在加载文字、图片的时候,经常出现“闪屏”的情况,比如文字或者图片还没有加载完毕,此时页面上对应的位置还是完全空着的,然后加载完毕,内容会突然撑开页面,导致“闪屏”的出现,造成不好的用户体验。

为了避免这种“闪屏”的情况,我们要做的就是提前设置占位元素,也就是 placeholder。已经有一些现成的第三方组件可以用了。

 

猜你喜欢

转载自blog.csdn.net/huangpb123/article/details/81490046