搜尋
首頁web前端js教程Js前端效能優化總結

Js前端效能優化總結

Feb 28, 2018 pm 01:42 PM
javascript最佳化總結

最好的資源最佳化就是不載入資源。緩存也是最見效的優化手段。說實話,雖然說客戶端快取發生在瀏覽器端,但快取主要還是服務端來控制,與我們前端關係並不是很大。但還是有必要了解一下。

快取包含服務端快取和客戶端緩存,本文只談客戶端快取。所謂客戶端快取主要是http快取。 http快取主要分為強制快取和協商快取。

強制快取

  • Expires(http1.0)

在http1.0中使用Expires來做強制快取。 Exprires的值為服務端傳回的資料到期時間。當再次請求時的請求時間小於返回的此時間,則直接使用快取資料。但由於服務端時間和客戶端時間可能有誤差,這也將導致快取命中的誤差。

  • Cache-Control

Cache-Control有很多屬性,不同的屬性代表的意義也不同。

  1. private:客戶端可以快取

  2. #public:客戶端和代理伺服器都可以快取

  3. max-age=t:快取內容將在t秒後失效

  4. no-cache:需要使用協商快取來驗證快取資料

  5. no-store:所有內容都不會快取。

協商快取

瀏覽器第一次要求資料時,伺服器會將快取標識與資料一起回應給客戶端,客戶端將它們備份到快取中。再次請求時,客戶端會將快取中的識別傳送給伺服器,伺服器根據此標識判斷。若未失效,返回304狀態碼,瀏覽器拿到此狀態碼就可以直接使用快取資料了。

  • Last-Modified

伺服器在回應請求時,會告訴瀏覽器資源的最後修改時間

  • if-Modified-Since

瀏覽器再次請求伺服器的時候,請求頭會包含此字段,後面跟著在快取中獲得的Last-Modified(最後修改時間)。服務端收到此要求頭髮現有if-Modified-Since,則與被要求資源的最後修改時間進行對比,如果大於被要求資源最後修改時間則返回304,瀏覽器從快取獲取資源。如果小於被要求資源最後修改時間,則傳回200,並傳回最新資源,瀏覽器從服務端取得最新的資源,並快取。

  • Etag

伺服器產生的每個資源的唯一識別字串

  • If -None-Match

再次請求伺服器時,瀏覽器的請求封包頭會包含此字段,後面的值為在快取中取得的識別。伺服器接收到次訊息後發現If-None-Match則與被要求資源的唯一識別進行比較。如果相同,表示資源沒有被修改過,返回304,瀏覽器從快取取得資源,如果不同說明資源被修改過,則傳回200,並傳回最新資源,瀏覽器從服務端取得最新資源,並快取。

Last-Modified與ETag是可以一起使用的,伺服器會優先驗證ETag,一致的情況下,才會繼續比對Last-Modified,最後才決定是否回傳304。

如果使用前端打包工具,可以在打包檔案時候在為檔案新增版本號碼或hash值,同樣可以區分資源是否過期。

減少http請求

  • 使用CDN託管靜態資源

  • 可以藉助gulp、webpack等打包工具對js、css等檔案合併與壓縮

  • 圖片懶載入、按需加載,當捲動到圖片視覺區域才去載入圖片

  • ##小圖片且基本上不會改變的圖片使用base64編碼傳輸。 base64不要濫用,即使小圖片經過base64編碼之後也會產生很長的字串,如果濫用base64反而會適得其反

  • 雪碧圖,這個也是針對基本不會更改的圖片才使用雪碧圖,因為如果一張圖片修改,會導致整個雪碧圖重新生成,如果亂用也會適得其反。

減少http請求資源體積

  • 借助webpack、gulp等工具壓縮資源

  • 服務端開啟gzip壓縮(壓縮率非常可觀,一般都在30%之上)

  • 如果有用打包工具,打包優化要做好,公共資源、提取第三方程式碼、不需要打包的庫...

渲染優化

讀過前面js運行機制的應該知道,從瀏覽器輸入url,到頁面出現在螢幕上,都發生了哪些事(tcp握手、dns解析等不在認知範圍)。
  • FPS 16ms 小於10ms完成最好  Google devtool 查看影格率

如果瀏覽器FPS到達60,就會顯得比較流暢,大多數顯示器的刷新頻率是60Hz,瀏覽器會自動依照這個頻率刷新動畫。
依照FPS等於60來計算,平均一幀的時間為1000ms/60 = 16.7ms,所以每次渲染時間不能超過16ms,如果超過這個時間就會出現丟幀、卡頓現象。

