歡迎你們前往騰訊雲技術社區,獲取更多騰訊海量技術實踐乾貨哦~css
導語 : 從事前端有6年+的時間了,從最開始的美工到重構再到偏向js邏輯開發的前端開發,一直在前端這個行業裏面摸索和學習,我如今將本身這些年的一個心得體會來個系統性的梳理寫成一篇關於性能優化的主題文章,但願對你們有點幫助,也歡迎你們提出各類意見和建議。html
做者:劉勇剛 前端
前端工程師是一個最近這5-6年纔開始慢慢被互聯網公司重視起來的一個職業,能夠說是一個新興行業,我用一張簡單的思惟導圖帶你們回顧一下前端技術發展的歷程以及將來一個展望:html5
1.0時代沒什麼說的,html、css打天下的時代,那個時候你會用js開發個計算器就牛逼到不行。2.0時代是最好的時代,新技術、新思想蓬勃發展,堪稱前端的工業革命,前端人員的地位獲得了充分承認,門檻也有必定的提高。前端性能優化的涉及點從服務器到協議再到宿主環境自己都要有比較深入的認識,業界目前主要仍是以雅虎總結出來35條前端性能優化的黃金軍規(www.cnblogs.com/siqi/p/3655… 爲參考。今天我想將這些年對前端的性能優化的經驗思考總體來個串燒,帶你們鳥瞰一下前端性能優化目前的一些通行作法以及這麼作的出發點。文章初衷主要是對一些性能優化基礎知識回顧和體系梳理,不對具體技術點作深刻分析,點到爲止,我的理解不對的地方歡迎各位大神拍磚,拋磚引玉。node
引入話題前我仍是先從一個老生常談的話題開始:webpack
「從用戶輸入URl到頁面展現給用戶瀏覽器客戶端的過程當中發生了什麼?」css3
這裏用個圖表簡單描述一下幾個步驟:web
web優化的目標就是如何讓用戶更快、更簡單易用、更流暢的使用咱們的服務,對於前端開發而言就是如何讓咱們的資源體量更小、數量更精簡、內容更早呈現、交互更加人性化。ajax
web性能優化有個你們比較公認的二八原則,就是資源從服務器處理完下發到客戶端的瀏覽器上(上圖第6步)所佔的時間比例大概是整個過程的20%,也就是說服務器端能夠優化的空間的效率提高並不會很明顯,前端性能優化成爲web性能優化重點考慮的領域,我下面將會從如下幾個維度去作了本身的一個思考(跟35條軍規有必定重疊)和總結:算法
瀏覽器是一個單線程解析模式去解析渲染從服務器端拿到的html文本,css加載的過程當中會對後續的腳本資源加載形成阻塞,腳本的加載也會阻塞後續DOM結構的解析形成頁面的留白時間增加,雅虎的35條軍規中有一條就是樣式文件放在頭部,腳本文件放在DOM節點最末尾,減小阻塞。這裏還有幾個針對腳本文件的優化:
瀏覽器的事件模型的冒泡的特性(瀏覽器事件模型不清楚的自行搜索瞭解)我以爲是最牛逼的設計之一,解決了瀏覽器由於解析DOM模型不一樣步致使開發者往DOM對象註冊事件回調找不到對象的問題。
瀏覽器事件註冊有3個級別定義,DOM 0級事件註冊(利用DOM元素行內事件屬性onclick註冊事件回調),DOM 1級事件註冊(利用DOM元素對象的onclick API 在外部註冊事件回調),DOM 2級事件註冊(利用利用DOM元素對象的addEventListner/attachEvent API 在外部註冊事件回調)。這裏性能優化的建議就是利用DOM2級在目標DOM的父標籤(大部分框架是在body標籤統一註冊事件監聽)註冊回調,收攏事件監聽入口同時節約了DOM節點引用開銷。
Cookie是前端做爲先後臺登陸態校驗最一般用的緩存方案,但鑑於瀏覽器在每次都會往同域的任何資源的http請求中自動帶上cookie信息的狀況,這裏有必要進行優化一下,由於像css、js、image這些資源請求是不須要cookie信息的,會無故形成請求帶寬的浪費(想象一下咱們的cookie大小假設爲10K,100個請求就是近1M的大小,高併發下以咱們現行網絡帶寬也是蠻大的一筆負擔了)。Cookie free性能優化方案的處理方式是CDN異域靜態資源服務器部署咱們的前端css、js、image資源。
以本身目前負責的香港跨境匯款爲例
頁面路徑下的資源的請求:
CDN資源加載的請求:
經過對比CDN分開部署的資源請求並無帶上cookie信息。
瀏覽器針對domain,而非頁面page作併發鏈接限制的特性,domain hash的技術優化方案的處理方式是將資源劃分域分開部署,但由於過多的域劃分會增長多餘的DNS開銷,這裏通行的數量是3個之內。目前咱們的港菲匯款業務只有兩個域名分開部署,一個主站,一個CDN,我我的建議能夠將CDN中的圖片資源再單獨再分一個域名部署會更好些,爲何單獨把圖片抽出來,後面會講到。
針對一些界面渲染過程比較耗時的狀況下,能夠利用CSS3屬性開啓GPU來加速渲染咱們的DOM,開啓很簡單通常我是用-webkit-transform:translateZ(0)假3D屬性來喚起系統GPU加速渲染功能,關於爲何會這樣,我這裏作個簡單的解釋:
對於咱們的瀏覽器而言,拿到咱們的html文本串開始按順序解析成DOM樹,並與同步解析出來的CSS匹配生成渲染樹(跟DOM樹的節點不是一一對應,好比display:none的節點就不會插入渲染樹)
圖片來源 segmentfault.com/a/119000000…
瀏覽器將渲染樹的節點用一個圖層表示,這樣層層疊加在一塊兒生成layout,有點像ps的圖層疊加的概念(能夠經過火狐瀏覽器開發者工具3維展現更直觀),通常狀況下對節點的任何涉及尺寸的改變都會引發layout的重排重繪(重排和重繪是形成瀏覽器渲染的最大性能損耗的因素),但有種開小竈的狀況Composite Layers(複合圖層)直接交給咱們GPU中單獨的合成器進程處理,自身變化不會引發其餘層的位置變化,不會引發重排重繪。tranform 3d屬性是能夠悄悄的告訴咱們的瀏覽器把元素解析做爲複合圖層交給單獨進程去處理的。
注:這裏有個原則,不能濫用咱們的加速,由於過多開啓硬件加速會消耗更多的用戶內存空間,也會比較耗電,通常針對css3動畫建議開啓
a、通行解決方案
圖片base64編碼傳輸:圖片base64編碼後,可讓瀏覽器減小自身的一次http請求,但由於自身的一些缺陷,不能濫用(即便一個很小的圖片編碼後都會有一大串字符,增長了咱們CSS體積,性能不降反升),個人建議是針對那些全站通用或者體積很小很差整合到雪碧圖裏面的圖標進行編碼,固然還有不少不一樣的場景你們本身權衡。
圖片延時加載:主要是爲了減小首屏一次性圖片的加載量。具體作法是給圖片或者標籤設置一個私有行內屬性data-image(固然能夠本身隨便定義)存放目標圖片地址信息,監聽瀏覽器的滾動事件,標籤到了瀏覽器可視區域就將圖片地址放入圖片的src屬性中或者做爲標籤的樣式的背景圖片中展現。淘寶首頁的作法是用一個div來作延時圖片加載,經過背景圖片來展現最後的圖片。
圖片展現前:
圖片展現後:
b、緩存機制
一、給須要作離線緩存的頁面html標籤設定manifest屬性,指定緩存的配置文件 cache.appcahe(能夠設定任何擴展名,只要在服務器端配置mime-type爲text/cache-manifest就行)。
二、建立上一步指定的cache.appcache配置文件,按如下截圖說明來配置資源
三、在服務器端配置配置文件的擴展名映射的mime-type爲text/cache-manifest
appcache離線方案詬病太多,目前接入的很少,有種慢慢變棄兒的趨勢,這裏提出來讓你們權衡
a、通行解決方案
css、script、圖片壓縮:這些能夠gulp或者webpack自動化腳本里面定義腳本任務來完成。
服務器開啓gzip壓縮:通常如今服務器都有開啓Gzip壓縮,壓縮率一般都是30%以上,效果仍是不錯的。
原圖:
Gzip壓縮後:
b、頁面切片預加載方案
性能優化靜態資源維度最後一塊內容就是針對頁面,如何儘早輸出頁面模塊,減小留白時間是一個思考點。facebook應用的BigPipe方案是個很不錯的借鑑思想,還有淘寶也有首頁作了相應的切片方案,對頁面合理的分塊,在服務器和客戶端創建某種對應機制,讓各個頁面塊並行的在服務器端拼接完成並吐出來,目前我對這塊沒有太深的瞭解,這裏只是提出bigPipe的方案供你們參考。
TCP鏈接中的3次握手、慢啓動的一些特性註定了鏈接通道的利用效率成爲制約性能的一個很大的因素。由於http是基於TCP的應用協議,TCP層維度考慮還得從http幾個版本的發展歷史來看:
谷歌(叒是谷歌,牛逼)率先在09年基於TCP開發出全新SPDY應用協議,解決了多路複用請求優化、服務器推送的痛點問題,也爲後面http2.0的推出奠基了基礎。
咱們能夠作的優化:減小一些沒必要要的請求(掃除404死鏈接、304請求用咱們的長緩存機制)去優化,儘可能減小一些沒必要要的鏈接請求數。
鑑於js語言自己的靈活性,以及每一個人的開發習慣,很難有很好的一個方式去驗證開發者的代碼實現的效率(目前更多的是用打點測速的方式去監控代碼的執行時間),更多的是一種建議,你們有更好的建議能夠提出來分享。
單線程限制:利用異步回調&多線程API突破js語言單線程帶來的內存開銷利用不充分的問題,現有能夠利用的一些異步方式的回調均可以嘗試利用好比settimeout,setinterval,requestAnimationframe(推薦用它),多線程的API方式有WebWork。這裏推薦日本的一個開發者開發的一個多線程前端庫Concurrent.Thread.js(它是做者用setTimeout和setInterval來模擬的多線程,能夠自行網上搜索瞭解)。
重點優化代碼中的循環結構體:就代碼自己而言影響執行效率的大部分是循環體結構和算法設計不合理致使的時間複雜度和空間複雜度的增長。這裏放兩段實際項目中的代碼截圖來對比:
實例功能須要:實現輸入框每4個字符一個空格隔開的效果
低效實現方式,用for循環:
改進後的方式:
性能優化通常都是從技術角度去入手,但咱們的目標之一「讓用戶簡單易用」也是性能優化的一環。當技術性能缺陷難於避免的時候,做爲前端交互實現的執行者,更應該配合產品和交互設計師提出一個咱們認爲更好的交互邏輯體驗方案去讓咱們的數據加載不那麼讓用戶有等待的感知,讓咱們的提示更加的人性舒服。(交互設計師更加專業,我這裏不敢班門弄斧)
文章最後對Web3.0時代作個本身的猜測,web3.0目前在業內尚未很明肯定義,你們能夠大膽猜測前端行業將來形態。我在這先YY一下,人工智能、大數據普遍應用應該會成爲推進前端進入3.0的時代的最好契機,以此引起的前端新的革命:
(以上猜測純屬我的理解,沒有權威認證,你們能夠暢所欲言)
從 10 Gb 到 40 Gb,從百萬級到千萬級轉發,打造高性能 TGW
此文已由做者受權騰訊雲技術社區發佈,轉載請註明文章出處
原文連接:https://cloud.tencent.com/community/article/879614