前言

性能优化 ,每个工程师跑不掉的一个话题。这里是本人总结的一些优化手法,希望对大家有所帮助,感谢各位大哥????

演示demo

在线预览: http://118.25.49.69:8085/

fe-optimize 源码: https://github.com/alexwjj/fe-optimize

演示PPT

在线预览:http://118.25.49.69:8086/

fe-ppt 使用HTML做的PPT源码

前端性能的影响(长篇大论警告❗️❗️❗️)

前端性能的一个重要指标是页面加载时间,不仅事关用户体验,也是搜索引擎排名考虑的一个因素。

  • 来自Google的数据表明,一个有10条数据0.4秒能加载完的页面,变成30条数据0.9秒加载完之后,流量和广告收入下降90%。

  • Google Map 首页文件大小从100KB减小到70-80KB后,流量在第一周涨了10%,接下来的三周涨了25%。

  • 亚马逊的数据表明:加载时间增加100毫秒,销量就下降1%。所以:重铸性能之光,我辈义不容辞????

一、调试工具

磨刀不误砍柴工,读完大学再打工!

1、Network

这里可以看到资源加载详情,初步评估影响页面性能的因素。鼠标右键可以自定义选项卡,页面底部是当前加载资源的一个概览。DOMContentLoaded DOM渲染完成的时间,Load:当前页面所有资源加载完成的时间

#思考:如何判断哪些资源对当前页面加载无用,做对应优化?shift + cmd + P 调出控制台的扩展工具,添加规则

扩展工具 更多使用姿势

#瀑布流waterfall

  • Queueing 浏览器将资源放入队列时间

  • Stalled 因放入队列时间而发生的停滞时间

  • DNS Lookup DNS解析时间

  • Initial connection 建立HTTP连接的时间

  • SSL 浏览器与服务器建立安全性连接的时间

  • TTFB 等待服务端返回数据的时间

  • Content Download 浏览器下载资源的时间

2、Lighthouse

  • First Contentful Paint 首屏渲染时间,1s以内绿色

  • Speed Index 速度指数,4s以内绿色

  • Time to Interactive 到页面可交换的时间

根据chrome的一些策略自动对网站做一个质量评估,并且会给出一些优化的建议。

3、Peformance

对网站最专业的分析~后面会多次讲到

4、webPageTest

可以模拟不同场景下访问的情况,比如模拟不同浏览器、不同国家等等,在线测试地址:webPageTest

5、资源打包分析

#webpack-bundle-analyzer

npm install --save-dev webpack-bundle-analyzer
// webpack.config.js 文件
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
module.exports={plugins: [new BundleAnalyzerPlugin({analyzerMode: 'server',analyzerHost: '127.0.0.1',analyzerPort: 8889,reportFilename: 'report.html',defaultSizes: 'parsed',openAnalyzer: true,generateStatsFile: false,statsFilename: 'stats.json',statsOptions: null,logLevel: 'info'}),]
}// package.json
"analyz": "NODE_ENV=production npm_config_report=true npm run build"

#开启source-mapwebpack.config.js

module.exports = {mode: 'production',devtool: 'hidden-source-map',
}

package.json

"analyze": "source-map-explorer 'build/*.js'",
npm run analyze

二、WEB API

工欲善其事,必先利其器。浏览器提供的一些分析API至关重要

1、监听视窗激活状态

大学都刷过慕课吧?只要离开窗口视频就会暂停~

或者一些考试网站,提醒你不能离开当前窗口

再或者,这种效果~

// 窗口激活状态监听
let vEvent = 'visibilitychange';
if (document.webkitHidden != undefined) {vEvent = 'webkitvisibilitychange';
}function visibilityChanged() {if (document.hidden || document.webkitHidden) {document.title = '客官,别走啊~'console.log("Web page is hidden.")} else {document.title = '客官,你又回来了呢~'console.log("Web page is visible.")}
}document.addEventListener(vEvent, visibilityChanged, false);

其实有很多隐藏的api,这里大家有兴趣的可以去试试看:

2、观察长任务(performance 中Task)

const observer = new PerformanceObserver((list) => {for (const entry of list.getEntries()) {console.log(entry)}
})observer.observe({entryTypes: ['longtask']})

3、监听网络变化

