前端優化 - 打開速度1s

先看一下網頁的加載流程:javascript

1.解析html結構
2.加載外部腳本和樣式表文件
3.解析並執行腳本(腳本會阻塞頁面的加載)
4.DOM樹構建完成 (DOMContentLoaded)
5.加載圖片等外部文件
6.頁面加載完畢 (load事件)css

THE WAY: 減小請求數量、減少請求大小html


減小請求數量
1.將小圖合併成雪碧圖(sprite)或者iconfont字體文件
2.使用base64減小請求(把圖片轉換成base64)
3.圖片延遲加載
4.JS/CSS按需打包
......前端

 

減少請求大小
1.JS/CSS/HTML 壓縮
2.gzip壓縮
3.圖片壓縮、JPG優化
4.webp優化
5.JS/CSS按需加載 (require)
......java

 

NEXT講一下具體的實現webpack


減小請求數量-->
1.sprite圖
  可使用構建工具(gulp.spritesmith插件)自動化生成。
2.base64
  即把小圖,不必發請求的轉成base64格式
3.圖片延遲加載
  圖片延遲加載的原理就是先不設置img的src屬性,等合適的時機(好比滾動、滑動、出如今視窗內等)再把圖片真實url放到img的src屬性上。
  (1) 固定寬高的圖片
  可使用lazysizes:  git

// 引入js文件
<script src="lazysizes.min.js" async=""></script>

// 非響應式 例子
<img src="" data-src="image.jpg" class="lazyload" />

// 響應式 例子,自動計算合適的圖片
<img
data-sizes="auto"
data-src="image2.jpg"
data-srcset="image1.jpg 300w,
image2.jpg 600w,
image3.jpg 900w" class="lazyload" />
// iframe 例子
<iframe frameborder="0"
class="lazyload"
allowfullscreen=""
data-src="//www.youtube.com/embed/ZfV-aYdU4uE">
</iframe>  

  (2) 固定寬高比的圖片
  不一樣設備的寬度不一樣致使高度也相應的不一樣,因此單個圖片從上往下加載完都會有抖動,每次抖動都會形成reflow(重繪),嚴重影響性能
  對此有兩種解決方案:github

  1⃣️第一種方案使用padding-top或者padding-bottom來實現固定寬高比。優勢是純CSS方案,缺點是HTML冗餘,而且對輸出到第三方不友好。web

<div style="padding-top:75%">
    <img data-src="" alt="" class="lazyload">
<div>

  2⃣️第二種方案在頁面初始化階段利用ratio設置實際寬高值,優勢是html乾淨,對輸出到第三方友好,缺點是依賴js,理論上會至少抖動一次。gulp

<img data-src="" alt="" class="lazyload" data-ratio="0.75">

  那麼,這個padding-top: 75%;和data-ratio="0.75"的數據從哪兒來呢?在你上傳圖片的時候,須要後臺給你返回原始寬高值,計算獲得寬高比,而後保存到data-ratio上。

  好奇心日報採用的第二種方案,主要在於第一種方案對第三方輸出不友好:須要對img設置額外的樣式,但第三方平臺一般不容許引入外部樣式。

  肯定第二種方案以後,咱們定義了一個設置圖片高度的函數:

// 重置圖片高度,僅限文章詳情頁
function resetImgHeight(els, placeholder) {
    var ratio = 0,
        i, len, width;

    for (i = 0, len = els.length; i < len; i++) {
        els[i].src = placeholder;

        width = els[i].clientWidth; //必定要使用clientWidth
        if (els[i].attributes['data-ratio']) {
            ratio = els[i].attributes['data-ratio'].value || 0;
            ratio = parseFloat(ratio);
        }

        if (ratio) {
            els[i].style.height = (width * ratio) + 'px';
        }
    }
}

  咱們將以上代碼的定義和調用都直接放到了HTML中,就爲了一個目的,第一時間計算圖片的高度值,下降用戶感知到頁面抖動的可能性,保證最佳效果。

  注意事項
  1⃣️、避免圖片過早加載,把臨界值調低一點。在實際項目中,並不須要過早就把圖片請求過來,尤爲是Mobile項目,過早請求不只浪費流量,也會由於請求太多,致使頁面加載速度變慢。
  2⃣️、爲了最好的防抖效果,設置圖片高度的JS代碼內嵌到HTML中以便第一時間執行。
  3⃣、根據圖片寬度設置高度時,使用clientWidth而不是width。這是由於Safari中,第一時間執行的JS代碼獲取圖片的width失敗,因此使用clientWidth解決這個問題。

