在創(chuàng)建 Web 應(yīng)用程序時(shí)應(yīng)始終考慮性能。為了幫助你開始,本文列舉了有效提高應(yīng)用程序性能的 12 種方法。
性能是創(chuàng)建網(wǎng)頁(yè)或應(yīng)用程序時(shí)最重要的一個(gè)方面。沒有人想要應(yīng)用程序崩潰或者網(wǎng)頁(yè)無(wú)法加載,或者用戶的等待時(shí)間很長(zhǎng)。根據(jù) Kissmetrics,47%的訪問(wèn)者希望網(wǎng)站在不到 2 秒的時(shí)間內(nèi)加載,如果加載過(guò)程需要 3 秒以上,則有 40%的訪問(wèn)者會(huì)離開網(wǎng)站。
考慮到以上這些數(shù)字,你在創(chuàng)建 Web 應(yīng)用程序時(shí)應(yīng)始終考慮性能。為了幫助你開始,以下提供了有效提高應(yīng)用程序性能的 12 種方法:
1、在瀏覽器中緩存
要這樣做有兩種選擇。第一種是使用 Javascript Cache API,我們可以安裝 service worker 來(lái)使用它。第二種是使用 HTTP 協(xié)議緩存。
訪問(wèn)某個(gè)對(duì)象通常要用腳本。通過(guò)把重復(fù)訪問(wèn)的對(duì)象存儲(chǔ)在用戶定義的變量中,以及在后續(xù)對(duì)該對(duì)象的引用中使用變量,可以立即實(shí)現(xiàn)性能的提升。
2、定義執(zhí)行的上下文
為了有效地衡量你在程序中加入的任何改進(jìn),你必須創(chuàng)建一組定義良好的環(huán)境,以便測(cè)試代碼的性能。
對(duì)所有 Javascript 引擎的所有版本進(jìn)行性能測(cè)試和優(yōu)化實(shí)際上是不可行的。但是,在單一的環(huán)境中進(jìn)行測(cè)試并非一個(gè)好習(xí)慣,因?yàn)槟憧赡軙?huì)得到片面的結(jié)果。因此,建立多個(gè)定義良好的環(huán)境并測(cè)試代碼是否有效非常重要。
3、刪除未使用的 Javascript
此步驟不僅會(huì)縮短傳輸時(shí)間,還會(huì)縮短瀏覽器分析和編譯代碼所需的時(shí)間。為此,你必須考慮以下幾點(diǎn):
如果你檢測(cè)到一個(gè)用戶未使用的功能,最好刪除所有與之相關(guān)的 Javascript 代碼,這樣網(wǎng)站的加載速度會(huì)更快,用戶也會(huì)有更好的體驗(yàn)。
還有可能,你錯(cuò)誤地加入了一個(gè)并不需要的庫(kù),或者你有依賴項(xiàng),這些依賴項(xiàng)提供的功能在所有瀏覽器中原本就有,那么你無(wú)需再增加多余的代碼。
4、避免使用太多內(nèi)存
你應(yīng)該始終給內(nèi)存加一條限制,那就是只有絕對(duì)必須的內(nèi)容才能使用內(nèi)存,因?yàn)槟銦o(wú)法知道運(yùn)行應(yīng)用程序的設(shè)備到底需要多少內(nèi)存。只要你的代碼要求瀏覽器保留新的內(nèi)存,瀏覽器的垃圾收集器就會(huì)被執(zhí)行,并停止 Javascript 的運(yùn)行。如果經(jīng)常發(fā)生這種情況,頁(yè)面將變慢。
5、推遲不必要的 JS 加載
用戶希望頁(yè)面快速加載,但并非所有函數(shù)都需要在頁(yè)面的初始加載時(shí)就可用。如果用戶必須執(zhí)行某個(gè)操作才能執(zhí)行某個(gè)函數(shù)(例如,通過(guò)單擊某個(gè)元素或更改選項(xiàng)卡),那么你可以將該函數(shù)的加載推遲到初始頁(yè)面加載之后。
通過(guò)這種方式,你可以避免加載和編譯那些會(huì)延遲頁(yè)面初始顯示的 Javascript 代碼。頁(yè)面完全加載后,我們可以再開始加載這些功能,以便它們?cè)谟脩糸_始交互時(shí)立即可用。在 RAIL 模型中,Google 建議將此延遲加載以 50 毫秒為單位進(jìn)行,這樣就不會(huì)影響用戶與頁(yè)面的交互。
6、避免內(nèi)存泄漏
如果內(nèi)存正在泄漏,則加載的頁(yè)面將保留越來(lái)越多的內(nèi)存,并最終占用設(shè)備的所有可用內(nèi)存并嚴(yán)重影響性能。你可能見過(guò)此類故障(并且可能對(duì)此類故障感到懊惱),例如在帶有輪播或圖像滑動(dòng)條的頁(yè)面上。
在 Chrome 開發(fā)者工具中,你可以通過(guò)在“性能”標(biāo)簽中記錄時(shí)間線來(lái)分析你的網(wǎng)站是否存在內(nèi)存泄漏。通常,內(nèi)存泄漏的原因是,你從頁(yè)面中刪除了 DOM,但有一些變量還在引用這些 DOM,因此,垃圾收集器無(wú)法消除它們。
7、適當(dāng)?shù)氖褂?Web worker
當(dāng)你執(zhí)行耗時(shí)很長(zhǎng)的代碼時(shí),請(qǐng)使用 Web worker。根據(jù) Mozilla 開發(fā)人員網(wǎng)絡(luò) (MDN) 文檔:“Web Worker 可以在與 Web 應(yīng)用程序的主執(zhí)行線程分開的后臺(tái)線程中運(yùn)行腳本操作。這樣做的好處是你可以在一個(gè)單獨(dú)的線程中執(zhí)行耗時(shí)又費(fèi)力的的處理,同時(shí)讓主(通常為 UI)線程運(yùn)行而不被阻塞或減慢。”
Web worker 允許代碼執(zhí)行處理器密集型計(jì)算,而不阻塞用戶界面線程。Web Worker 允許你生成新線程并將工作委托給這些線程以獲得高效的性能。這樣,通常會(huì)阻礙其他任務(wù)且需要長(zhǎng)時(shí)間運(yùn)行的任務(wù)將被傳遞給 worker,從而讓主線程可以在無(wú)阻礙的情況下運(yùn)行。
8、適當(dāng)將 DOM 元素保存在局部變量中
訪問(wèn) DOM 會(huì)很慢。如果要多次讀取某元素的內(nèi)容,最好將其保存在局部變量中。但記住重要的是,如果稍后你會(huì)刪除 DOM 的值,則應(yīng)將變量設(shè)置為“null”,不然會(huì)導(dǎo)致內(nèi)存泄漏。
9、優(yōu)先訪問(wèn)局部變量
Javascript 首先搜索以查看變量是否存在于本地,然后才在更高級(jí)別的作用域內(nèi)逐步搜索到全局變量為止。將變量保存在本地作用域內(nèi)能讓 Javascript 更快地訪問(wèn)它們。
局部變量是基于最具體的作用域的,并且可能會(huì)穿過(guò)多個(gè)級(jí)別的作用域,因此查找這一動(dòng)作可能導(dǎo)致出現(xiàn)通用的查詢。在一個(gè)它前面沒有變量聲明的局部變量中定義函數(shù)作用域時(shí),需要在每個(gè)變量之前加上 let 或 const,以便定義當(dāng)前作用域,防止查找并加速代碼執(zhí)行。
10、避免使用全局變量
因?yàn)槟_本引擎在從函數(shù)或其他作用域內(nèi)引用全局變量時(shí)需要逐一查看作用域,所以當(dāng)本地作用域丟失時(shí),該變量將被銷毀。如果全局作用域中的變量無(wú)法在腳本的生命周期內(nèi)持續(xù)存在,則性能將得到改善。
11、實(shí)施一些優(yōu)化方案
始終使用計(jì)算復(fù)雜度最低的算法和最佳的數(shù)據(jù)結(jié)構(gòu)來(lái)解決任務(wù)。
重寫算法以獲得相同的結(jié)果和更少的計(jì)算。
避免遞歸調(diào)用。
給重復(fù)的函數(shù)加入變量、計(jì)算和調(diào)用。
分解和簡(jiǎn)化數(shù)學(xué)公式。
使用搜索數(shù)組:用它們來(lái)獲取基于另一個(gè)的值,而不是使用 switch/case 語(yǔ)句。
使條件總是更有可能為真,以更好地利用處理器的推測(cè)執(zhí)行。
如果可以,請(qǐng)使用位級(jí)運(yùn)算符替換某些操作,因?yàn)檫@些運(yùn)算符的處理周期較短。
12、使用工具檢測(cè)問(wèn)題
Lighthouse 是一個(gè)很好的網(wǎng)頁(yè)性能工具,它可以幫助你審核性能、可訪問(wèn)性、最佳實(shí)踐和 SEO。谷歌 PageSpeed 旨在幫助開發(fā)人員了解網(wǎng)站的性能優(yōu)化和潛在可改進(jìn)的方面。這些組件旨在識(shí)別網(wǎng)站是否符合 Google Web 性能最佳實(shí)踐,以及將調(diào)整過(guò)程自動(dòng)化。
在 Chrome 中,你還可以使用主菜單中的“更多工具”選項(xiàng)來(lái)查看每個(gè)選項(xiàng)卡使用的內(nèi)存和 CPU。對(duì)于更高級(jí)的分析,你可以使用 Firefox 或 Chrome 中的開發(fā)人員工具“性能”視圖來(lái)分析不同的指標(biāo),例如:
devtools 的性能分析允許你在加載頁(yè)面時(shí)模擬 CPU 消耗、網(wǎng)絡(luò)和其他指標(biāo),以便識(shí)別和修復(fù)問(wèn)題。
devtools 的性能分析允許你在加載頁(yè)面時(shí)模擬 CPU 消耗、網(wǎng)絡(luò)和其他指標(biāo),以便識(shí)別和修復(fù)問(wèn)題。
為了更深入地了解,建議你使用 Javascript Navigation Timing API,它允許你詳細(xì)測(cè)量代碼的每個(gè)部分從編程本身中獲取的內(nèi)容。
對(duì)于基于 Node.js 構(gòu)建的應(yīng)用程序,NodeSource Platform 也是一種非常好、影響低的方式,它可以在非常精細(xì)的級(jí)別上探索應(yīng)用程序性能。
全面的 Node.js 指標(biāo)可幫助你識(shí)別內(nèi)存泄漏源或其他性能問(wèn)題,并更快地解決這些問(wèn)題。
最后的說(shuō)明在代碼的可讀性和優(yōu)化之間保持平衡很重要。代碼由計(jì)算機(jī)解釋,但我們需要確保代碼將來(lái)可以由我們自己或其他人維護(hù),因此它們需要易于理解。
請(qǐng)記?。簯?yīng)始終考慮性能,但不應(yīng)將性能凌駕于錯(cuò)誤檢測(cè)和功能添加之上。