Thứ tư, 25/12/2019 | 00:00 GMT+7

Cách bắt đầu với API hiệu suất JavaScript


Hiệu suất, hiệu suất, hiệu suất. Bạn có thể có trang web tốt nhất trên thế giới, nhưng nếu mất 2 phút để tải thì sẽ không có ai nhìn thấy nó. Nếu trang web mất 2 phút để tải thì có lẽ sẽ không quá khó để tìm ra lý do. Tối ưu hóa phức tạp hơn khi bạn cố gắng giảm thời gian tải trung bình từ 1 giây xuống 0,85 giây.

Có rất nhiều công cụ có thể giúp bạn hiểu cách ứng dụng của bạn hoạt động local . API Hiệu suất ở đây để giúp ta hiểu chi tiết về các trang web của ta trong tự nhiên. Bạn có thể lấy dữ liệu thực và xem cách trang web hoạt động trong các trình duyệt, mạng, các khu vực khác nhau trên thế giới và hơn thế nữa!

API hiệu suất thường được mô tả là một group API. Có quá nhiều thứ để mô tả tất cả trong một bài báo. Trong bài đăng này, ta sẽ trình bày các tính năng cơ bản nhất để giúp bạn bắt đầu theo dõi hiệu suất.

API đang phát triển và sẽ có nhiều tính năng mới cũng như việc ngừng sử dụng. Cấp độ 2 của tất cả các API hiệu suất sắp ra mắt; một số trong số đó được thực hiện một phần, một số vẫn còn là bản nháp. Vì vậy, bạn nên thường xuyên kiểm tra MDN hoặc trang web của W3C để biết các bản cập nhật mới nhất.

Cách truy cập dữ liệu hiệu suất

performance.now

Cách cơ bản nhất để đo lường hiệu suất của chương trình là sử dụng performance.now() . Thao tác này sẽ trả về thời gian hiện tại ở độ phân giải dưới mili giây. Nếu bạn muốn tìm hiểu kỹ về thời gian có độ phân giải cao, tôi thực sự khuyên bạn nên đọc bản thảo của Biên tập viên của W3C về chủ đề đó .

performance.now chỉ cho phép bạn đo lường những gì trong mã JavaScript của bạn (còn gọi là hiệu suất user ). Sau đó trong bài đăng này, tôi sẽ xem xét một ví dụ về cách sử dụng performance.now .


Để truy cập các sự kiện DOM và trình duyệt khác nhau, ta có 3 chức năng:

  • getEntries() trả về tất cả các mục hiệu suất có sẵn. Hãy thử chạy performance.getEntries() trên trang hiện tại và bạn sẽ thấy một mảng lớn. Ban đầu, hầu hết các mục nhập sẽ liên quan đến tất cả hình ảnh, tập lệnh và những thứ khác được tải bởi trang (hay còn gọi là tài nguyên).
const tenthEntry = performance.getEntries()[10] // on Alligator.io it will return the following object // { initiatorType: "script", // nextHopProtocol: "h2", // workerStart: 526.8099999520928, // redirectStart: 0, // .... // decodedBodySize: 0, // serverTiming: [], // name: "https://d33wubrfki0l68.cloudfront.net/bundles/e2203d1b1c14952473222bcff4c58a8bd9fef14a.js", // entryType: "resource", // startTime: 315.5049999477342, // duration: 231.48499999661 //} // We can see this is a resource entry for a script loaded from cloudfront 
  • getEntriesByType () giống như getEntries() , nhưng sẽ cung cấp cho bạn một số khả năng lọc kết quả.

Có 6 loại mà bạn có thể truy vấn:

  • frame: Tính năng rất thử nghiệm cho phép các nhà phát triển lấy dữ liệu về lượng công việc được trình duyệt thực hiện trong một vòng lặp sự kiện. Nếu trình duyệt thực hiện quá nhiều công việc trong một vòng lặp, tốc độ khung hình sẽ giảm xuống và trải nghiệm user sẽ kém.
  • tài nguyên: Điều này liên quan đến tất cả các tài nguyên được download bởi trang web.
  • mark: Đây là những điểm đánh dấu tùy chỉnh được dùng để tính toán tốc độ mã của bạn.
  • Thước đo: Các thước đo cho phép ta dễ dàng đo lường sự khác biệt giữa hai nhãn hiệu.
  • paint: Các mục paint liên quan đến các pixel hiển thị trên màn hình.
  • longtask: Nhiệm vụ dài là bất kỳ tác vụ nào mất hơn 50ms để thực hiện.

