前端如何处理首屏优化问题

用户普遍反馈项目首屏加载比较满,所以我做了完整的一次性能分析,定位到几个关键的瓶颈;

1.问题主要在js bundle体积过大(3.2mb) 和首屏并发请求过多(12个);

2.bundle问题做了代码分割和懒加载,路由改成动态的import、三方库按需引入。

针对接口就是梳理了下数据依赖,把12个借口合并成2个关键接口。

所以首屏加载时间从4.2秒优化到1.8秒,fcp指标提升了60%,效果显著

如何分析出的这些瓶颈的?

1.performance:

浏览器吧检查调出来有一个performance那一栏,点击录制,然后操作页面,再stop停止录制,就会出现一个火焰图。

发现主线程被大量的js解析任务阻塞(黄色部分占据很大一个比例),同时用Lighthouse跑分,量化出FCP和LCP指标确实比较低。

2.构建分析:

用webpack-buldle-analyzer对打包产物进行可视化分析,一下就可以看出moment.js这种库占了韩大的体积,就改用更轻量的days.js

使用:yarn add --dev webpack-bundle-analyzer

通过 Webpack 配置插件(推荐)

在你的 webpack.config.js(或者 webpack.prod.js等构建配置文件)中引入并使用该插件:

示例代码:

const BundleAnalyzerPlugin =

require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {

// ...你的其他 webpack 配置

plugins: [ // 添加这个插件(不传参数默认会在构建后自动打开分析页面)

new BundleAnalyzerPlugin()

] };

🧠 如何操作:

  • ∙ 运行 webpack 构建后,​​该插件会启动一个本地 HTTP 服务器(通常是 http://localhost:8888)​

  • ∙ 然后​​自动打开浏览器​​,展示打包结果的可视化分析页面

  • ∙ 页面中以​​矩形树图(Treemap)的形式展示各个模块的大小与依赖关系​

如何解决细节

组件方面:

对于一些体积比较大,但是不是一进入页面理解展示的组件 通过动态import()方式进行分割;

代码分离

配置方面:

在webpack配置层面,使用了splitChunks,将常用的第三方库和公共模块抽离成独立的chunk,以便浏览器长期缓存'

将代码分离到不同的bundle中,之后我们可以按需加载,或者并行加载这些文件

默认情况下,所有的JavaScript代码(业务代码、第三方依赖、暂时没有用到的模块)在首页全部都加载,就会影响首页的加载速度

代码分离可以分出出更小的bundle,以及控制资源加载优先级,提供代码的加载性能

这里通过splitChunksPlugin来实现,该插件webpack已经默认安装和集成,只需要配置即可

默认配置中,chunks仅仅针对于异步(async)请求,我们可以设置为initial或者all

复制代码
module.exports = {
    ...
    optimization:{
        splitChunks:{
            chunks:"all"
        }
    }
}

splitChunks主要属性有如下:

  • Chunks,对同步代码还是异步代码进行处理
  • minSize: 拆分包的大小, 至少为minSize,如何包的大小不超过minSize,这个包不会拆分
  • maxSize: 将大于maxSize的包,拆分为不小于minSize的包
  • minChunks:被引入的次数,默认是1

如何保证代码分割后的用户体验

1.我加了一个loading等待的效果,缓解用户的等待焦虑;或者suspense的fallback设计一个骨架屏

import React, { Suspense, lazy } from 'react';

// 动态导入组件 => 会生成单独的 chunk

const HomePage = lazy(() => import('./pages/HomePage'));

function App() {

return (

<Suspense fallback={<div>🌀 页面加载中,请稍候...</div>}>

<HomePage />

</Suspense>

);

}

2.我还弄了一个预加载,就是在用户鼠标hover导航菜单时候,以前与加载对应页面的chunk,让页面条环更快

实现思路:

  • ∙ 不是直接调用 import('./Page')(这会立即加载),而是将动态导入函数保存下来,在 hover 事件里 ​​手动调用它​​。

  • ∙ React.lazy 的 import()是自动执行的,所以我们需要 ​​自行封装动态 import,以拿到 Promise 函数​​,实现"按需手动触发"。

// 不使用 React.lazy,而是自己封装动态加载函数

const getHomePage = () => import('./pages/HomePage');

// 在导航菜单 hover 时预加载

function Navigation() {

const handleMouseEnter = () => {

// hover 时触发 chunk 加载

getHomePage(); // 这里会开始下载对应 chunk

};

return (

<nav>

<span onMouseEnter={handleMouseEnter}>首页</span>

</nav>

);

}

// 真正渲染组件时仍然用 React.lazy + Suspense

const HomePage = React.lazy(getHomePage);

function App() {

return (

<Suspense fallback={<div>加载中...</div>}>

<HomePage />

</Suspense>

);

}

3.用错误边界包裹了动态加载的组件,这样即使整个chunk因为网络问题加载失败,整个应用也不会白屏,给他展示一个toast提示。

除了这些 还有什么其他可以首屏优化的,协同团队做了基础设施层的优化;

1.将所有静态资源部书到cdn的边缘节点,开启http/2协议和gzip压缩

2.和后端同学一起,为核心api增加额redis缓存,并对曼查询的数据库表增加了索引,给接口响应时间从800ms降低到200ms

3。建立监控体系:部署了前端性能监控系统,能够持续追踪core web vitals等核心指标,让优化不再是一次性行为,而是一个长期迭代的体系

相关推荐
goto_w39 分钟前
前端实现复杂的Excel导出
前端·excel
Baklib梅梅1 小时前
2025文档管理软件推荐:效率、安全与协作全解析
前端·ruby on rails·前端框架·ruby
卷Java1 小时前
小程序前端功能更新说明
java·前端·spring boot·微信小程序·小程序·uni-app
FogLetter1 小时前
前端性能救星:虚拟列表原理与实现,让你的10万条数据流畅如丝!
前端·性能优化
我是天龙_绍1 小时前
前端驼峰,后端下划线,问:如何统一?
前端
知识分享小能手1 小时前
微信小程序入门学习教程,从入门到精通,微信小程序常用API(下)——知识点详解 + 案例实战(5)
前端·javascript·学习·微信小程序·小程序·vue·前端开发
code_YuJun1 小时前
nginx 配置相关
前端·nginx
对不起初见3 小时前
PlantUML 完整教程:从入门到精通
前端·后端
东方掌管牛马的神3 小时前
oh-my-zsh 配置与使用技巧
前端