十個構(gòu)建高性能網(wǎng)站的JavaScript 技巧
在構(gòu)建高性能網(wǎng)站時,JavaScript 可能是你的好朋友,也可能是你的噩夢。一些精心選擇的優(yōu)化技術(shù)可以顯著加快你的網(wǎng)站速度,從而帶來更流暢的用戶體驗。
以下 10 條提示深入探討了性能提升實踐,分解了每條實踐背后的“原因”和“方式”:
1. 盡量減少 DOM 操作
修改 DOM 就像每次需要一雙襪子時重新整理整個衣柜一樣,非常耗時!每次 DOM 操作都會觸發(fā)重新渲染,這會降低你的應(yīng)用速度,尤其是當你一次進行多項更改時。
相反,請嘗試批量更新 DOM。
如果你必須操作 DOM,請盡量以盡量減少重排和重繪的方式進行,例如,使用 DocumentFragment 或在將其插入 DOM 之前構(gòu)建 UI 結(jié)構(gòu)。你的用戶會感謝你多花幾秒鐘的注意力。
示例:
const fragment = document.createDocumentFragment();
data.forEach(item => {
const element = document.createElement('div');
element.textContent = item.name;
fragment.appendChild(element);
});
document.body.appendChild(fragment);
2. 防抖和節(jié)流用戶事件
你是否曾看到過網(wǎng)站在您嘗試滾動時變得非常慢?這可能是因為每次您移動時,網(wǎng)站都會觸發(fā)大量事件偵聽器。
防抖和節(jié)流通過限制函數(shù)調(diào)用的頻率來防止這種過載。節(jié)流允許操作以指定的間隔發(fā)生,而防抖則確保函數(shù)僅在上次事件發(fā)生后經(jīng)過一定時間后觸發(fā)。
節(jié)流示例:
const throttle = (fn, limit) => {
let lastFunc, lastRan;
return function(...args) {
if (!lastRan) {
fn.apply(this, args);
lastRan = Date.now();
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(function() {
if ((Date.now() - lastRan) >= limit) {
fn.apply(this, args);
lastRan = Date.now();
}
}, limit - (Date.now() - lastRan));
}
};
};
// Usage with a scroll event
window.addEventListener('scroll', throttle(handleScroll, 200));
3. 延遲加載資源
Web 性能的一個關(guān)鍵方面是確保用戶僅在需要時加載他們需要的內(nèi)容。
延遲加載就是針對圖像、腳本和其他重資源的。
例如,對屏幕外圖像實施延遲加載不僅可以加快頁面加載時間,還可以改善移動數(shù)據(jù)使用情況。
大多數(shù)瀏覽器現(xiàn)在都支持使用 loading="lazy" 實現(xiàn)圖像的原生延遲加載,但您也可以使用 JavaScript 來實現(xiàn)此目的,以獲得更多控制。
示例:
<img src="image.jpg" loading="lazy" alt="Lazy loaded image">
4. 使用 Web Workers 進行繁重計算
JavaScript 通常在主線程上運行,如果與繁重計算有關(guān),則可能意味著用戶的性能會很差。
Web Workers 允許您在主線程之外運行代碼,讓用戶感覺繁重的任務(wù)變得輕松很多。
使用 Web Workers 的示例:
const worker = new Worker('worker.js');
worker.postMessage('start');
worker.onmessage = (e) => {
console.log(`Worker said: ${e.data}`);
};
5. 選擇原生 JavaScript 而非庫
雖然像 jQuery 這樣的庫讓 JavaScript 更容易訪問,但它們也有自己的負擔。如今的原生 JavaScript 擁有庫曾經(jīng)添加的大部分功能。
這意味著您可以跳過加載整個庫的過程,只需進行基本的 DOM 操作即可。
代碼越少,加載時間越快 — — 這對用戶來說是一種勝利。
// Instead of jQuery's $('#myElement').addClass('active')
document.getElementById('myElement').classList.add('active');
6. 使用異步和延遲加載腳本
如果處理不當,JavaScript 文件可能會阻止網(wǎng)頁的呈現(xiàn)。async 和 defer 屬性可以通過加載 JavaScript 而不占用整個頁面來防止這種情況。
async 在下載腳本后立即執(zhí)行,而 defer 則等到 HTML 文檔完全解析后再執(zhí)行。
<script src="script.js" async></script>
<script src="script.js" defer></script>
7. 使用動態(tài)導入實現(xiàn)代碼拆分
如果用戶可能根本不需要,為什么要預(yù)先加載所有內(nèi)容?代碼拆分可讓您將代碼拆分為多個包,僅加載特定頁面或組件所需的內(nèi)容。
動態(tài)導入使此操作更加容易,允許您僅在需要時有條件地導入模塊。
// Importing a module only when needed
if (condition) {
import('./module.js').then(module => {
module.someFunction();
});
}
8. 減少對全局變量的依賴
全局變量就像一個不斷插話的家庭成員——它們可能會通過相互沖突和霸占主范圍而導致意外問題。
使用局部變量或?qū)⒐δ芊庋b在函數(shù)內(nèi)以限制全局范圍內(nèi)的混亂,從而減少出錯的機會并使您的代碼更快。
function scopedFunction() {
let localVariable = 'This stays here';
}
9. 優(yōu)化循環(huán)和迭代
如果不進行優(yōu)化,循環(huán)很快就會成為性能瓶頸。例如,如果您反復(fù)訪問大型數(shù)組或?qū)ο蟮拈L度或其他屬性,則循環(huán)速度會很慢。
通過緩存長度并避免在循環(huán)內(nèi)進行過多的 DOM 查找,您可以節(jié)省寶貴的處理時間。
const array = [1, 2, 3, 4];
for (let i = 0, len = array.length; i < len; i++) {
console.log(array[i]);
}
10. 利用緩存的力量
Web 瀏覽器帶有一個稱為緩存的便捷功能。通過設(shè)置 HTTP 標頭以鼓勵緩存,您可以允許用戶在本地存儲您網(wǎng)站的部分內(nèi)容。
這意味著后續(xù)訪問的加載時間更快,對服務(wù)器的請求更少。這就像為用戶提供您網(wǎng)站的 VIP 通行證,讓他們無需排隊。
Cache-Control: public, max-age=31536000
總結(jié)
以上就是今天這篇文章跟您分享的全部內(nèi)容,希望對你有所幫助。