Ta sẽ đi sâu vào một số loại này trong các phần tiếp theo. Đây là một ví dụ đơn giản để bắt đầu:

const paintEntries = performance.getEntriesByType('paint') // paint Entries[0] equals { //    name: "first-paint", //    entryType: "paint", //    startTime: 342.160000000149, //    duration: 0, //    } // paintEntries[1] equals { //    name: "first-contentful-paint", //    entryType: "paint", //    startTime: 342.160000000149, //    duration: 0, // } 
  • getEntriesByName (entryName) lọc tất cả các mục nhập theo tên.
const nativeLogoPerfEntry = performance.getEntriesByName('https://alligator.io/images/alligator-logo3.svg')[0]; // It will return performance information related to the logo's performance: // {initiatorType: "img", // nextHopProtocol: "", // workerStart: 539.6649999311194, // ........ // name: "https://alligator.io/images/alligator-logo3.svg", // entryType: "resource", // startTime: 539.5149999530986, // duration: 94.24000000581145 //} 

Nếu bạn đang tìm kiếm thông tin cấp cao hơn về hiệu suất của trang web, bạn cũng có thể gọi performance.toJSON() .

Kiểm tra các chức năng của bạn

Để kiểm tra các hàm JavaScript cụ thể, công cụ cơ bản nhất là performance.now() mà ta đã mô tả ở trên.

Đây là một ví dụ sử dụng:

const firstNow = performance.now() // This loop is just to simulate slow calculations for (let i = 0; i < 100000; i++){   var ii = Math.sqrt(i) } const secondNow = performance.now()  const howLongDidOurLoopTake = secondNow - firstNow // on my laptop it returns howLongDidOurLoopTake == 4.08500000089407 in milliseconds 

Vấn đề now là hơi khó quản lý nếu bạn có nhiều phép đo. Một công cụ hữu ích hơn là mark tạo ra một số mục nhập hiệu suất mà bạn có thể truy vấn sau này. Sau đó, bạn có thể kết hợp các điểm đánh dấu và tạo các mục nhập mới bằng cách sử dụng measure .

performance.mark('beginSquareRootLoop'); // This loop is just to simulate slow calculations for (let i = 0; i < 1000000; i++){   var ii = Math.sqrt(i); } performance.mark('endSquareRootLoop'); // Then anywhere in your code you can use  // We create a new entry called measureSquareRootLoop which combines our two marks performance.measure('measureSquareRootLoop','beginSquareRootLoop', 'endSquareRootLoop');  console.log(performance.getEntriesByName('beginSquareRootLoop')); // {detail: null, // name: "beginSquareRootLoop", // entryType: "mark", // startTime: 3745.360000000801, // duration: 0}  console.log(performance.getEntriesByName('measureSquareRootLoop')); // {detail: null, // name: "measureSquareRootLoop", // entryType: "measure", // startTime: 3745.360000000801, This is the same as beginSquareRootLoop // duration: 9.904999984428287 shows the time it took to get from beginSquareRootLoop to endSquareRootLoop //} 

Điều hướng được sử dụng để hiểu chi tiết về các bước quan trọng để xây dựng trang web . Cách an toàn nhất để truy cập dữ liệu chuyển là thực hiện:

const navigationEntry = performance.getEntriesByType('navigation')[0] 

Trong trình duyệt của bạn , tôi nhận được:

{   unloadEventStart: 213.41000002576038,   unloadEventEnd: 213.41000002576038,   domInteractive: 975.8100000326522,   domContentLoadedEventStart: 982.2649999987334,   domContentLoadedEventEnd: 1217.9650000180118,   domComplete: 2000.960000033956,   loadEventStart: 2001.044999982696,   loadEventEnd: 2008.6500000325032,   type: "reload",   redirectCount: 0,   initiatorType: "navigation",   nextHopProtocol: "",   workerStart: 2.5550000136718154,   redirectStart: 0,   redirectEnd: 0,   fetchStart: 2.5599999935366213,   domainLookupStart: 2.5599999935366213,   domainLookupEnd: 2.5599999935366213,   connectStart: 2.5599999935366213,   connectEnd: 2.5599999935366213,   secureConnectionStart: 0,   requestStart: 2.5599999935366213,   responseStart: 107.46500000823289,   responseEnd: 214.3950000172481,   transferSize: 0,   encodedBodySize: 0,   decodedBodySize: 0,   serverTiming: [],   name: "https://alligator.io/",   entryType: "navigation",   startTime: 0,   duration: 2008.6500000325032 } 

