可以用到项目的优化网站加载速度方案

简介: 可以用到项目的优化网站加载速度方案

1、合并图标,减少网络请求


合并图标是减少网络请求的常见的优化手段,网页中的小图标特征是体积小、数量多,而浏览器同时发起的并行请求数量又是有限制的,所以这些小图标会严重的影响网页的加载速度,阻碍关键内容的请求和呈现


sprite图


合并sprite图是慢工细活儿,并没有特别大的技术含量,但却是每个前端开发都必须掌握的技术。

刚入门的前端直接手动切图拼图即可。

经验丰富的前端可以尝试利用构建工具实现自动化,推荐使用。gulp.spritesmith插件

// 构建视图文件
gulp.task('sprites', function() {
    var spriteData = gulp.src(config.src)
        .pipe(plumber(handleErrors))
        .pipe(newer(config.imgDest))
        .pipe(logger({ showChange: true }))
        .pipe(spritesmith({
            cssName: 'sprites.css',
            imgName: 'sprites.png',
            cssTemplate: path.resolve('./gulp/lib/template.css.handlebars')
        }));
        var imgStream = spriteData.img
        .pipe(buffer())
        .pipe(gulp.dest(config.imgDest));    
        var cssStream = spriteData.css
        .pipe(gulp.dest(config.cssDest));    
        return merge([imgStream, cssStream]);
});

sprite图不适合移动端的响应式场景。

iconfont字体文件


iconfont字体文件是用字体编码的形式来实现图标效果,既然是文字,那就可以随意设置颜色设置大小,相对来说比sprite方案更好。但是它只适用于纯色图标。推荐使用 阿里巴巴矢量图标库


2、用base64代替图片


场景:适用于图片大小小于2KB,页面上引用图片总数不多的情况 原理:将图片转换为base64编码字符串inline到页面或css中 优势:减少http的请求次数,并可以放到后台数据库中,只传输字符串,有较多的构建工具可以直接实现 劣势:这种方法仅限于图片总数较少,而且图片大小小于2KB的情况。否则图片字符串会变得很长很长


3、图片处理


1.图片懒加载

图片是网页中流量占比最多的部分,也是需要重点优化的部分。

图片延迟加载的原理就是先不设置img的src属性,等合适的时机(比如滚动、滑动、出现在视窗内等)再把图片真实url放到img的src属性上。常用插件:基于jQ的Lazyload插件

2.图片压缩

好用的网站:

https://tinypng.com/

https://zhitu.isux.us/

http://alloyteam.github.io/gopng/


4、JS/CSS按需打包


按需打包是webpack独特的优势,如果有需要通过此种方式来管理模块之间的依赖关系,强烈推荐引入!

插件化:webpack本身非常灵活,提供了丰富的插件接口。基于这些接口,webpack开发了很多插件作为内置功能。

速度快:webpack使用异步IO以及多级缓存机制。所以webpack的速度是很快的,尤其是增量更新。

丰富的Loaders:loaders用来对文件做预处理。这样webpack就可以打包任何静态文件。

高适配性:webpack同时支持AMD/CommonJs/ES6模块方案。webpack会静态解析你的代码,自动帮你管理他们的依赖关系。此外,webpack对第三方库的兼容性很好。

代码拆分:webpack可以将你的代码分片,从而实现按需打包。这种机制可以保证页面只加载需要的JS代码,减少首次请求的时间。

优化:webpack提供了很多优化机制来减少打包输出的文件大小,不仅如此,它还提供了hash机制,来解决浏览器缓存问题。

开发模式友好:webpack为开发模式也提供了很多辅助功能。比如SourceMap、热更新等。

使用场景多:webpack不仅适用于web应用场景,也适用于WebworkersNode.js场景


webpack 如何最佳配置?


webpack官方提供的配置方法是通过module.exports返回一个json,但是这种场景不灵活,不能适配多种场景。

比如要解决:production模式和development模式,webpack的配置是有差异的,大致有两种思路。

1、两份配置文件webpack.config.production.js/webpack.config.development.js,然后不同场景下,使用不同的配置文件。

2、通过module.exports返回函数,该函数能接受参数。

相对来说,第一种更简单,但是重复配置多;第二种更灵活,推荐第二种方式。

那么,按返回函数的方式的配置代码架子如下:

module.exports = function(env) {
    return {
        context: config.context,
        entry: config.src,
        output: {
            path: path.join(config.jsDest, project),
            filename: '[name].js',
            chunkFilename: '[name].[chunkhash:8].js',
            publicPath: '/assets/' + project + '/'
        },
        devtool: "eval",
        watch: false,
        profile: true,
        cache: true,
        module: {
            loaders: getLoaders(env)
        },
        resolve: {
            alias: getAlias(env)
        },
        plugins: getPlugins(env)
    };
}

