欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

前端性能优化

程序员文章站 2022-05-14 13:08:54
...

在前端开发过程中,发现APP会有很多方面的性能需要注意,例如:

  • APP卡顿
  • 网络慢
  • APP加载慢
    以下是一些具体的实践经验。
    性能优化分为两个方面:一个是加快静态资源的加载,一个是提高页面渲染的速度。

页面渲染性能优化

  • 减少DOM层级,在写DOM的时候没必要的层级可以不要加。
  • 不需要阴影的地方,不要加阴影。
  • 使用chrome的performance分析,分析原因。

静态资源加载优化

资源压缩

页面的资源包括js、css、images等等,这些文件尽可能压缩

使用 tree-shaking、scope hoisting、code-splitting

  • tree-shaking
    移除无用代码,只加载实际使用了的代码。
  • scope hoisting
    作用域提升,允许工具检测哪些 import 可以被提升或者可以转换成一个内联函数。
  • Code-splitting
    将代码分为按需加载的“块”。

缓存

HTTP缓存:如果有HTTP缓存,并且缓存没有失效,浏览器会直接使用缓存;反之,则向服务器请求数据。

强制缓存:

  • Expires,这个字段表示缓存到期时间。如果在响应消息头中设置了这个字段,就告知了浏览器在没到这个时间之前不需要再次请求。
  • Cache-Control,这个字段表示缓存的最大有效时间,在这个时间内客户端不需要向服务器发送请求。

对比缓存:

  • Last-Modified:服务器告知客户端,资源最后一次被修改的时间。
  • If-Modified-Since:再次发送请求时,请求头中带有该字段,服务器会将If-Modified-Since的值与Last-Modified字段进行对比,如果相等,则表示未修改,响应304;反之,则表示修改了,响应200状态码,返回数据。

推荐的用法:

  • Etag:它存储的是文件的特殊标识(一般都是hash生成的),服务器存储着文件的Etag字段,可以在与每次客户端传送If-no-match的字段进行比较,如果相等,则表示未修改,响应304;反之,则表示已修改,响应200状态码,返回数据。

使用lazyload&preload

为了提高页面的加载速度,我们期望的是按需加载,也就是说只加载当前的页面,别的页面不会一起被加载进来,免得阻碍了当前页面的加载。这就是懒加载,也被称为延迟加载,延迟相关资源的加载。
当首页加载完毕后,预判用户行为,提前加载之后的页面,也会提高用户的体验。这就是预加载。

实践中的一些例子

APP卡顿的时候,多次点击触发事件的处理

当APP卡顿时,如果多次点击一个button,刚好这个button会打开下一页,那么就会看到打开了很多页的动画效果。为了防止这种情况,考虑了很多做法。

  1. debounce
    加上一个Directive,监听click事件,在某个时间段内,多次点击,只触发一次操作。
import { Directive, EventEmitter, HostListener, OnInit, Output } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { debounceTime } from 'rxjs/operators';

@Directive({
  selector: '[appDebounceClick]'
})
export class DebounceClickDirective implements OnInit {
  @Output() debounceClick = new EventEmitter();
  private clicks = new Subject();

  constructor() {}

  ngOnInit() {
    this.clicks.pipe(debounceTime(4000)).subscribe(e => this.debounceClick.emit(e));
  }

  @HostListener('click', ['$event'])
  clickEvent(event) {
    event.preventDefault();
    event.stopPropagation();
    this.clicks.next(event);
  }
}

component的html:

 <button appDebounceClick (debounceClick)="log()">Debounced Click</button>

component的ts文件

public log() {
// do some thing
  }

具体做法参考:
https://coryrylan.com/blog/creating-a-custom-debounce-click-directive-in-angular

  1. disable button
    其实就是在button触发事件后,通过disable属性来控制接下来的事件是否生效,这个需要注意button disabled样式可能会发生变化,并且要在合适的时机来控制该button的disable。如果对于APP中全部button都做这个控制的话,可以抽一个Button component,并加上disable控制。
  2. disable event
    目前的APP中,主要遇上的问题是多次点击button跳转页面时,会打开多个页面,又不想改变button的样式,所以在button触发的页面跳转时,加上一个flag,判断是否跳转,在跳转后的callback方法里重置该flag。
    具体做法其实就是,创建一个service,里面有一个flag属性和跳转方法。跳转方法中,在页面跳转前,先判断一下该flag是否可以跳转,如果可以,进行跳转事件,并且在callback方法里面重置flag。因为这个是针对于某一个页面的跳转事件,所以这个service应该inject到每一个用到的page。
    4.更好的办法,继续探索中。。。

参考
前端性能优化清单
谈谈关于前端的缓存的问题
浏览器缓存