从实际项目去优化前端性能

前言

前端性能优化有多重要?试想如果一个网页要5秒才打开,你会等吗?提高前端性能才能保证用户体验和留存率。该篇文章会从项目的代码、打包、http层面谈谈前端优化方案。

准备

下面我将用自己的笔记本项目做例子,去优化前端性能。(PS:前端用React+Antd,对比都是没有使用浏览器缓存的情况下做的


开发角度

1. 资源压缩

在项目中使用图片、gif等资源前,应该先进行压缩,这里推荐一个图片压缩网站Tinypng

压缩前.png

压缩后.png

这里只用了少量资源比较,资源多的话可以节省不少带宽。


2. 图片渐进加载

先加载一张较小的图片,等大图加载完毕再进行替换,替换的时候用transition将小图慢慢过渡为透明。

    // 组件加载完毕执行
    const loadBg = () => {
        const img = new Image()
        img.src = require('@assets/img/bg.png') // 大图
        img.onload = () => {
            setBgImg(img.src)
        }
    }
 
    return(
       <div
           className={styles.bgImgs}
           style={{
                backgroundImage: `url(${bgImg})`
           }}
        >
            <img
                src={require('@assets/img/bg-small.png')}  // 小图
                style={{
                    opacity: Number(!bgImg)
                }}
            />
            <div className={styles.bgImgsMask} />
       </div>
    )

3. 代码分割

react lazy 文档react-loadable,通过代码分割,只加载当前路由的资源,其他路由的资源等待跳转到对应路由再加载。

const Home = lazy(() => import(/* webpackChunkName: "Home" */ '@views/Home'))
const Login = lazy(() => import(/* webpackChunkName: "Login" */ '@views/Login'))
const NotFound = lazy(() => import(/* webpackChunkName: "NotFound" */ '@views/NotFound'))
const ShareArticle = lazy(() => import(/* webpackChunkName: "ShareArticle" */ '@views/ShareArticle'))
   <Suspense fallback={<PageLoading Icon={<img src={require('@assets/gifs/loading-pen.gif')} />} />}>
         <Switch>
            <Route path="/login" exact={true}>
                 <Login />
            </Route>
            <Route path="/share-article">
                 <ShareArticle />
            </Route>
            <Route path="/" exact={true}>
                 <Home />
            </Route>
            <Route>
                 <NotFound />
            </Route>
        </Switch>
   </Suspense>
分割前.png
分割后.png
可以看到资源大小小了很多,这是登录页面,只包含Login的资源和antd Button的资源。

4. 使用iconfont的在线图标资源

不需要下载到本地,用script标签引用资源,整理图标方便,存在哪些图标一目了然,避免图标重复出现,而且提高打包速度和包大小。

5. Antd按需加载
文档
6. 开发注意事项
  • 通用代码封装成组件、尽量细分解耦。
  • 长列表可以选择用react-virtualized方案。
  • 组件之间不传没用的参数,考虑好是否需要用展开符。
  • shouldComponentUpdate避免重复渲染。
  • 不可变传参,应该先定义好变量,再将变量传给组件。

打包角度

1. 资源压缩

通过css-minimizer-webpack-plugin压缩css资源。
通过terser-webpack-plugin压缩js资源,webpack5自带。

2. 防止js阻塞页面渲染

    // js插入到body,或者使用defer
    new HtmlWebpackPlugin({
        template: 'build/tpl/index.html',
        inject:'body',
        scriptLoading:'defer'
    })

3. 分包

因为之前用了lazy异步加载 ,webpack会自动对这些组件分包。然后下面我将一些公共的单独打出来,减少包的体积。

    splitChunks: {
        chunks: 'all',
        cacheGroups: {
            // 禁用默认缓存
            default: false,
            vendor: {
                name: 'vendor',
                // 包含同步和异步
                chunks: 'all',
                // 最少被引用两次
                minChunks: 2,
                // 优先级
                priority: 10,
                // 最小大小
                minSize: 0,
                test: /[\\/]node_modules[\\/]/
            },
            reactBase: {
                name: 'reactBase',
                test: /[\\/]node_modules[\\/](react|react-dom|react-router-dom)[\\/]/,
                priority: 11,
                minChunks: 1,
                minSize: 0
            },
            mobxBase: {
                name: 'mobxBase',
                test: /[\\/]node_modules[\\/](mobx|mobx-react|mobx-react-router)[\\/]/,
                priority: 12,
                minChunks: 1,
                minSize: 0
            },
            lodash: {
                name: 'lodash',
                test: /[\\/]node_modules[\\/](lodash)[\\/]/,
                priority: 13,
                minChunks: 1,
                minSize: 0
            }
        }
    }

4. 图片内联到html中

url-loader配置小于指定大小的图片资源通过Data URL方式内联到html中。


http角度

1. 开启gzip压缩,开启后请求资源体积小了36%。
nginx-config.png
2. 使用CDN缓存,我用的是七牛的CDN设置了30天有效期,发版本的话可以调用接口刷新缓存。
3. 使用http2的多路复用技术,时间从3.5s提高到1.7s。你还可以使用服务器推送技术,提前得到使用的资源。

最后

不同场景可能会有不同方案,有什么不足之处欢迎大神指正,小白也在不断学习实践中 [手动抱拳][手动抱拳]
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容