其中关键的配置这儿简单介绍如下,后续的系列博客会根据每个点详细介绍。

context:上下文。

entry:入口文件,是所有依赖关系的入口,webpack从这个入口开始静态解析,分析模块之间的依赖关系。

output:打包输出的配置。

devtools:SourceMap选项,便于开发模式下调试。

watch:监听模式,增量更新,开发必备!

profile:优化。

cache:webpack构建的过程中会生成很多临时的文件,打开cache可以让这些临时的文件缓存起来,从而更快的构建。

module.loaders:如前文介绍,loaders用来对文件做预处理。这样webpack就可以打包任何静态文件。

resolve.alias:模块别名,这样可以更方便的引用模块。

plugins:如前文介绍,webpack的一些内置功能均是以插件的形式提供。

webpack和gulp区别:

gulp是基于流的构建工具:all in one的打包模式,输出一个js文件和一个css文件,优点是减少http请求,万金油方案。

webpack是模块化管理工具,使用webpack可以对模块进行压缩、预处理、打包、按需加载等。


如何减小请求大小?


1、JS/CSS/HTML压缩


这也是常规手段,就不介绍太多,主要的方式有:

1、通过构建工具实现,比如webpack/gulp/fis/grunt等。

2、后台预编译。

3、利用第三方online平台,手动上传压缩。

无论是第二种还是第三种方式,都有其局限性,第一种方法是目前的主流方式,凭借良好的插件生态,可以实现丰富的构建任务。

在好奇心日报的项目中,我们使用webpack & gulp作为构建系统的基础。

简单介绍一下JS/CSS/HTML压缩方式和一些注意事项


JS压缩


JS压缩:使用webpack的UglifyJsPlugin插件,同时做一些代码检测。
new webpack.optimize.UglifyJsPlugin({
    mangle: {
        except: ['$super', '$', 'exports', 'require']
    }
})
CSS压缩

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
];
HTML压缩

HTML压缩:使用htmlmin压缩HTML,同时对不规范的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压缩效果

那么gzip压缩的效果有多明显呢?保守估计,在已经完成JS/CSS/HTML压缩的基础上,还能降低60-80%左右的大小。

但需要注意,gzip压缩会消耗服务器的性能,不能过度压缩。

所以推荐只对JS/CSS/HTML等资源做gzip压缩。图片的话,托管到第三方的图片建议开启gzip压缩,托管到自己应用服务器的图片不建议开启gzip压缩。


3、JS/CSS按需加载


和前面提到的按需打包不同。

JS/CSS按需打包是预编译发生的事情,保证只打包当前页面相关的逻辑。

JS/CSS按需加载是运行时发生的事情,保证只加载当前页面第一时间使用到的逻辑。

那么怎么实现按需加载呢?好奇心日报使用webpack提供的requirerequire.ensure方法来实现按需加载,值得一提的是,除了指定的按需加载文件列表,webpack还会自动解析回调函数的依赖及指定列表的深层次依赖,并最终打包成一个文件。

4dc525533eb0c97d0efe704a779e8e9c_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.jpg

webpack按需加载

上诉代码的实现效果是:只有当点击登录按钮的时候,才会去加载登录相关的JS/CSS资源。资源在加载成功后自动执行。


4、图片压缩,jpg优化


托管到应用服务器的图片压缩

可以手动处理,也可以通过gulp子任务来处理。

手动处理的话,推荐一个网站 tinypng ,压缩效果极好。

gulp子任务处理的话,推荐使用gulp-imagemin插件,自动化处理,效果也还不错。

// 图片压缩
gulp.task('images', function() {
    return gulp.src(config.src)
            .pipe(plumber(handleErrors))
            .pipe(newer(config.dest))
            .pipe(logger({ showChange: true }))
            .pipe(imagemin()) // 压缩
        .pipe(gulp.dest(config.dest));
});


托管到第三方平台的图片压缩


比如七牛云平台,他们会有一套专门的方案来对图片压缩,格式转换,裁剪等。只需要在url后面加上对应的参数即可,虽然偶尔会有一些小bug,但整体来说,托管方案比用自家应用服务器方案更优。

a00e2a8bb8a1fe8d04cc3cae715837d4_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.jpg

改变参数,实现不同程度的压缩


jpg优化