4.JS/CSS按需打包
  推薦前端構建工具webpack
  http://webpack.github.io/docs/
  好奇心日報是典型的多頁應用,爲了緩存通用代碼,咱們使用webpack按需打包的同時,還利用webpack的CommonsChunkPlugin 插件抽離出公用的JS/CSS代碼,便於緩存,在請求數量和公用代碼的緩存之間作了一個很好的平衡。

 

減少請求大小-->
1.JS/CSS/HTML壓縮
  這也是常規手段,就不介紹太多,主要的方式有:
  (1) 經過構建工具實現,好比webpack/gulp/fis/grunt等。
  (2) 後臺預編譯。
  (3) 利用第三方online平臺,手動上傳壓縮。

  不管是第二種仍是第三種方式,都有其侷限性,第一種方法是目前的主流方式,憑藉良好的插件生態,能夠實現豐富的構建任務。
  在好奇心日報的項目中,使用webpack & gulp做爲構建系統的基礎。
  1⃣️: JS壓縮:使用webpack的UglifyJsPlugin插件,同時作一些代碼檢測。

new webpack.optimize.UglifyJsPlugin({
    mangle: {
        except: ['$super', '$', 'exports', 'require']
    }
})

  2⃣️: CSS壓縮:使用cssnano壓縮,同時使用postcss作一些自動化操做,好比自動加前綴、屬性fallback支持、語法檢測等。

var postcss = [
    cssnano({
        autoprefixer: false,
        reduceIdents: false,
        zindex: false,
        discardUnused: false,
        mergeIdents: false
    }),
    autoprefixer({ browers: ['last 2 versions', 'ie >= 9', '> 5% in CN'] }),
    will_change,
    color_rgba_fallback,
    opacity,
    pseudoelements,
    sorting
];

  3⃣️: HTML壓縮:使用htmlmin壓縮HTML。

// 構建視圖文件-build版本
gulp.task('build:views', ['clean:views'], function() {
    return streamqueue({ objectMode: true },
            gulp.src(config.commonSrc, { base: 'src' }),
            gulp.src(config.layoutsSrc, { base: 'src' }),
            gulp.src(config.pagesSrc, { base: 'src/pages' }),
            gulp.src(config.componentsSrc, { base: 'src' })
        )
        .pipe(plumber(handleErrors))
        .pipe(logger({ showChange: true }))
        .pipe(preprocess({ context: { PROJECT: project } }))
        .pipe(gulpif(function(file) {
            if (file.path.indexOf('.html') != -1) {
                return true;
            } else {
                return false;
            }
        }, htmlmin({
            removeComments: true,
            collapseWhitespace: true,
            minifyJS: true,
            minifyCSS: true,
            ignoreCustomFragments: [/<%[\s\S]*?%>/, 
                                    /<\?[\s\S]*?\?>/, 
                                    /<meta[\s\S]*?name="viewport"[\s\S]*?>/]
        })))
        .pipe(gulp.dest(config.dest));
});

2.gzip壓縮
  gzip壓縮也是比較常規的優化手段。前端並不須要作什麼實際的工做,後臺配置下服務器就行,效果很是明顯。若是你發現你的網站尚未配置gzip,那麼趕忙行動起來吧。
  若是瀏覽器支持gzip壓縮,在發送請求的時候,請求頭(request Headers)中會帶有Accept-Encoding:gzip。而後服務器會將原始的response進行gzip壓縮,並將gzip壓縮後的response傳輸到瀏覽器,緊接着瀏覽器進行gzip解壓縮,並最終反饋到網頁上。
  但須要注意,gzip壓縮會消耗服務器的性能,不能過分壓縮。
  因此推薦只對JS/CSS/HTML等資源作gzip壓縮。圖片的話,託管到第三方的圖片建議開啓gzip壓縮,託管到本身應用服務器的圖片不建議開啓gzip壓縮。
3.JS/CSS按需加載
  webpack的require
4.圖片壓縮和JPG優化

  https://tinypng.com/ (近乎於無損壓縮)

 

參考:http://www.jianshu.com/p/d857c3ff78d6

相關文章
相關標籤/搜索