Rumah >hujung hadapan web >tutorial js >Bagaimanakah Angular mengoptimumkan? Analisis ringkas penyelesaian pengoptimuman prestasi

Bagaimanakah Angular mengoptimumkan? Analisis ringkas penyelesaian pengoptimuman prestasi

青灯夜游
青灯夜游ke hadapan
2021-10-11 09:55:472649semak imbas

Bagaimana untuk mengoptimumkan Angular? Artikel berikut akan memberitahu anda tentang pengoptimuman prestasi dalam Angular saya harap ia akan membantu anda!

Bagaimanakah Angular mengoptimumkan? Analisis ringkas penyelesaian pengoptimuman prestasi

Artikel ini akan membincangkan tentang pengoptimuman prestasi Angular, dan terutamanya memperkenalkan pengoptimuman yang berkaitan dengan masa jalan. Sebelum bercakap tentang cara mengoptimumkan, pertama sekali kita perlu menjelaskan jenis halaman yang mempunyai masalah prestasi? Apakah ukuran prestasi yang baik? Apakah prinsip di sebalik pengoptimuman prestasi? Jika soalan ini menarik minat anda, sila baca. [Cadangan tutorial berkaitan: "tutorial sudut"]

Bagaimanakah Angular mengoptimumkan? Analisis ringkas penyelesaian pengoptimuman prestasi

Tukar mekanisme pengesanan

Berbeza daripada pengoptimuman penghantaran rangkaian, pengoptimuman masa jalan lebih menumpukan pada mekanisme pengendalian Angular dan cara membuat kod untuk mengelakkan masalah prestasi (amalan terbaik) dengan berkesan. Untuk memahami mekanisme pengendalian Angular, anda perlu terlebih dahulu memahami mekanisme pengesanan perubahannya (juga dikenali sebagai semakan kotor) - cara untuk memaparkan semula perubahan keadaan ke dalam paparan. Cara menggambarkan perubahan dalam status komponen pada paparan juga merupakan masalah yang perlu diselesaikan oleh ketiga-tiga rangka kerja hadapan. Penyelesaian daripada rangka kerja yang berbeza mempunyai idea yang sama tetapi juga mempunyai ciri tersendiri.

Pertama sekali, kedua-dua Vue dan React menggunakan DOM maya untuk melaksanakan kemas kini paparan, tetapi masih terdapat perbezaan dalam pelaksanaan khusus:

Untuk React:

  • Dengan menggunakan setState atau forceUpdate untuk mencetuskan kaedah render untuk mengemas kini paparan

  • Apabila komponen induk mengemas kini paparan, ia juga akan menentukan sama ada re-render komponen anak

Untuk Vue:

  • Vue akan merentasi semua sifat objek

    dan menggunakan data. untuk menukar semua sifat ini menjadi Object.defineProperty dan gettersetter

  • Setiap tika komponen mempunyai objek contoh

    yang sepadan, yang akan merekodkan sifat sebagai kebergantungan watcher

    semasa pemaparan komponen.
  • Apabila kebergantungan

    dipanggil, ia akan memberitahu setter untuk mengira semula, supaya komponen yang berkaitan boleh dikemas kini watcher

semasa Pas sudut Introduce Zone.js untuk menampal API operasi tak segerak dan memantau pencetusnya untuk pengesanan perubahan. Prinsip Zone.js diperkenalkan secara terperinci dalam artikel

sebelumnya . Ringkasnya, Zone.js merangkum dan menggantikan semua API tak segerak dalam penyemak imbas atau Node melalui tampalan Monyet.

Contohnya,

dalam penyemak imbas: setTimeout

let originalSetTimeout = window.setTimeout;

window.setTimeout = function(callback, delay) {
  return originalSetTimeout(Zone.current.wrap(callback),  delay);
}

Zone.prototype.wrap = function(callback) {
  // 获取当前的 Zone
  let capturedZone = this;

  return function() {
    return capturedZone.runGuarded(callback, this, arguments);
  };
};
atau

kaedah: Promise.then

let originalPromiseThen = Promise.prototype.then;

// NOTE: 这里做了简化,实际上 then 可以接受更多参数
Promise.prototype.then = function(callback) {
  // 获取当前的 Zone
  let capturedZone = Zone.current;
  
  function wrappedCallback() {
    return capturedZone.run(callback, this, arguments);
  };
  
  // 触发原来的回调在 capturedZone 中
  return originalPromiseThen.call(this, [wrappedCallback]);
};
Zone.js Semasa memuatkan, semua antara muka tak segerak Dikapsulkan . Oleh itu, semua kaedah tak segerak yang dilaksanakan dalam Zone.js akan dianggap sebagai Tugas dan diselia secara seragam olehnya, dan fungsi cangkuk yang sepadan (cangkuk) disediakan untuk melaksanakan beberapa operasi tambahan sebelum dan selepas pelaksanaan tugas tak segerak atau pada peringkat tertentu . Oleh itu, Zone.js boleh melaksanakan fungsi dengan mudah seperti pengelogan, memantau prestasi dan mengawal masa pelaksanaan panggilan balik tak segerak.