除了对图片进行压缩之外,对透明图床没有要求的场景,强烈建议将png转换为jpg,效果很明显!

如下图,将png格式化为jpg格式,图片相差差不多8倍!

a5702381737d1c970538c4a1fba1fac0_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.jpg

png转jpg,体积相差八倍

再次强调,可以转换成jpg的图片,强烈建议转换成jpg!


5、webp优化 & srcset优化


webp优化

粗略看一眼,卧槽,兼容性这么差,也就安卓浏览器及chrome浏览器对它的支持还算给力。

663a5289a3c9c7ac46771a89808032d6_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.jpg

webp兼容性

另一方面,webp优化能在jpg的基础上再降低近50%的大小。其优化效果明显。此外,如果浏览器支持webpanimation,还能对gif做压缩!

c3c649a1959349aa2d15a310a10107f8_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.jpg

普通图片webp优化

7d24cd0115664d79c9ade52cfe5faf17_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.jpg

gif图片优化

兼容性差,但效果好!最终好奇心决定尝试一下。

1、判断浏览器对webp及webpanimation的兼容性。

2、如果浏览器支持webp及webpanimation,将其替换成webp格式的图片。

鉴于浏览器对webp的支持比较局限,我们采用渐进升级的方式来优化:对于不支持webp的浏览器,不做处理;对于支持webp的浏览器,将图片src替换成webp格式。

那么如何判断webp兼容性呢?

// 检测浏览器是否支持webp
// 之所以没写成回调,是因为即使isSupportWebp=false也无大碍,但却可以让代码更容易维护
(function() {
    function webpTest(src, name) {
        var img = new Image(),
            isSupport = false,
            className, cls;
        img.onload = function() {
            isSupport = !!(img.height > 0 && img.width > 0);
            cls = isSupport ? (' ' + name) : (' no-' + name);
            className = document.querySelector('html').className
            className += cls;
            document.querySelector('html').className = className.trim();
        };
        img.onerror = function() {
            cls = (' no-' + name);
            className = document.querySelector('html').className
            className += cls;
            document.querySelector('html').className = className.trim();
        };
        img.src = src;
    }
    var webpSrc = 'data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoB\
                AAEAAwA0JaQAA3AA/vuUAAA=',
        webpanimationSrc = 'data:image/webp;base64,UklGRlIAAABXRUJQVlA4WAoAAAA\
                            SAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAA\
                            AAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA';
    webpTest(webpSrc, 'webp');
    webpTest(webpanimationSrc, 'webpanimation');
})();

借鉴modernizr,实现了检测webp/webpanimation兼容性的函数,从代码中可以看出,检测原理就是模拟下载对应格式的图片,在异步函数中可以得到兼容性结果。

接下来就是替换url为webp格式

// 获取webp格式的src
function _getWebpSrc(src) {
    var dpr = Math.round(window.devicePixelRatio || 1),
        ratio = [1, 1, 1.5, 2, 2, 2],
        elHtml = document.querySelector('html'),
        isSupportWebp = (/(^|\s)webp(\s|$)/i).test(elHtml.className),
        isSupportWebpAnimation = (/(^|\s)webpanimation(\s|$)/i).test(elHtml.className),
        deviceWidth = elHtml.clientWidth,
        isQiniuSrc = /img\.qdaily\.com\//.test(src),
        format = _getFormat(src),
        isGifWebp, isNotGifWebp, regDetailImg;
    if (!src || !isQiniuSrc || !format || format == 'webp') {
        return src;
    }
    isNotGifWebp = (format != 'gif' && isSupportWebp);
    isGifWebp = (format == 'gif' && isSupportWebpAnimation);
    // 根据屏幕分辨率计算大小
    src = src.replace(/\/(thumbnail|crop)\/.*?(\d+)x(\d+)[^\/]*\//ig, function(match, p0, p1, p2) {
        if(dpr > 1){
            p1 = Math.round(p1 * ratio[dpr]);
            p2 = Math.round(p2 * ratio[dpr]);
            match = match.replace(/\d+x\d+/, p1 + 'x' + p2)
        }
        return match;
    });
    if(isNotGifWebp || isGifWebp) {
       // 替换webp格式,首页/列表页
        src = src.replace(/\/format\/([^\/]*)/ig, function(match, p1) {
            return '/format/webp';
        });
    }
}
注意事项

1、window的屏幕像素密度不一定是整数,mac浏览器缩放之后,屏幕像素密度也不是整数。所以获取dpr一定要取整:dpr = Math.round(window.devicePixelRatio || 1);

