做者:劉軼斌,騰訊應用開發 工程師
商業轉載請聯繫騰訊WeTest得到受權,非商業轉載請註明出處。
原文連接:wetest.qq.com/lab/view/34…javascript
此文總結了筆者在Web靜態資源方面的一些優化經驗。css
用戶在訪問網頁時, 最直觀的感覺就是頁面內容出來的速度,咱們要作的優化工做, 也主要是爲了這個目標。那麼爲了提升頁面加載(或者渲染)速度呢?通常來講有三個方面:html
一、代碼邏輯:優秀的代碼邏輯結構能夠有效減小渲染頁面使用的內存和速度(好比虛擬DOM),此方面不在本文討論範圍內。前端
二、SSR服務器渲染,也就是所謂的「直出」。將首屏全部內容在服務器端渲染成html靜態代碼後,直接輸出給瀏覽器,能夠有效加快用戶訪問站點時首屏的加載時間。不過此方面也不在本文討論範圍內。java
三、提高靜態文件的加載速度,這是本文會討論的點,而這方面大體又可分爲下面幾點:webpack
— 加快靜態文件下載速度ios
— 減小靜態文件的文件大小nginx
— 減小靜態文件請求數量,從而減小發起請求的次數(對於移動端頁面來講,請求的開銷比網速的開銷要大)git
最常規的優化手段之一。github
咱們在平時開發的時候,JS腳本文件和CSS樣式文件中的代碼,都會依據必定的代碼規範(好比javascript-standard-style)來提升項目的可維護性,以及團隊之間合做的效率。
可是在項目發佈現網後, 這些代碼是給客戶端(瀏覽器)識別的,此時代碼的命名規範、空格縮進都已沒有必要,咱們可使用工具將這些代碼進行混淆和壓縮,減小靜態文件的大小
這裏咱們選擇使用 Webpack,具體會在後面介紹。
在npm流行的今天,前端在進行項目開發的時候,每每會使用不少第三方代碼庫,好比jQuery,axios,weixin-js-sdk,lodash,bootstrap等等,每一個庫都有屬於本身的腳本或者樣式文件。
按照最老的方式的話,咱們會用<script>
標籤或者<style>
標籤分別引入這些庫文件,致使在打開一個頁面的時候會發起幾十個請求,這對於移動端來講是不可接受的。
在減小文件請求數量方面大體有如下三方面:
一、合併js腳本文件
二、合併css樣式文件
三、合併css引用的圖片,使用sprite雪碧圖。
對於 雪碧圖 ,咱們能夠把頁面上用到的多個細碎的小圖片合併成一個大圖片,把N個圖片請求合併成了一個。而後在css樣式中指定圖片偏移,來實現顯示不一樣的圖片,以下圖:
這裏咱們繼續選擇使用Webpack,具體會在後面介紹。
咱們的文件在壓縮合並以後,文件大小和文件數量都有了客觀的減小。可是一旦站點業務邏輯多了,或者引入的第三方庫多了以後,對於移動端來講,文件大小仍是不太樂觀。
這個時候就是gzip壓縮登場的時候啦~咱們在webpack的配置中增長gzip壓縮配置:
上面代碼會對文件大小大於10240,而且壓縮率好於0.8的js、css文件進行gzip壓縮,執行打包代碼後生成結果文件以下:
咱們能夠看到除了原有的js和css文件外,咱們還獲得了壓縮後的gz文件。
把全部這些文件一塊兒部署到服務器上。(固然也能夠直接nginx或其餘web server配置gzip壓縮)
咱們能夠看到vendor.[hash].js文件的大小顯著減小,從318kb減小到了不到100kb。
爲何使用CDN?
CDN 是一個全球(或者只有國內,具體看供應商)分佈式網絡,它把網站內容更快地傳遞給服務範圍內的一個具體位置,而每每這個具體的位置離實際的內容服務器距離很遠。舉個極端點的例子,你的網站主機在愛爾蘭(海南),而你的用戶則在澳大利亞(漠河)訪問。這時當你的用戶訪問你的網站的時候,延遲會很大,把你的(靜態)數據用 CDN 放到澳大利亞(漠河)則會很大程度上提升用戶訪問網站的體驗。
若是沒有CDN服務,咱們能夠添加Expires頭,減小DNS查找,配置ETag,使AjaX可緩存。
web前端對於xss安全漏洞必定不陌生。咱們知道Javascript語句甚至是css表達式均可能致使xss攻擊,如今不少前端會使用CSP策略來進行腳本源的限制防護。
而咱們因爲使用的cdn域名和業務域名不同:
cdn域名:cdn.xxx.qq.com
業務域名:xxx.qq.com
咱們能夠:
服務器端直接返回相應的HTTP response header頭信息;
例如:
這裏除了指定了cdn的域名源,告訴瀏覽器從這個域名加載的js文件都是可信的。同時由於咱們使用的webpack打包壓縮代碼後的一些特性,咱們還須要加上'unsafe-inline'標識。
使用CSP策略咱們能夠指定瀏覽器安全解析script、css、fonts、media等資源的源與方式。
參考資料有:
Content Security Policy Reference
使用webpack2最重要的地方就是使用它tree-shaking的特性。這個特性對於ES6的module管理有着很是優美的優化,大概能減小30%左右的包體積。
ES module和CommonJS的require模塊管理不一樣,前者是基於靜態的,然後者是動態的。
CJS:
容許動態同步 require()
導出僅在模塊執行後才知道
導出能夠在模塊初始化後添加,替換和刪除
ES module:
只容許靜態同步 import
在模塊執行以前,導入和導出已經關聯
導入和導出是不可變的
如今咱們來看一下如何使用webpack:
咱們本身寫的代碼由於在開發時須要遵循必定的代碼規範,因此會有不少多餘的換行和空格字符,甚至是便於閱讀的長變量名,這些其實對於機器(瀏覽器)來講,都不是必要的。因此咱們能夠把這些都幹掉。好比咱們寫的代碼多是這樣的:
接着咱們就使用Webpack來進行壓縮。首先,須要在工程根目錄的package.json(相信使用過npm包管理的前端同窗必定不陌生)文件中添加webpack的依賴配置:
各個工程應該按需引入須要的loader和webpack-plugin庫。有一點須要注意的是:webpack自己是沒有對各個類型的文件進行分析處理的能力的,這個時候咱們須要使用各類第三方庫的loader,好比css-loader等(固然咱們也能夠本身編寫loader)。同時webpack也有強大的第三方Plugin插件供咱們對文件進行進一步處理。
接下來咱們就能夠在scripts中指向的腳本文件裏編寫webpack對應的構建代碼了。
例如在webpackConfig配置中的plugins屬性數組中,咱們能夠添加如下配置:
而最終生成的文件結構以下:
咱們能夠看到全部樣式代碼被壓縮後抽離到了一個app.[hash].css文件中,全部js邏輯代碼按照業務邏輯和第三方庫被抽離到了app.[hash].js和vendor.[hash].js文件中。
被打包文件的內容也已經被webpack壓縮混淆,減小了加載文件的Content Size。
關於其餘的webpack用法配置,能夠查詢官方文檔和中文文檔,這裏就不一一詳細說明了
目前webpack3 和webpack4使用了新的方式打包代碼,能夠進一步提高js在瀏覽器中的執行效率。
跨域方面: CORS
咱們知道因爲現代瀏覽器安全策略的不斷完善,對跨域請求的限制也是各類各樣。
當咱們保存在靜態資源文件中的script對其餘域名發起請求時就會遇到跨域問題,若是沒有作任何措施,請求會被瀏覽器攔截。
當前主流的跨域解決方案主要是JSONP和CORS
由表可見,隨着前端不斷髮展,CORS跨域是大趨勢。
CORS須要被請求端根據請求者的host,與白名單比對後返回正確的HTTP response header頭信息。
詳情內容建議閱讀MDN的官方文檔
爲了可以對前端優化效果有一個系統的驗證,憑藉肉眼來感覺頁面響應速度確定是遠遠不夠的,咱們能夠經過一些針對服務器性能測試的產品來驗證頁面的響應時間,這裏推薦一個「壓測大師」。能夠經過配置訪問過程當中的最大人數,獲取訪問後的性能效果,如圖:
騰訊WeTest壓測大師對包含Web,H5等頁面準備了針對性的方案,解決了多數壓測人員Web頁面壓測的問題。
壓測大師服務了包括王者榮耀、龍之谷手遊、軒轅傳奇手遊、火影忍者等多款高星級手遊,也包括QQ、NOW直播等明星產品,經過基於真實業務場景和用戶行爲進行壓力測試,幫助開發者發現服務器端的性能瓶頸,進行鍼對性的性能調優,下降服務器採購和維護成本。
爲了讓外部更多產品可以享受到簡單易用的壓測產品,騰訊WeTest決定將這份服務器測試能力產品化,以產品」壓測大師「的形式,正式對外開放。目前更有低至四折的時效資源包優惠,歡迎你們使用!
點擊連接:wetest.qq.com/gaps/ 便可使用。
若是對使用當中有任何疑問,歡迎聯繫騰訊WeTest企業QQ:800024531