Fungsi cangkuk (cangkuk) ini boleh ditetapkan melalui kaedah

Untuk butiran, sila rujuk konfigurasi berikut: Zone.fork()

Zone.current.fork(zoneSpec) // zoneSpec 的类型是 ZoneSpec

// 只有 name 是必选项,其他可选
interface ZoneSpec {
  name: string; // zone 的名称,一般用于调试 Zones 时使用
  properties?: { [key: string]: any; } ; // zone 可以附加的一些数据,通过 Zone.get('key') 可以获取 
  onFork: Function; // 当 zone 被 forked,触发该函数
  onIntercept?: Function; // 对所有回调进行拦截
  onInvoke?: Function; // 当回调被调用时,触发该函数
  onHandleError?: Function; // 对异常进行统一处理
  onScheduleTask?: Function; // 当任务进行调度时,触发该函数
  onInvokeTask?: Function; // 当触发任务执行时,触发该函数
  onCancelTask?: Function; // 当任务被取消时,触发该函数
  onHasTask?: Function; // 通知任务队列的状态改变
}
Berikan contoh mudah

: onInvoke

let logZone = Zone.current.fork({ 
  name: 'logZone',
  onInvoke: function(parentZoneDelegate, currentZone, targetZone, delegate, applyThis, applyArgs, source) {
    console.log(targetZone.name, 'enter');
    parentZoneDelegate.invoke(targetZone, delegate, applyThis, applyArgs, source)
    console.log(targetZone.name, 'leave'); }
});

logZone.run(function myApp() {
    console.log(Zone.current.name, 'queue promise');
    Promise.resolve('OK').then((value) => {console.log(Zone.current.name, 'Promise', value)
  });
});
Hasil pelaksanaan akhir:

Bagaimanakah Angular mengoptimumkan? Analisis ringkas penyelesaian pengoptimuman prestasi

Selepas memahami prinsip Zone.js, dengan membaca kod sumber Angular, anda boleh mengetahui Zon itu .js digunakan dalam Sudut Untuk mencapainya apabila kaedah atau peristiwa tak segerak dipanggil, pengesanan perubahan akan dicetuskan. Kira-kira seperti berikut:

Pertama, dalam fail

applicatoin_ref.ts, apabila dibina, ia melanggan acara panggil balik bahawa baris gilir microtask kosong dan ia memanggil kaedah ApplicationRef ( iaitu pengesanan perubahan): tick

2-Bagaimanakah Angular mengoptimumkan? Analisis ringkas penyelesaian pengoptimuman prestasi

Kedua, dalam kaedah checkStable, ia akan dinilai bahawa acara onMicrotaskEmpty akan dicetuskan apabila baris gilir microtask dikosongkan (secara gabungan, ia bersamaan dengan mencetuskan pengesanan perubahan):

2-Bagaimanakah Angular mengoptimumkan? Analisis ringkas penyelesaian pengoptimuman prestasi

Akhir sekali, tempat yang boleh mencetuskan panggilan kaedah checkStable adalah dalam tiga fungsi cangkuk Zone.js, iaitu onInvoke , onInvokeTask dan onHasTask:

Bagaimanakah Angular mengoptimumkan? Analisis ringkas penyelesaian pengoptimuman prestasi

Contohnya, onHasTask - cangkuk dicetuskan apabila kehadiran atau ketiadaan ZoneTask dikesan :

Bagaimanakah Angular mengoptimumkan? Analisis ringkas penyelesaian pengoptimuman prestasi

Selain itu, tugas tak segerak dalam Zone.js dibahagikan kepada tiga kategori:

Tugas Mikro: dicipta oleh Promise dan lain-lain, native Promise akan dilaksanakan sebelum gelung acara semasa tamat dan Promise yang ditampal juga akan dilaksanakan sebelum gelung acara tamat.

Tugas Makro: dicipta oleh setTimeout dsb., dan native daripada setTimeout akan diproses pada masa akan datang.

Tugas Acara: dicipta oleh addEventListener dsb. task ini mungkin dicetuskan beberapa kali atau mungkin tidak pernah dicetuskan.