2、ratio = [1, 1, 1.5, 2, 2, 2]表示:1倍屏使用1倍图,2倍屏使用1.5倍图,3倍屏以上都用2倍图。这儿的规则可以按实际情况来设置。

3、webp优化更适合托管到第三方的图片,简单修改参数就可以获取不同的图片。

6a7f054feff08f50bc0b72224fb8bc04_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.jpg

devicePixelRatio兼容性

srcset兼容性

93b79242f689c9ec8e2426ef3457acfe_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.jpg

srcset兼容性

如上所述,在对webp优化的时候,我们顺道模拟实现了srcset:根据屏幕像素密度来设置最适合的图片宽高。

lazysizes原本提供了srcset选项,也可以借用lazysizes的方案来实现srcset,有兴趣的可以去看看源码。


知识点


整体来说,涉及的知识面比较广:包括webpack & gulp的构建系统、图片的webp优化、服务器的gzip配置、浏览器的加载顺序、图片延迟加载方案等等。


目录
相关文章
|
8月前
|
前端开发 JavaScript UED
如何优化前端网页加载速度:最佳实践与技巧
本文探讨了如何通过优化前端网页加载速度来提升用户体验和网站性能。从资源压缩和合并、减少HTTP请求、优化图片、使用CDN加速、采用异步加载和延迟加载等方面介绍了一系列最佳实践和技巧,帮助开发者更好地优化前端性能,提升网页加载速度。
|
8月前
|
缓存 前端开发 JavaScript
如何优化前端网页加载速度:关键步骤与技巧
在当今互联网时代,网页加载速度对用户体验至关重要。本文将介绍如何通过优化前端代码和调整网页资源加载顺序等关键步骤,有效提升网页加载速度,从而提升用户满意度和网站流量。
|
2月前
|
缓存 监控 前端开发
优化 Flutter 应用启动速度的策略,涵盖理解启动过程、资源加载优化、减少初始化工作、界面布局优化、异步初始化、预加载关键数据、性能监控与分析等方面
本文探讨了优化 Flutter 应用启动速度的策略,涵盖理解启动过程、资源加载优化、减少初始化工作、界面布局优化、异步初始化、预加载关键数据、性能监控与分析等方面,并通过案例分析展示了具体措施和效果,强调了持续优化的重要性及未来优化方向。
83 10
|
2月前
|
缓存 前端开发 JavaScript
前端优化网站加载速度的具体操作流程是什么?
在实际操作过程中,需要根据网站的具体情况和需求,灵活选择和应用相应的优化方法,并不断进行测试和调整,以达到最佳的优化效果。
|
3月前
|
缓存 前端开发 网络协议
优化网站的加载速度
【10月更文挑战第8天】优化网站的加载速度
23 3
|
8月前
|
缓存 前端开发 JavaScript
使用Web前端性能优化提高网站加载效率
前端性能优化关键在于提高用户体验和降低资源消耗,Webpack是重要工具。基础优化策略包括减少HTTP请求、资源压缩与缓存、异步加载。Webpack优化配置涉及Tree Shaking、代码分割。高级策略涵盖Long-term Caching、缓存提升和插件优化。打包部署时,自动化流程和环境管理也至关重要。通过这些方法,可提升Web应用速度和体验。
197 0
|
5月前
|
缓存 前端开发 JavaScript
微前端集成优化:让所有子应用体积更小,加载更快!
【8月更文挑战第17天】微前端集成优化:让所有子应用体积更小,加载更快!
118 1
|
5月前
|
存储 缓存 Java
Android项目架构设计问题之优化业务接口数据的加载效率如何解决
Android项目架构设计问题之优化业务接口数据的加载效率如何解决
64 0
|
5月前
|
缓存 前端开发 JavaScript
优化前端性能:从渲染到加载的全方位策略
前端性能优化是提升用户体验的关键因素。本文探讨了从浏览器渲染到资源加载的各个方面,介绍了使用现代工具和技术的策略,包括减少关键渲染路径、优化资源加载和利用缓存。通过实施这些策略,可以显著提高页面响应速度,减少加载时间,提供更流畅的用户体验。
|
8月前
|
缓存 Java Android开发
构建高效的Android应用:内存优化策略解析
【5月更文挑战第25天】在移动开发领域,性能优化一直是一个不断探讨和精进的课题。特别是对于资源受限的Android设备来说,合理的内存管理直接关系到应用的流畅度和用户体验。本文深入分析了Android内存管理的机制,并提出了几种实用的内存优化技巧。通过代码示例和实践案例,我们旨在帮助开发者识别和解决内存瓶颈,从而提升应用性能。