网络变化时给用户反馈网络问题,有时候看直播的时候自己的网络卡顿,直播平台也会提醒你或者自动给你切换清晰度

var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
var type = connection.effectiveType;function updateConnectionStatus() {console.log("Connection type changed from " + type + " to " + connection.effectiveType);type = connection.effectiveType;
}connection.addEventListener('change', updateConnectionStatus);

4、计算DOMContentLoaded时间

window.addEventListener('DOMContentLoaded', (event) => {let timing = performance.getEntriesByType('navigation')[0];console.log(timing.domInteractive);console.log(timing.fetchStart);let diff = timing.domInteractive - timing.fetchStart;console.log("TTI: " + diff);
})

5、更多计算规则

DNS 解析耗时: domainLookupEnd - domainLookupStart
TCP 连接耗时: connectEnd - connectStart
SSL 安全连接耗时: connectEnd - secureConnectionStart
网络请求耗时 (TTFB): responseStart - requestStart
数据传输耗时: responseEnd - responseStart
DOM 解析耗时: domInteractive - responseEnd
资源加载耗时: loadEventStart - domContentLoadedEventEnd
First Byte时间: responseStart - domainLookupStart
白屏时间: responseEnd - fetchStart
首次可交互时间: domInteractive - fetchStart
DOM Ready 时间: domContentLoadEventEnd - fetchStart
页面完全加载时间: loadEventStart - fetchStart
http 头部大小:transferSize - encodedBodySize
重定向次数:performance.navigation.redirectCount
重定向耗时: redirectEnd - redirectStart

三、老生常谈,雅虎军规

磨好刀了,就该想想往哪里捅比较好了~ ????????????

关于雅虎军规,你知道的有多少条,平时写用到的又有哪些?针对以下规则,我们可以做很多优化工作

1、减少cookie传输

cookie传输会造成带宽浪费,可以:

减少cookie中存储的东西 静态资源不需要cookie,可以采用其他的域名,不会主动带上cookie。

2、避免过多的回流与重绘

连续触发页面回流操作

  let cards = document.getElementsByClassName("MuiPaper-rounded");const update = (timestamp) => {for (let i = 0; i <cards.length; i++) {let top = cards[i].offsetTop;cards[i].style.width = ((Math.sin(cards[i].offsetTop + timestamp / 100 + 1) * 500) + 'px')}window.requestAnimationFrame(update)}update(1000);

看下效果,很明显的卡顿

performance分析结果,load事件之后存在大量的回流,并且chrome都给标记了红色

使用fastDom进行优化,将对dom的读和写分离,合并

 let cards = document.getElementsByClassName("MuiPaper-rounded");const update = (timestamp) => {for (let i = 0; i < cards.length; i++) {fastdom.measure(() => {let top = cards[i].offsetTop;fastdom.mutate(() => {cards[i].style.width =Math.sin(top + timestamp / 100 + 1) * 500 + "px";});});}window.requestAnimationFrame(update)}update(1000);

再看下效果,很流畅~

performance分析结果,load事件之后也没有了那么多的红色标记

感兴趣的可以去了解一下fastDom:github fastdom 在线预览:fastdom demo

关于任务拆分与组合的思想,react fiber架构做的很牛逼,有兴趣的可以去了解一下调度算法在fiber中的实践

四、压缩

嗯哼哼、确定一下没有走错场子,继续继续!

1、Gzip

开启方式可参考:nginx开启gzip

还有一种方式:打包的时候生成gz文件,上传到服务器端,这样就不需要nginx来压缩了,可以降低服务器压力。可参考:gzip压缩文件&webPack配置Compression-webpack-plugin

2、服务端压缩

server.jsconst express = require('express');
const app = express();
const fs = require('fs');
const compression = require('compression');
const path = require('path');app.use(compression());
app.use(express.static('build'));app.get('*', (req,res) =>{res.sendFile(path.join(__dirname+'/build/index.html'));
});const listener = app.listen(process.env.PORT || 3000, function () {console.log(`Listening on port ${listener.address().port}`);
});
package.json"start": "npm run build && node server.js",

3、JavaScript、Css、Html压缩

工程化项目中直接使用对应的插件即可,webpack的主要有下面三个:

UglifyJS webpack-parallel-uglify-plugin terser-webpack-plugin 具体优缺点可参考:webpack常用的三种JS压缩插件。压缩原理简单的讲就是去除一些空格、换行、注释,借助es6模块化的功能,做了一些tree-shaking的优化。同时做了一些代码混淆,一方面是为了更小的体积,另一方面也是为了源码的安全性。css压缩主要是mini-css-extract-plugin,当然前面的js压缩插件也会给你做好css压缩。使用姿势:

npm install --save-dev mini-css-extract-plugin
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
plugins:[new MiniCssExtractPlugin({filename: "[name].css",chunkFilename: "[id].css"})
]

html压缩可以用HtmlWebpackPlugin,单页项目就一个index.html,性能提升微乎其微~

4、http2首部压缩

http2的特点

二进制分帧 首部压缩 流量控制 多路复用 请求优先级 服务器推送http2_push: 'xxx.jpg' 具体升级方式也很简单,修改一下nginx配置,方法请自行Google

五、webpack优化

上文中也提到了部分webpack插件,下面我再来看看还有哪些~

1、DllPlugin 提升构建速度

通过DllPlugin插件,将一些比较大的,基本很少升级的包拆分出来,生成xx.dll.js文件,通过manifest.json引用

webpack.dll.config.jsconst path = require("path");
const webpack = require("webpack");
module.exports = {mode: "production",entry: {react: ["react", "react-dom"],},output: {filename: "[name].dll.js",path: path.resolve(__dirname, "dll"),library: "[name]"},plugins: [new webpack.DllPlugin({name: "[name]",path: path.resolve(__dirname, "dll/[name].manifest.json")})]
};
package.json"scripts": {"dll-build": "NODE_ENV=production webpack --config webpack.dll.config.js",},
#2、splitChunks 拆包
optimization: {splitChunks: {cacheGroups: {vendor: {name: 'vendor',test: /[\\/]node_modules[\\/]/,minSize: 0,minChunks: 1,priority: 10,chunks: 'initial'},common: {name: 'common',test: /[\\/]src[\\/]/,chunks: 'all',minSize: 0,minChunks: 2}}}},

六、骨架屏

用css提前占好位置,当资源加载完成即可填充,减少页面的回流与重绘,同时还能给用户最直接的反馈。图中使用插件:react-placeholder

关于实现骨架屏还有很多种方案,用Puppeteer服务端渲染的挺多的

使用css伪类:只要css就能实现的骨架屏方案

等等

七、窗口化

原理:只加载当前窗口能显示的DOM元素,当视图变化时,删除隐藏的,添加要显示的DOM就可以保证页面上存在的dom元素数量永远不多,页面就不会卡顿

图中使用的插件:react-window

安装:npm i react-window

引入:import { FixedSizeList as List } from 'react-window';

使用:

const Row = ({ index, style }) => (<div style={style}>Row {index}</div>
);const Example = () => (<Listheight={150}itemCount={1000}itemSize={35}width={300}>{Row}</List>
);

八、缓存

1、http缓存

keep-alive

判断是否开启:看response headers中有没有Connection: keep-alive 。

开启以后,看network的瀑布流中就没有 Initial connection耗时了

nginx设置keep-alive(默认开启)

#0 为关闭
#keepalive_timeout 0;
#65s无连接 关闭
keepalive_timeout 65;
#连接数,达到100断开
keepalive_requests 100;

Cache-Control / Expires / Max-Age 设置资源是否缓存,以及缓存时间

Etag / If-None-Match 资源唯一标识作对比,如果有变化,从服务器拉取资源。如果没变化则取缓存资源,状态码304,也就是协商缓存

Last-Modified / If-Modified-Since 通过对比时间的差异来觉得要不要从服务器获取资源

更多HTTP缓存参数可参考:使用 HTTP 缓存:Etag, Last-Modified 与 Cache-Control

2、Service Worker

借助webpack插件WorkboxWebpackPlugin和ManifestPlugin,加载serviceWorker.js,通过serviceWorker.register()注册

new WorkboxWebpackPlugin.GenerateSW({clientsClaim: true,exclude: [/\.map$/, /asset-manifest\.json$/],importWorkboxFrom: 'cdn',navigateFallback: paths.publicUrlOrPath + 'index.html',navigateFallbackBlacklist: [new RegExp('^/_'),new RegExp('/[^/?]+\\.[^/]+$'),],
}),new ManifestPlugin({fileName: 'asset-manifest.json',publicPath: paths.publicUrlOrPath,generate: (seed, files, entrypoints) => {const manifestFiles = files.reduce((manifest, file) => {manifest[file.name] = file.path;return manifest;}, seed);const entrypointFiles = entrypoints.app.filter(fileName => !fileName.endsWith('.map'));return {files: manifestFiles,entrypoints: entrypointFiles,};},
}),