Malah, dari perspektif penyemak imbas, Tugas Acara sebenarnya boleh dianggap sebagai tugas makro Dalam erti kata lain, semua acara atau API tak segerak boleh difahami sebagai tugas makro atau mikro Salah satu daripadanya, dan perintah pelaksanaannya telah dianalisis secara terperinci dalam artikel sebelumnya Ringkasnya:

(1) Selepas utas utama dilaksanakan, mikropemproses akan diperiksa. pertama. Sama ada masih terdapat tugasan yang perlu dilaksanakan dalam baris gilir tugasan

(2) Selepas pengundian pertama selesai, ia akan menyemak sama ada masih terdapat tugasan untuk dilaksanakan dalam baris gilir tugasan makro. semak sama ada masih terdapat tugasan untuk dilaksanakan dalam senarai tugas mikro, dan kemudian Proses ini akan diulang

Prinsip Pengoptimuman Prestasi

Yang paling banyak cara intuitif untuk menilai prestasi halaman adalah untuk melihat sama ada respons halaman lancar dan responsif. Respons halaman pada asasnya ialah proses memaparkan semula perubahan keadaan halaman pada halaman Dari perspektif yang agak makro, pengesanan perubahan Angular sebenarnya hanya satu bahagian daripada keseluruhan kitaran tindak balas acara. Semua interaksi antara pengguna dan halaman dicetuskan melalui peristiwa dan keseluruhan proses respons adalah kira-kira seperti berikut:

Bagaimanakah Angular mengoptimumkan? Analisis ringkas penyelesaian pengoptimuman prestasi

Jika anda mempertimbangkan untuk mengoptimumkan kelajuan respons halaman, anda boleh mulakan daripada setiap peringkat:

(1) Untuk peringkat peristiwa pencetus, pencetusan peristiwa boleh dikurangkan untuk mengurangkan bilangan keseluruhan pengesanan perubahan dan pemaparan semula

(2) Untuk Acara Peringkat logik pelaksanaan pengendali, kod kompleks boleh dioptimumkan Logik untuk mengurangkan masa pelaksanaan

(3) Untuk pengikatan data pengesanan Perubahan dan peringkat pengemaskinian DOM, bilangan pengiraan data pengesanan dan templat perubahan boleh dikurangkan kepada kurangkan masa pemaparan

(4) Untuk Dalam fasa pemaparan penyemak imbas, anda mungkin perlu mempertimbangkan untuk menggunakan penyemak imbas lain atau menambah baik konfigurasi perkakasan

Kami tidak akan membincangkan terlalu banyak tentang pengoptimuman fasa kedua dan keempat di sini Digabungkan dengan Sudut yang disebutkan di atas untuk tak segerak Pengelasan tugas boleh diperjelaskan lagi untuk kaedah pengoptimuman peringkat pertama dan ketiga:

(1) Untuk permintaan penggabungan tugas Makro, cuba untuk kurangkan bilangan kutu

(2) Tandakan penggabungan tugas Mikro

(3) Kurangkan pencetus dan pendaftaran acara untuk tugasan Acara

(4) Tandakan ialah dibahagikan kepada dua fasa: semak dan render, mengurangkan pengiraan dan rendering yang tidak perlu dalam fasa semak

前面有提到,大多数情况通过观察页面是否流畅可以判断页面的是否存在性能问题。虽然这种方式简单、直观,但也相对主观,并非是通过精确的数字反映页面的性能到底如何。换言之,我们需要用一个更加有效、精确的指标来衡量什么样的页面才是具备良好性能的。而 Angular 官方也提供了相应的方案,可以通过开启 Angular 的调试工具,来实现对变更检测循环(完成的 tick)的时长监控。

首先,需要使用 Angular 提供的 enableDebugTools 方法,如下:

Bagaimanakah Angular mengoptimumkan? Analisis ringkas penyelesaian pengoptimuman prestasi

之后只需要在浏览器的控制台中输入 ng.profiler.timeChangeDetection() ,即可看到当前页面的平均变更检测时间:

Bagaimanakah Angular mengoptimumkan? Analisis ringkas penyelesaian pengoptimuman prestasi

从上面可以看出,执行了 692 次变更检测循环(完整的事件响应周期)的平均时间为 0.72 毫秒。如果多运行几次,你会发现每次运行的总次数是不一样、随机的。

官方提供了这样一个判断标准:理想情况下,分析器打印出的时长(单次变更检测循环的时间)应该远低于单个动画帧的时间(16 毫秒)。一般这个时长保持在 3 毫秒下,则说明当前页面的变更检测循环的性能是比较好的。如果超过了这个时长,则就可以结合 Angular 的变更检测机制分析一下是否存在重复的模板计算和变更检测。