Ta sẽ đi sâu vào một số giải thích chi tiết hơn về cách sử dụng dữ liệu đó trong một bài đăng trong tương lai. Nhưng trong thời gian chờ đợi, đây là hình ảnh của dòng thời gian chuyển :

Dòng thời gian  chuyển  hiệu suất trên Alligator.io

Nguồn

Khi nào tài nguyên được tải bởi một trang, ta có thể tìm thấy dấu vết của nó trong Mục nhập Hiệu suất . Tất cả những gì ta phải làm để có được chúng là chạy performance.getEntriesByType('resource') . Điều này bao gồm hình ảnh, tập lệnh, file CSS và hơn thế nữa. Vì vậy, ví dụ: nếu ta muốn tập trung vào hiệu suất của hình ảnh trên trang web, ta có thể chạy:

performance.getEntriesByType('resource').filter(resource=> resource.initiatorType == 'img') 

Đây là một trong những tài nguyên được tìm thấy trên Alligator.io:

{     initiatorType: "img",     nextHopProtocol: "h2",     workerStart: 551.2149999849498,     redirectStart: 0,     redirectEnd: 0,     fetchStart: 551.3149999896996,     domainLookupStart: 0,     domainLookupEnd: 0,     connectStart: 0,     connectEnd: 0,     secureConnectionStart: 0,     requestStart: 0,     responseStart: 0,     responseEnd: 560.1850000093691,     transferSize: 0,     encodedBodySize: 0,     decodedBodySize: 0,     serverTiming: [],     name: "https://d33wubrfki0l68.cloudfront.net/39d2d2905588dad289b228deb021d51449f6143d/a3baf/images/logos/gatsby-logo.svg",     entryType: "resource",     startTime: 222.0450000022538,     duration: 338.1400000071153 } 

Mục nhập này có rất nhiều giá trị 0 như bạn thấy , đó là do ta bị hạn chế bởi CORS (đây là giới hạn lớn của API định thời tài nguyên). Vì vậy, các thuộc tính sau sẽ luôn trả về 0: redirectStart, redirectEnd, domainLookupStart, domainLookupEnd, connectStart, connectEnd, secureConnectionStart, requestStart và responseStart.

Sơn

API sơn liên quan đến các sự kiện vẽ pixel trên cửa sổ. Như ta đã thấy trong đoạn trước, ta có quyền truy cập Lần đầu tiên vẽBức tranh có nội dung đầu tiên . Nếu bạn đã làm việc với các công cụ tối ưu hóa giao diện user như Lighthouse, bạn có thể quen thuộc với các thuật ngữ này. Lần đầu tiên vẽ là khi pixel đầu tiên hiển thị trên màn hình user . Sơn nội dung đầu tiên là khi một phần tử được xác định trong DOM được hiển thị đầu tiên. Để tối ưu hóa lớp sơn nội dung đầu tiên, bạn có thể giảm các tập lệnh và bảng định kiểu chặn hiển thị, sử dụng cache HTTP, tối ưu hóa khởi động JavaScript và hơn thế nữa!

Đây là những số liệu hữu ích nhưng khá hạn chế nếu bạn đang cố gắng hiểu những gì user của bạn nhìn thấy. Để có ý tưởng tốt về nhận thức hiệu suất của user , ta cần kết hợp nhiều chỉ số.

API hiệu suất rất lớn và đang thay đổi nhanh chóng. Nơi tốt nhất để tìm kiếm các bản cập nhật tất nhiên là Alligator.io, nhưng nếu bạn muốn khám phá chủ đề này một cách thực sự chuyên sâu, bạn nên xem trang của Group làm việc về Hiệu suất Web , nơi bạn có thể tìm thấy các bản nháp và đề xuất mới nhất.


Tags:

Các tin liên quan

Xem xét tất cả 13 bẫy proxy JavaScript
2019-12-19
Khám phá phương thức indexOf cho chuỗi và mảng trong JavaScript
2019-12-17
Thao tác DOM trong JavaScript với innerText và innerHTML
2019-12-14
Cách gói một gói JavaScript Vanilla để sử dụng trong React
2019-12-12
Cách phát triển một trình tải lên tệp tương tác với JavaScript và Canvas
2019-12-12
Cách sử dụng map (), filter () và Reduce () trong JavaScript
2019-12-12
Giải thích về lập trình chức năng JavaScript: Ứng dụng một phần và làm xoăn
2019-12-12
Giới thiệu về Closures và Currying trong JavaScript
2019-12-12
Bắt đầu với các hàm mũi tên ES6 trong JavaScript
2019-12-12
Cách đếm số nguyên âm trong một chuỗi văn bản bằng thuật toán JavaScript
2019-12-12