先看一下网页的加载流程: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