性能优化方案

在理解 Angular 优化原理的基础上,我们就可以更有针对性地去进行相应的性能优化:

(1)针对异步任务 ——减少变更检测的次数

  • 使用 NgZone 的 runOutsideAngular 方法执行异步接口
  • 手动触发 Angular 的变更检测

(2)针对 Event Task —— 减少变更检测的次数

  • 将 input 之类的事件换成触发频率更低的事件
  • 对 input valueChanges 事件做的防抖动处理,并不能减少变更检测的次数

Bagaimanakah Angular mengoptimumkan? Analisis ringkas penyelesaian pengoptimuman prestasi

如上图,防抖动处理只是保证了代码逻辑不会重复运行,但是 valueChanges 的事件却随着 value 的改变而触发(改变几次,就触发几次),而只要有事件触发就会相应触发变更检测。

(3)使用 Pipe ——减少变更检测中的计算次数

  • 将 pipe 定义为 pure pipe(@Pipe 默认是 pure pipe,因此也可以不用显示地设置 pure: true

    import { Piep, PipeTransform } from '@angular/core';
    
    @Pipe({
      name: 'gender',
      pure,
    })
    export class GenderPiep implements PipeTransform {
      transform(value: string): string {
        if (value === 'M') return '男';
        if (value === 'W') return '女';
        return '';
      }
    }

关于  Pure/ImPure Pipe:

  • Pure Pipe: 如果传入 Pipe 的参数没有改变,则会直接返回之前一次的计算结果

  • ImPure Pipe: 每一次变更检测都会重新运行 Pipe 内部的逻辑并返回结果。(简单来说, ImPure Pipe 就等价于普通的 formattedFunction,如果一个页面触发了多次的变更检测,那么 ImPure Pipe 的逻辑就会执行多次)

(4)针对组件 ——减少不必要的变更检测

  • 组件使用 onPush 模式
    • 只有输入属性发生变化时,该组件才会检测
    • 只有该组件或者其子组件中的 DOM 事件触发时,才会触发检测
    • 非 DOM 事件的其他异步事件,只能手动触发检测
    • 声明了 onPush 的子组件,如果输入属性未变化,就不会去做计算和更新
@Component({
  ...
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class XXXComponent {
	....
}

在 Angular 中 显示的设置 @ComponentchangeDetection 为  ChangeDetectionStrategy.OnPush 即开启 onPush 模式(默认不开启),用 OnPush 可以跳过某个组件或者某个父组件以及它下面所有子组件的变化检测,如下所示:

Bagaimanakah Angular mengoptimumkan? Analisis ringkas penyelesaian pengoptimuman prestasi

(5)针对模板 ——减少不必要的计算和渲染

  • Gunakan trackBy untuk rendering gelung senarai
  • Cuba gunakan nilai cache ​​dan elakkan menggunakan panggilan kaedah dan dapatkan panggilan atribut
  • Jika terdapat tempat yang anda perlukan untuk memanggil fungsi dalam templat, dan Untuk berbilang panggilan, anda boleh menggunakan cache templat
  • ngIf untuk mengawal paparan komponen dan meletakkannya di tempat komponen dipanggil

(6) Cadangan pengoptimuman pengekodan lain

  • Jangan gunakan try/catch untuk kawalan proses, ia akan menyebabkan penggunaan masa yang banyak (merekodkan banyak maklumat tindanan, dsb.)
  • Animasi yang berlebihan akan menyebabkan lag memuatkan halaman
  • Senarai panjang boleh menggunakan tatal maya
  • Tangguhkan beban sebanyak mungkin untuk modul pramuat, kerana bilangan urutan permintaan http serentak penyemak imbas adalah terhad Setelah melebihi had, permintaan seterusnya akan disekat dan digantung
  • dsb.

Ringkasan.

(1) Terangkan secara ringkas cara Angular menggunakan Zone .js untuk melaksanakan pengesanan perubahan

(2) Atas dasar memahami pengesanan perubahan Angular, kami menjelaskan lagi prinsip pengoptimuman prestasi sudut dan kriteria untuk menilai sama ada halaman mempunyai prestasi yang baik

(3) Sediakan beberapa penyelesaian pengoptimuman prestasi masa jalan yang disasarkan

Untuk lebih banyak pengetahuan berkaitan pengaturcaraan, sila lawati: Pengenalan kepada Pengaturcaraan! !

Atas ialah kandungan terperinci Bagaimanakah Angular mengoptimumkan? Analisis ringkas penyelesaian pengoptimuman prestasi. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:juejin.cn. Jika ada pelanggaran, sila hubungi admin@php.cn Padam