Angular 10渲染千条数据时FontAwesome图标导致页面加载慢
问题根因
该性能问题和FontAwesome字体文件是否命中缓存无关:使用web字体+CSS类的方式渲染图标时,浏览器需要为每一个<i class="fas fa-chevron-circle-down"></i>节点执行字体字形匹配、样式计算、布局重排操作,1000+个循环生成的图标节点会将这部分渲染开销线性放大,直接拖慢页面加载渲染速度。
可行方案(按性能收益从高到低排序)
方案1:替换为内联SVG图标(性能最优,视觉效果完全一致)
放弃web字体渲染模式,改用内联SVG渲染图标,不存在字体匹配开销,渲染速度和普通DOM元素无差异:- 提取
fa-chevron-circle-down对应的SVG源码,在页面模板中只声明一次SVG符号定义,放在模板最顶部即可,无需重复编写全量SVG代码:
<svg style="display: none;"> <symbol id="fa-chevron-circle-down" viewBox="0 0 512 512"> <path fill="currentColor" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm121.6 313.1c4.7 4.7 4.7 12.3 0 17l-22.6 22.6c-4.7 4.7-12.3 4.7-17 0L256 279l-82 81.9c-4.7 4.7-12.3 4.7-17 0l-22.6-22.6c-4.7-4.7-4.7-12.3 0-17l113-113.1c4.7-4.7 12.3-4.7 17 0l113.2 113z"/> </symbol> </svg>- 在*ngFor循环的行模板中,直接引用该符号即可,单节点渲染开销极低:
<svg class="icon-chevron" width="16" height="16"> <use href="#fa-chevron-circle-down"></use> </svg>- 配套少量CSS控制图标尺寸、颜色,和原有FontAwesome图标视觉效果完全一致,千条数据下渲染速度比字体图标快80%以上。注意只提取业务实际用到的图标即可,不要引入全量SVG图标包,避免增加打包体积。
- 提取
方案2:接入虚拟滚动(无需修改现有图标逻辑,收益显著)
如果不想替换现有图标引入方式,可通过虚拟滚动只渲染视口可见范围内的行,从根源上减少同时渲染的DOM(含图标)节点总数:- 安装与Angular 10版本匹配的CDK依赖:
npm install @angular/cdk@10.x- 在业务模块中导入
ScrollingModule - 将原有*ngFor循环容器替换为虚拟滚动容器,配置固定行高、容器高度:
<cdk-virtual-scroll-viewport itemSize="48" class="list-viewport" style="height: 600px;"> <div *cdkVirtualFor="let row of dataList" class="list-row"> <!-- 原有行内容无需修改,保留原来的FontAwesome图标标签即可 --> <i class="fas fa-chevron-circle-down"></i> </div> </cdk-virtual-scroll-viewport>该方案下无论总数据量是1000条还是更多,同时渲染的DOM节点仅为视口内的十几到几十个,图标渲染开销可以忽略。注意不要在*ngFor(包括cdkVirtualFor)中使用
@fortawesome/angular-fontawesome的图标组件,该组件在Angular 10版本下会为每个图标生成额外的组件实例开销,渲染速度比纯CSS类字体图标更慢。方案3:CSS渲染优化(改动最小,仅作临时过渡)
如果既不想替换SVG也不想接入虚拟滚动,可以通过CSS给图标节点开启渲染优化,减少重排开销:.fas { contain: layout paint; transform: translateZ(0); text-rendering: optimizeSpeed; }该方案收益有限,千条数据下仍会存在可感知的渲染延迟,仅适合临时应急使用。
内容的提问来源于stack exchange,提问作者Sid
相关产品推荐
相关产品推荐

