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

前言

前端性能优化有多重要?试想如果一个网页要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。你还可以使用服务器推送技术,提前得到使用的资源。

最后

不同场景可能会有不同方案,有什么不足之处欢迎大神指正,小白也在不断学习实践中 [手动抱拳][手动抱拳]
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353

推荐阅读更多精彩内容