九、预加载 && 懒加载

1、preload

就拿demo中的字体举例,正常情况下的加载顺序是这样的:

加入preload:

2、prefetch

场景:首页不需要这样的字体文件,下个页面需要:首页会以最低优先级Lowest来提前加载

加入prefetch:

需要的页面,从prefetch cache中取

webpack也是支持这两个属性的:webpackPrefetch 和 webpackPreload

#3、懒加载

#图片

机械图片

渐进式图片(类似高斯模糊) 需要UI小姐姐出稿的时候指定这种格式

响应式图片

原生模式:

<img src="./img/index.jpg" sizes="100vw" srcset="./img/dog.jpg 800w, ./img/index.jpg 1200w"/>

#路由懒加载

通过函数 + import实现

const Page404 = () => import(/* webpackChunkName: "error" */'@views/errorPage/404');

十、ssr && react-snap

  • 服务端渲染SSR,vue使用nuxt.js,react使用next.js

  • react-snap可以借助Puppeteer实现先渲染单页,然后保留DOM,然后发送到客户端

十一、体验优化

#白屏loading loading.html

需要自取哦,还有种方式,使用webpack插件HtmlWebpackPlugin将loading资源插入到页面中

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Loading</title><style>body {margin: 0;}#loadding {position: fixed;top: 0;bottom: 0;display: flex;width: 100%;align-items: center;justify-content: center;}#loadding > span {display: inline-block;width: 8px;height: 100%;margin-right: 5px;border-radius: 4px;-webkit-animation: load 1.04s ease infinite;animation: load 1.04s ease infinite;}@keyframes load {0%,100% {height: 40px;background: #98beff;}50% {height: 60px;margin-top: -20px;background: #3e7fee;}}</style></head><body><div id="loadding"><span></span><span style="animation-delay: 0.13s"></span><span style="animation-delay: 0.26s"></span><span style="animation-delay: 0.39s"></span><span style="animation-delay: 0.52s"></span></div></body><script>window.addEventListener("DOMContentLoaded", () => {const $loadding = document.getElementById("loadding");if (!$loadding) {return;}$loadding.style.display = "none";$loadding.parentNode.removeChild($loadding);});</script>
</html>

原文链接:

https://alexwjj.github.io/views/fe/others/%E5%89%8D%E7%AB%AF%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96.html#%E4%BA%8C%E3%80%81web-api

前端学习笔记????

最近花了点时间把笔记整理到语雀上了,方便同学们阅读:公众号回复笔记或者简历

最后

1.看到这里了就点个在看支持下吧,你的「点赞,在看」是我创作的动力。

2.关注公众号前端壹栈,回复「1」加入前端交流群!「在这里有好多前端开发者,会讨论前端知识,互相学习」!

3.也可添加公众号【前端壹栈】,一起成长