可以在chrome瀏覽器開發者工具中的Timeline中查看更新率,可以查看所有幀率耗時情況以及某一幀的執行情況。 Timeline的使用教學:https://segmentfault.com/a/11...

為了確保正常的FPS,有些渲染效能最佳化還是有必要的。以下所介紹的都是有關渲染優化的策略。

  • 盡量使用css3來做動畫

#總所周知,css的效能要比js快,所以能使用css,盡量不用js來實現

  • 避免使用setTimeout或setInterval,盡量使用requestAnimationFrame來做動畫或高頻Dom操作。

因為setTimeout和setInterval無法保證callback函數的執行時機,很可能在幀結束的時候執行,從而導致丟幀,但是requestAnimationFrame可以保證callback函數在每幀動畫開始的時執行
requestAnimationFrame的中文MDN位址:https://developer.mozilla.org...

  • 複雜的運算運算使用Web Workers

#如果有需要複雜的資料操作,例如對一個有一個元素的陣列遍歷求和,那麼Web Workers在適合不過了。

Web Workers可以讓JavaScript腳本在後台執行緒(類似建立一個子執行緒),而後台執行緒不會影響到主執行緒中的頁面。不過,使用Web Workers建立的執行緒是不能操作DOM樹。
有關Web Workers的更多可以查看MDN詳解:https://developer.mozilla.org...

  • css放在頭部,js放在尾部。

讀過前面js運作機制的應該知道頁面渲染是怎樣一個過程,不再贅述了。 css放在頭部會避免生成html樹之後重新佈局的閃屏現象,js一般對頁面的影響較大,一般放在尾部最後執行。

  • 事件防手震(debounce)與節流(throttle)

針對高頻觸發的事件(mousemove、scroll)等事件,如果不加以控制會在短時間內觸發很多事件。

函數防手震是指頻繁觸發的情況下,只有足夠的空閒時間,才會執行程式碼一次。場景:註冊時郵箱的輸入框,隨著使用者的輸入,即時判斷郵箱格式是否正確,當第一次輸入事件觸發,設定定時:在800ms之後執行檢查。假如只過了100ms,上次的定時還沒執行,此時清除定時,重新定時800ms。直到最近一次的輸入,後面沒有緊鄰的輸入了,這最近一次的輸入定時計時結束,終於執行了檢查代碼。

const filter  = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;  
$("#email").on("keyup",checkEmail());  
function checkEmail(){  
    let timer=null;  
    return function (){  
        clearTimeout(timer);  
        timer=setTimeout(function(){  
            console.log('执行检查');  
        },800);  
    }  
}

函數節流是指一定時間內js方法只跑一次。就是本來一秒要執行100次的變成一秒執行10次。
場景:函數節流應用的實際場景,多數在監聽頁面元素滾動事件的時候會用到。

var canRun = true;
document.getElementById("throttle").onscroll = function(){
    if(!canRun){
        // 判断是否已空闲,如果在执行中,则直接return
        return;
    }

    canRun = false;
    setTimeout(function(){
        console.log("函数节流");
        canRun = true;
    }, 300);
};
  • Dom操作

前端開發人員都知道Do操作是非常耗時的(曾經親測過30*30的表格遍歷新增樣式)。所以盡量避免頻繁的Dom操作,如果避免不了就盡量對DOm操作做優化。

1.:缓存Dom查询,比如通过getElementByTagName('p')获取Dom集,而不是逐个获取。

2: 合并Dom操作,使用createDocumentFragment()
    var frag = document.createDocumentFragment()
    for (i<pre class="brush:php;toolbar:false"> 3: 使用React、Vue等框架的虚拟dom(原理目前还不明白),可以更快的实现dom操作。
  • 盡量避免重繪(rePaint)和回流(reFlow)

如果使用js修改元素的顏色或背景色就會觸發重繪,重繪的開銷還是比較昂貴的,因為瀏覽器會在某一個DOM元素的視覺效果改變後去check這個DOM元素內的所有節點。

如果修改元素的尺寸和位置就會發生回流,回流開銷更大,它會在某一個DOM元素的位置改變後觸發,而且它會重新計算所有元素的位置和在頁面中的佔有的面積,這樣的話將會引起頁面某一個部分甚至整個頁面的重新渲染。

  • css3硬體加速

瀏覽器渲染時,會分成兩個圖層:普通圖層和複合圖層。

普通文件流內可以理解為一個複合圖層,absolute、fixed佈局雖然可以脫離普通文檔流,但它仍然屬於普通圖層,不會啟動硬體加速。上面說的重繪(rePaint)和回流(reFlow)說的就是普通圖層上的重繪和回流。

複合圖層會啟動硬體加速。和普通圖層不在同一個圖層,所以複合圖層不會影響普通圖層,如果一個元素被提升到複合圖層,再操作該元素時,就不會引起普通圖層的重繪和回流,從而提升渲染效能。

如何啟動硬體加速:

1.使用translate3d和translateZ

webkit-transform: translateZ(0);
-moz-transform: translateZ(0);
-ms-transform: translateZ(0);
-o-transform: translateZ(0);
transform: translateZ(0);

webkit-transform: translate3d(0,0,0);
-moz-transform: translate3d(0,0,0);
-ms-transform: translate3d(0,0,0);
-o-transform: translate3d(0,0,0);
transform: translate3d(0,0,0);

2.使用opacity
需要动画执行的过程中才会创建合成层,动画没有开始或结束后元素还会回到之前的状态

3.使用will-chang属性
这个属性比较不常用,一般配合opacity与translate使用

针对webkit浏览器,启用硬件加速有些时候可能会导致浏览器频繁闪烁或抖动,可以使用下面方法消除:

-webkit-backface-visibility:hidden;
-webkit-perspective:1000;
如果使用硬件加速,请使用z-index配合使用, 因为如果这个元素添加了硬件加速,并且index层级比较低, 那么在这个元素的后面其它元素(层级比这个元素高的,或者相同的,并且releative或absolute属性相同的), 会默认变为复合层渲染,如果处理不当会极大的影响性能
  • 避免强制同步布局和布局抖动

浏览器渲染过程为:js/css(javascript) > 计算样式(style) > 布局(layout) > 绘制(paint) > 渲染合并图层(Composite)

JavaScript:JavaScript实现动画效果,DOM元素操作等。
Style(计算样式):确定每个DOM元素应该应用什么CSS规则。
Layout(布局):计算每个DOM元素在最终屏幕上显示的大小和位置。
Paint(绘制):在多个层上绘制DOM元素的的文字、颜色、图像、边框和阴影等。
Composite(渲染层合并):按照合理的顺序合并图层然后显示到屏幕上。

在js中如果读取style属性的某些值就会让浏览器强行进行一次布局、计算,然后再返回值,比如:

offsetTop, offsetLeft, offsetWidth, offsetHeight

scrollTop/Left/Width/Height

clientTop/Left/Width/Height

width,height

请求了getComputedStyle(), 或者 IE的 currentStyle

所以,如果强制浏览器在执行JavaScript脚本之前先执行布局过程,这就是所谓的强制同步布局。
比如下面代码:

requestAnimationFrame(logBoxHeight);

// 先写后读,触发强制布局
function logBoxHeight() {
    // 更新box样式
    box.classList.add('super-big');

    // 为了返回box的offersetHeight值
    // 浏览器必须先应用属性修改,接着执行布局过程
    console.log(box.offsetHeight);
}

// 先读后写,避免强制布局
function logBoxHeight() {
    // 获取box.offsetHeight
    console.log(box.offsetHeight);

    // 更新box样式
    box.classList.add('super-big');
}

在JavaScript脚本运行的时候,它能获取到的元素样式属性值都是上一帧画面的,都是旧的值。因此,如果你在当前帧获取属性之前又对元素节点有改动,那就会导致浏览器必须先应用属性修改,结果执行布局过程,最后再执行JavaScript逻辑。

如果连续多次强制同步布局,就会导致布局抖动
比如下面代码:

function resizeAllParagraphsToMatchBlockWidth() {
  for (var i = 0; i <p>我们知道浏览器是一帧一帧的刷新页面的,对于每一帧,上一帧的布局信息都是已知的。<br>强制布局就是使用js强制浏览器提前布局,比如下面代码:</p><pre class="brush:php;toolbar:false">// bed  每次循环都要去获取left ,就会发生一次回流
function logBoxHeight() {
  box.style.left += 10
  console.log(box.style.left)
}

// goog 
var width = box.offsetWidth;

function resizeAllParagraphsToMatchBlockWidth() {
  for (var i = 0; i 
  • DOMContentLoaded与Load

DOMContentLoaded 事件触发时,仅当DOM加载完成才触发DOMContentLoaded,此时样式表,图片,外部引入资源都还没加载。而load是等所有的资源加载完毕才会触发。

1. 解析HTML结构。
2. 加载外部脚本和样式表文件。
3. 解析并执行脚本代码。
4. DOM树构建完成。//DOMContentLoaded
5. 加载图片等外部文件。
页面加载完毕。//load
  • 视觉优化

等待加载时间可以合理使用loading gif动图一定程度上消除用户等待时间的烦躁感

代码性能

代码对性能的影响可大可小,但是养成一个良好的写代码习惯和高质量的代码,会潜移默化的提高性能,同时也能提高自己的水平。废话不多说,直接看我总结的部分要点(因为这一部分知识点太多,需要大家写代码的时候多多总结)。

  • 避免全局查找

访问局部变量会比访问全局变量快,因为js查找变量的时候现在局部作用局查找,找不到在逐级向上找。

// bad
function f () {
    for (...){
        console.log(window.location.href)
    }
}

//good
function f () {
    var href = window.location.href
    for (...){
        console.log(href)
    }
}
  • 循环技巧

// bed 
for(var i = 0; i 
  • 不要使用for in 遍历数组

for in是最慢的,其他的都差不多,其中直接使用for循环是最快的。for in只是适合用来遍历对象。

  • 使用+''代替String()吧变量转化为字符串

var a = 12
//bad
a = String(a)

// good
var a = 12
a = a + ''

这个还有很多类似的,比如使用*1代替parseInt()等都是利用js的弱类型,其实这样对性能提升不是很大,网上有人测试过,进行十几万次变量转换,才快了零点几秒。

  • 删除dom

删除dom元素要删除注册在该节点上的事件,否则就会产生无法回收的内存,在选择removeChild和innerHTML=''二者之间尽量选择后者,据说removeChild有时候无法有效的释放节点(具体原因不明)

  • 使用事件代理处理事件

任何可以冒泡的事件都可以在节点的祖先节点上处理,这样对于子节点需要绑定相同事件的情况就不用分别给每个子节点添加事件监听,而是都提升到祖先节点处理。

  • 通过js生成的dom对象必须append到页面中

在IE下,js创建的额dom如果没有添加到页面,这部分内存是不会被回收的

  • 避免与null比较

可以使用下面方法替换与null比较
1.如果该值为引用类型,则使用instanceof检查其构造函数
2.如果该值为基本类型,使用typeof检查类型

  • 尽量使用三目运算符代替if else

if(a>b){num = a}
else{num = b}

// 可以替换为
num = a > b ? a : b
  • 当判断条件大于3中情况时,使用switch代替if

因为switch的执行速度比if要快,也别是在IE下,速度大约是if的两倍。

相关推荐:

CSS解读前端性能优化的具体分析

在HTML5中如何提高网站前端性能的示例代码分析

web前端性能优化方法


以上是Js前端效能優化總結的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
超越瀏覽器:現實世界中的JavaScript超越瀏覽器:現實世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

使用Next.js(後端集成)構建多租戶SaaS應用程序使用Next.js(後端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:23 AM

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

如何使用Next.js(前端集成)構建多租戶SaaS應用程序如何使用Next.js(前端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:22 AM

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

JavaScript:探索網絡語言的多功能性JavaScript:探索網絡語言的多功能性Apr 11, 2025 am 12:01 AM

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

JavaScript的演變:當前的趨勢和未來前景JavaScript的演變:當前的趨勢和未來前景Apr 10, 2025 am 09:33 AM

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

神秘的JavaScript:它的作用以及為什麼重要神秘的JavaScript:它的作用以及為什麼重要Apr 09, 2025 am 12:07 AM

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

Python還是JavaScript更好?Python還是JavaScript更好?Apr 06, 2025 am 12:14 AM

Python更适合数据科学和机器学习,JavaScript更适合前端和全栈开发。1.Python以简洁语法和丰富库生态著称,适用于数据分析和Web开发。2.JavaScript是前端开发核心,Node.js支持服务器端编程,适用于全栈开发。

如何安裝JavaScript?如何安裝JavaScript?Apr 05, 2025 am 12:16 AM

JavaScript不需要安裝,因為它已內置於現代瀏覽器中。你只需文本編輯器和瀏覽器即可開始使用。 1)在瀏覽器環境中,通過標籤嵌入HTML文件中運行。 2)在Node.js環境中,下載並安裝Node.js後,通過命令行運行JavaScript文件。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境