拯救你的年底 KPI:前端性能优化相关推荐

  1. (译)2019年前端性能优化清单 — 上篇

    (译)2019年前端性能优化清单 - 上篇 (译)2019年前端性能优化清单 - 中篇 (译)2019年前端性能优化清单 - 下篇 写在译前:首先介绍一下我自己,一个跨行业的.完全非科班生的文科单身狗 ...

  2. 2019年前端性能优化清单

    由于全文篇幅太长,无法将所有内容一次性发布完,所以计划分成上.中.下三个篇章.上篇包括( 计划和度量.制定现实的目标 和 定义环境 ),中篇包括( 资源优化.构建优化 和 交付优化 ),下篇包括( H ...

  3. 深度讲解:web前端性能优化

    一.课程简介: 1.课程大纲 涉及到的分类 网络层面 构建层面 浏览器渲染层面 服务端层面 涉及到的功能点 资源的合并与压缩 图片编解码原理和类型选择 浏览器渲染机制 懒加载预加载 浏览器存储 缓存机 ...

  4. 大型网站技术架构(3):WEB 前端性能优化

    上次说到了性能优化策略,根据网站的分层架构,可以大致的分为 web 前端性能优化,应用服务器性能优化,存储服务器性能优化三大类 这次来说一下 web 前端性能优化,一般来说,web 前端就是应用服务器 ...

  5. 前端性能优化——从 10 多秒到 1.05 秒

    https://lishaoy.net 关于 性能优化 是个大的面,这篇文章主要涉及到 前端 的几个点,如 前端性能优化 的流程.常见技术手段.工具等. 提及 前端性能优化 ,大家应该都会想到 雅虎军 ...

  6. 移动H5前端性能优化指南[转]

    移动H5前端性能优化指南 米随随2015.01.23 移动H5前端性能优化指南 概述 1. PC优化手段在Mobile侧同样适用 2. 在Mobile侧我们提出三秒种渲染完成首屏指标 3. 基于第二点 ...

  7. WEB前端性能优化小结

    1. 请减少HTTP请求 基本原理: 在浏览器(客户端)和服务器发生通信时,就已经消耗了大量的时间,尤其是在网络情况比较糟糕的时候,这个问题尤其的突出. 一个正常HTTP请求的流程简述:如在浏览器中输 ...

  8. 前端性能优化最佳实践(转)

    转载请注明: 转载自WEB前端开发(www.css119.com)-关注常见的WEB前端开发问题.最新的WEB前端开发技术(webApp开发.移动网站开发).最好的WEB前端开发工具和最全的WEB前端 ...

  9. 前端性能优化:使用媒体查询加载指定大小的背景图片

    日期:2013-7-8  来源:GBin1.com 直到CSS @supports被广泛支持,CSS媒体查询的使用接近于CSS中写逻辑控制.我们经常用CSS媒体查询来根据设备调整CSS属性(通常根据屏 ...

  10. 如何给网站瘦身?图文并茂的前端性能优化指南

    提高网站的速度对网站的成功有巨大的影响,因为网站的加载速度直接影响到用户体验和搜索引擎排名.Browser Diet 是一个非常好的指南,列出了前端性能优化的各种技巧和工具. 您可能感兴趣的相关文章 ...

最新文章

  1. Linux shell类型
  2. JZOJ 100026. 【NOIP2017提高A组模拟7.7】图
  3. 若S作主串,P作模式串,试分别写出利用BF算法和KMP算法的匹配过程。
  4. 基于keras中IMDB的文本分类 demo
  5. 【转载】用廉价的315M遥控模块实现数据传输
  6. 【送给Git初学者】
  7. ACL 2010-2020研究趋势总结
  8. java 数据结构 迷宫_JAVA数据结构与算法之递归(一)~ 迷宫问题
  9. 语言把数据写入csv文件_把JSON/CSV文件打造成MySQL数据库
  10. 修改Launcher2欢迎页面字符重叠
  11. 辨异 —— 有两人生日在同一天、只有两人生日在同一天
  12. linux长ping然后保存,Linux下长时间ping网络加时间戳并记录到文本
  13. 中标麒麟系统u盘安装_中标麒麟u盘安装系统教程
  14. 线面图标设计样式解析
  15. 数据中心IDC产业研究报告:碳中和背景下,IDC产业链的破局之路
  16. 我想吃掉你的胰脏--影片--观后感
  17. [转载]2016美国数学建模MCM F题(政策)翻译:难民移入政策建模
  18. 日本海淘转运运输方式对比及如何选择转运渠道
  19. 通过网格拆分高德地图
  20. 《观察与思考》:相信中国,寻找下一个比尔·盖茨

热门文章

  1. 【dp专题】在经历了时空扭曲后的总结
  2. 了解聚类是什么。聚类方法:k-means、核聚类、层次聚类、谱聚类
  3. python中表示嵌套语句快_Python编程(8)——if语句的嵌套,语言,程序设计,8if
  4. IP访问控制列表配置
  5. python ssh实时交互_python SSH客户端的交互式和非交互方式
  6. 如何解决医美行业获客难得问题,我是一名医美行业的营销人员
  7. 深度学习在超分辨率重建上的应用SRCNN,FSRCNN,VDSR,DRCN,SRGAN
  8. 心算(手算)开平方,比较有用
  9. C语言 goto语句
  10. Python基础的学习和简单爬虫的编写