day-090-ninety-20230612-函数式编程-数据类型检测-网络层优化
函数式编程
-
函数式编程 && 命令式编程
-
函数式编程:把具体的操作过程“封装”到一个函数中,我们无需关注内部是如何处理的(How),只需要关注处理的结果(What)即可;
// 如果是依次迭代数组每一项,则函数式编程更加的方便。 let arr = [10,20,30,40] arr.forEach((item,index)=>{ console.log(`item-->`, item); })
- 使用便捷,开发效率高。
- 减少页面冗余代码,低耦合高内聚。
-
命令式编程:具体如何去处理,是由自己实现及掌控的,关注How的过程!
let arr = [10,20,30,40] for(let i=0;i<arr.length;i++){ console.log(arr[i],i); }
-
操作灵活,可以自主把控处理的每一个步骤。
-
对于一些复杂的处理逻辑,还是要使用命令式编程,自己去管控操作的步骤。
// 但是对于一些复杂的处理逻辑,还是要使用命令式编程,自己去管控操作的步骤 //隔一项打印一次-函数式编程-每一项都会被遍历到,但非条件要求,就不执行打印的操作。 let arr = [10,20,30,40] arr.forEach((item, index) => { if (index % 2 === 0) { console.log(item) } }) //隔一项打印一次-函数式编程-可以只遍历需要进行打印的项。 let arr = [10,20,30,40] for (let i = 0; i < arr.length; i += 2) { console.log(arr[i]) }
-
-
处理性能一般比函数式编程式要好。
- 例如:forEach循环要慢于for循环。
-
-
总结:处理的数据量“较多”的情况下,使用命令式编程来提高性能!操作逻辑较为复杂,需要自己灵活把控处理步骤的情况下,也使用命令式编程!其余情况,优先推荐函数式编程!
// 需求:循环5次。 new Array(5).fill(null).forEach((item, index) => { console.log(`index-->`, index); });
- new Array(数字)创建一个长度为指定数字的稀疏数组。
- Array.prototype.forEach()等是无法处理稀疏数组的。
- 基于Array.prototype.fill(指定值)可以把指定值填充到稀疏数组中把其变为密集数组。
-
-
匿名函数具名化。
-
特点:原本应该是匿名函数「例如:自执行函数、函数表达式、回调函数等」,但是我们会为其设置一个名字。
//这样创建函数,因为变量提升的机制,导致函数可以在`定义的代码`之前或之后执行都可以,逻辑不严谨。 fn() function fn() { console.log(`fn;`); } fn()
//基于函数表达式的方式创建函数,可以抵消变量提升的影响,函数只能在创建的代码后面执行! fn(); //1函数式编程.js:44 Uncaught ReferenceError: Cannot access 'fn' before initialization; const fn = function () { console.log(`fn;`); };
//匿名函数具名化:原本应该是一个匿名函数,但是现在我们给其设置了名字。 fn(); //1函数式编程.js:44 Uncaught ReferenceError: Cannot access 'fn' before initialization; const fn = function () { console.log(`fn;`); };
- 更规范的操作方式。让函数不能在定义之前被调用,会报错,会让错误出现,提示修改。
- 有助于匿名函数的递归操作。
-
arguments.callee指代函数本身
// 匿名函数的递归操作-非严格模式-arguments.callee: let n = 12; (function () { if (n >= 15) { return; } n++; arguments.callee();//arguments.callee指代函数本身。 })(); console.log(n);
// 匿名函数的递归操作-严格模式-arguments.callee: 'use strict' let n = 12; (function () { if (n >= 15) { return; } n++; arguments.callee();//arguments.callee指代函数本身,严格模式下会报错。//Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them })(); console.log(n);
// 匿名函数的递归操作-严格模式-可以使用匿名函数具名化指代匿名函数本身。 // 方便匿名函数实现递归 'use strict' let n = 12; (function fn() { if (n >= 15) { return; } n++; fn(); })(); console.log(n);
-
-
即便具名化,函数也没有在外层作用域中声明,导致在外面依然是用不了的!
// 即便具名化,函数也没有在外层作用域中声明,导致在外面依然是用不了的! (function fn(){ })() console.log(fn);//Uncaught ReferenceError: fn is not defined;//即便具名化,函数也没有在外层作用域中声明「导致在外面依然是用不了的」
-
匿名函数具名化,可以在函数内部使用这个名字来指代匿名函数,代表当前函数本身!
// 匿名函数具名化,可以在函数内部使用这个名字来指代匿名函数,代表当前函数本身! (function fn(){ console.log(fn);//可以在函数内部使用这个名字来指代匿名函数,代表当前函数本身! })()
/* //这样创建函数,因为变量提升的机制,导致函数可以在`定义的代码`之前或之后执行都可以,逻辑不严谨。 fn() function fn() { console.log(`fn;`); } fn() */ /* //基于函数表达式的方式创建函数,可以抵消变量提升的影响,函数只能在创建的代码后面执行! fn()//1函数式编程.js:44 Uncaught ReferenceError: Cannot access 'fn' before initialization; const fn = function (){ console.log(`fn;`); } */ /* //匿名函数具名化:原本应该是一个匿名函数,但是现在我们给其设置了名字。 fn()//1函数式编程.js:44 Uncaught ReferenceError: Cannot access 'fn' before initialization; const fn = function (){ console.log(`fn;`); } */ /* // 即便具名化,函数也没有在外层作用域中声明,导致在外面依然是用不了的! (function fn(){ })() console.log(fn);//Uncaught ReferenceError: fn is not defined; */ /* // 匿名函数具名化,可以在函数内部使用这个名字来指代匿名函数,代表当前函数本身! (function fn(){ console.log(fn);//可以在函数内部使用这个名字来指代匿名函数,代表当前函数本身! })() */ /* // 非严格模式: let n = 12; (function () { if (n >= 15) { return; } n++; arguments.callee();//arguments.callee指代函数本身。 })(); console.log(n); */ /* // 严格模式: 'use strict' let n = 12; (function () { if (n >= 15) { return; } n++; arguments.callee();//arguments.callee指代函数本身,严格模式下会报错。//Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them })(); console.log(n); */ /* // 严格模式-可以使用匿名函数具名化指代匿名函数本身。 'use strict' let n = 12; (function fn() { if (n >= 15) { return; } n++; fn(); })(); console.log(n); */ /* // 不允许直接修改函数名对应的值,fn表示匿名函数本身。 (function fn() { fn=10; console.log(fn);//fn依旧是匿名函数本身。//不允许直接修改函数名对应的值,fn表示匿名函数本身。 })(); */ /* //如果匿名函数中函数名被用其它方式声明,则会以其它声明的为主。 (function fn() { let fn=10; console.log(`fn-->`, fn);//10//如果被用其它方式声明,则会以其它声明的为主。 })(); */
-
数据类型检测
typeof
-
typeof数据类型检测的底层机制
-
特点1:返回的结果是字符串,字符串中包含了对应的数据类型
typeof typeof typeof [1,2,3]
//"string"
-
特点2:按照计算机底层存储的二进制进行检测「效率高」
- 000
对象
; - 1
整数
; - 010
浮点数
; - 100
字符串
; - 110
布尔
; - 000000…
null
; - -2^30
undefined
; - …
- typeof按照二进制进行检测的时候,认为以“000”开始的就是对象类型
- 因为null存储的是64个零,所以被识别为对象,导致:typeof null -> “object”
- 如果检测出来是对象,再去看是否实现了call方法;如果实现了,说明其是一个函数对象,返回“function”;
- 如果没有实现call,都返回“object”;
- 000
-
特点3:typeof null -> “object”
-
特点4:typeof 对象 -> “object” && typeof 函数 -> “function”
- typeof不能检测null,也无法对“对象”进行细分(除函数对象外)
-
特点5:typeof 未被声明的变量 -> “undefined”
-
typeof在实战中的运用:
-
检测除null以外的原始值类型
-
笼统的校验是否为对象
const isObject = function isObject(value) { if (value === null) { return false; } return /^(object|function)$/.test(typeof value); };
-
检测是否为函数 => if(typeof obj===“function”){…}
// https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Operator_precedence#汇总表 const isFunction = function isFunction(value) { return typeof value === `function`; };
-
处理浏览器兼容「ES6+语法规范,都不兼容IE」
//需求:获取对象所有的私有属性-不兼容IE浏览器。 let obj = { name: "obj", age: 15, [Symbol("AA")]: 100, }; let keys = Reflect.ownKeys(obj); console.log(keys);
//需求:获取对象所有的私有属性-兼容IE浏览器。 let obj = { name: "obj", age: 15, [Symbol("AA")]: 100, }; let keys = Object.getOwnPropertyNames(obj); if (typeof Symbol !== "undefined") { // 非IE浏览器。 keys = keys.concat(Object.getOwnPropertySymbols(obj)); } console.log(keys);
- 使用typeof检测Symbol,是因为IE等低版本浏览器中,没有Symbol。直接访问Symbol,会报错,导致报错行后续代码不会再执行。
- 在浏览器中,如果直接访问一个未被声明的变量,就会报错,导致后续代码不再执行。
- 使用typeof检测Symbol,是因为IE等低版本浏览器中,没有Symbol。直接访问Symbol,会报错,导致报错行后续代码不会再执行。
-
-
-
所有的数据类型值,在计算机底层都是以 2进制 格式进行存储「undefined比较特殊 」
-
进制:
- 2~36
- 2 : 0/1
- 3 : 0/1/2
- …
- 8: 0~7
- 10: 0~9
- 16 : 0~9 A-F
- …
- 2~36
-
操作系统
- 32位
- 64位
JS中数据类型检测汇总
-
JS中数据类型检测汇总
-
typeof 变量
-
对象变量 instanceof 构造函数
//instanceof console.log([] instanceof Array);//true console.log([] instanceof Object);//true console.log(/0/ instanceof Array);//false
- 原本的意义是用来检测“某个对象是否是相应类的实例”,只不过针对于这个特点,我们可以用其检测一些数据类型
- 检测是否为数组:值 instanceof Array
- 检测是否为正则:值 instanceof RegExp
- …
- 也就是基于 instanceof ,可以弥补 typeof 不能细分对象的缺陷!
- 特点:
- 无法检测原始值类型,返回结果都是false;
- 原本不是检测数据类型的,现在非要让其检测类型,所以检测的结果不一定精准;
- 原理:
-
依次查找对象的原型链(proto),一直到 Object.prototype ,在此过程中,如果 构造函数.prototype 出现在了其原型链的某个环节,则说明 当前对象 是此构造函数的一个实例,检测结果就是true!
/* //准。 let obj = {} console.log(obj instanceof Array);//false */ // 不准。 let obj = {} obj.__proto__=Array.prototype//Object.setPrototypeOf(obj,Array.prototype) console.log(obj instanceof Array);//true;
-
- 原本的意义是用来检测“某个对象是否是相应类的实例”,只不过针对于这个特点,我们可以用其检测一些数据类型
-
constructor
// constructor console.log([].constructor === Array);//true; console.log([].constructor === Object);//false;//只有对象的原型链是直接指向Object.prototype原型的,则其constructor属性值才是Object。或者其本身所属类的原型对象上没有constructor,一层层往上查找,才找到了Object.constructor。一个对象的constructor为Object的,我们称之为标准普通对象或纯粹的对象。
- 获取对象的构造函数,从而判断是否是属于某一个数据类型
- 只不过这种方式我们一般很少去使用,因为 constructor 值是可以被更改的「修改值的成本低」,一但被更改,则检测结果是不准确的!
- 获取对象的构造函数,从而判断是否是属于某一个数据类型
-
Object.prototype.toString.call([value])
-
不仅仅 Object.prototype 上有 toString 方法,在 Number/String/Boolen/Array/Function… 的原型对象上,也有 toString 方法,只不过其它原型上的toString方法都是用来转换为字符串的,只有Object.prototype.toString是用来检测数据类型的
let obj = {ang:100} obj.toString() //obj先基于原型链,找到Object.pprototype.toString(),把toString()执行,方法中的this是obj。
-
把 Object.prototype 上的 toString 方法执行,让方法中的 this 指向要检测的数据值,这样就可以返回此数据值的数据类型 -> “[object ?]”
特点:精准且强大「唯一不足就是写起来麻烦一丢丢」- “?”一般情况下,就是检测值所属的构造函数(前提:内置的构造函数)
- 如果被检测的值具备 Symbol.toStringTag 这个属性,那么属性值是啥,最后检测结果中的“?”就是啥
-
此办法虽然很不错,但是也不是所有的数据类型检测都使用这个办法,一般来讲:需要笼统的检测或者按照大的类别去检测,使用 typeof 会更方便,而需要很精准检测的时候,使用 toString 会更好!
-
// 检测是否是纯粹对象。 const toString = Object.prototype.toString; const isPlainObject = function isPlainObject(obj) { //先校验:如果基于toString.call()检测结果都不是`[object Object]`,则一定不是纯粹对象。 if (toString.call(obj) !== "[object Object]") { return false; } // Object.create(null)返回的也是一个纯粹的对象。 let proto = Object.getPrototypeOf(obj); if (!proto) { return true; } let Ctor = "constructor" in obj && obj.constructor; return Ctor === Object; };
-
-
快捷方法:
- isNaN 检测是否为有效数字
- Array.isArray 检测是否为数组
- …
网络层优化
- 如何部署一个项目:
- 购卖服务器。
- 所谓服务器就是一台性能好的主机。
- 多个CPU核心。
- 24小时不间断运行。
- 会热,所以需要散热。
- 散热,空调房。
- 24小时不断网。
- 会热,所以需要散热。
- 一般个人电脑也就一个CPU。
- 但服务器一般多个CPU。
- 买云服务器
- 阿里云/腾讯云服务器 - 云服务器ECS。
- 服务器有一个外网IP:别人基于外网IP就可以访问到服务器。
- 在服务器上安装一些需要的工具-慎重。
- 如输入法,别乱按照,可以收集数据及占用一些端口。
- 操作系统:linux、Ubuntu乌班图、windows server。
- 推荐用linux。
- 发布工具:nginx、apache、IIS。
- 前端推荐用nginx。
- 数据库:mongodb、MySQL、SQLServer、Oracle。
- 一般MySQL比较多,比较主流,nodejs也支持。
- 和后端语言配置的东西:nodejs、…
- 把我们编写的代码上传到服务器。
- FTP上传。
- FileZilla。
- FTP上传。
- 在服务器上进行部署。
- 一台服务器上可以部署多个项目。
- 我们需要基于端口号区分不同的项目。
- 端口号取值范围:0~65535,其中比较重要的端口号:80、443、21。
- 阿里云/腾讯云服务器 - 云服务器ECS。
- 截止目前,其它人可以基于
http://外网IP:端口号
这样的地址访问我们的项目了!
- 所谓服务器就是一台性能好的主机。
- 购卖域名
- 域名:就是给不好记忆的外网IP,起一个好记的名字。
- 购买域名后,需要做域名解析。
- 域名解析就是让域名和外网IP关联在一起。
- 解析记录在DNS服务器上。
- 一定要记得域名备案。
- 这样,别人就可以基于域名访问到我们的项目了!
- 购卖服务器。
基础知识扫盲
-
外网IP、内网IP(局域网IP)。
- 局域网:同一个外部网络,基于路由器等设备,构建的局域网络。
- 例如:一起连的同一个路由器或wiff。
- IP地址就是用来区分,两只一个局域网下不同设备的。
- 在相同局域网内的设备可以互相访问。
- 作用:
- 移动端的真机调试。
- 让手机和电脑处于同一个局域网下。
- 把电脑作为服务器,发布项目,找到电脑的局域网IP。
- windows:
ipconfig -all
- 一般是看IPv4地址。
- mac:网络设置中查找。
- windows:
- 手机端可以基于这个IP,直接访问同一个局域网下的设备。
- 有时候需要关闭电脑的防火墙。
- 把电脑作为服务器,发布项目,找到电脑的局域网IP。
- 让手机和电脑处于同一个局域网下。
- 公司平时开发的时候,一般都是在内网环境下开发。
- 只有连接公司的内网,才可以调取接口数据等。
- 回到家后,如果想继续连接公司的内网,就需要VPIN!
- 只有连接公司的内网,才可以调取接口数据等。
- 移动端的真机调试。
- 外网:只要有网络,就可以访问!
- 除非自己做限制,比如设置防火墙。
- 局域网:同一个外部网络,基于路由器等设备,构建的局域网络。
-
域名的分类
- 顶级域名: qq.com
- 只需要购买顶级域名即可,其余都是在域名解析的时候自己手动分配的。
- 一级域名:www.qq.com
- 二级域名:sports.qq.com
- 三级域名:kbs.sports.qq.com
- …
- 顶级域名: qq.com
-
域名后缀的含义
- .com 国际域名
- .cn 中国域名
- .net 系统
- .
个人网站步骤
- 买服务器 公网IP:124.23.16.8
- 基于FTP把写好的代码上传到服务器上。
- 部署项目-指定端口号
- 个人博客:80
- 毕设项目:443
- 计划管理:81
- 此时客户端-浏览器可以基于:
http://124.23.16.8:80/index.html
访问到我们的代码。- URL地址解析。
- 确认该URL是否是一个合法的地址。
- 缓存检查。
- 查看浏览器是否有该URL的资源的缓存。
- DNS解析。
- 到DNS服务器上,找到外网IP。
- TCP的三次握手。
- 浏览器与外网IP对应的服务器产生联系。
- 客户端和服务器之间的数据通信。服务器把资源给到浏览器。
- TCP四次挥手。
- 把浏览器和服务器之间的连接通道断开。
- 客户端处理并渲染服务器返回的信息。
- 可以看
《图解HTT》
这本电子书。
- URL地址解析。
步骤
- 第一步:URL地址解析。
- http://www.xxx.com:80/index.html?lx=1&from=weixin#video
- URI/URL/URN
- URI: 统一资源标识符。
- URL与URN的统称。
- 平时我们看到的URI,其实集散控制系统的就是URL。
- URL与URN的统称。
- URL:统一资源定位符。
- 网址。
- URN:统一资源名称。
- 如图书编号。
- URI: 统一资源标识符。
- 解析信息:
- 传输协议:
- 作用:负责客户端和服务器端之间信息的传输(可以理解为快递小哥)。
- 分类:
- http:即HyperText Transfer Protocol,超文本传输协议。
- 除传输文本内容外,还可传输图片和音视频等。
- https:即Hypertext Transfer Protocol Secure,HTTP+SSL,更安全的传输协议,经过加密处理。
- ftp:即File Transfer Protocol,文件传输协议,主要用于往服务器上,上传和下载内容。
- http:即HyperText Transfer Protocol,超文本传输协议。
- 域名:
- 端口号
- 作用:区分相同服务器上部署的不同项目的,取值范围0~65535宰。
- 浏览器有默认端口号机制:我们在地址栏中输入URL地址,如果没有写端口号,则浏览器会根据当前的传输协议,自动把端口号加上!
- http -> 80
- https -> 443
- ftp -> 21
- 作用:区分相同服务器上部署的不同项目的,取值范围0~65535宰。
- 请求资源的路径名称。
- 问号传参信息
- 哈希值
- Hash值。
- 传输协议:
辅助知识点
- 辅助知识点1:URL地址的编译(编码和解码)
- 基于encodeURI/decodeURI对整个URL进行编码解码
前端性能优化方案
-
前端性能优化方案:
- 减少 HTTP 请求:合并和压缩文件、使用雪碧图或字体图标减少图片请求、使用 CSS 和 JavaScript 文件的最小化版本等。
- 使用缓存:使用浏览器缓存和服务器缓存来减少对服务器的请求,减少重复加载资源的次数。
- 延迟加载:对于大型的或不是首要显示的内容,延迟加载可以提高初始页面加载速度,例如图片懒加载、按需加载等。
- 压缩资源:压缩 HTML、CSS、JavaScript 和图片等资源,减小文件大小,提高加载速度。
- 使用 CDN 加速:使用内容分发网络(CDN)来加速静态资源的传输,将资源分发到离用户更近的服务器上。
- 预加载和预渲染:通过预加载相关资源或预渲染页面来提前获取所需内容,减少用户操作时的延迟。
- 使用响应式设计:通过响应式布局和媒体查询,使网页能够适应不同屏幕大小的设备,提供更好的用户体验。
- 优化图片:使用适当的图片格式、压缩图片大小、使用懒加载或按需加载等技术来优化图片加载。
- 优化 JavaScript 执行:避免长时间执行的 JavaScript 代码,使用节流和防抖等技术控制事件频率,减少不必要的计算和操作。
- 使用异步加载:使用异步加载 JavaScript 和 CSS 文件,避免阻塞页面渲染。
- 优化渲染性能:减少重排和重绘,使用 CSS 动画代替 JavaScript 动画,使用虚拟列表或分页加载等技术优化大量数据的展示。
- 优化字体加载:使用字体子集、使用适当的字体格式,避免在页面加载时阻塞渲染。
- 监控和优化网页性能:使用性能监控工具分析网页加载过程中的性能瓶颈,进行针对性的优化。
-
按步骤来做:
- URL地址解析。
- 要请求地址写好,最好先预编码好。
- 方便浏览器减少地址的解析时间。(感觉没能提高多少速度)。
- 减少HTTP请求-使用雪碧图或字体图标减少图片请求。
- 而不是一个文字编码或一个小图,都要请求一次。
- 减少HTTP请求-合并文件,比如把几个css文件合并成一个css文件。把多个js文件合并成一个。
- 这个是借由weback及模块引入来完成的。
- 减少HTTP请求-优化字体加载:使用字体子集、使用适当的字体格式,避免在页面加载时阻塞渲染。
- 字体文件一般都有点大,以M为单位,最好少使用一点。或者直接使用系统字体。
- 字体子集化:只加载页面中使用到的字体字符,可以减小字体文件大小,提高页面加载速度。
- 把页面使用到的字体组合打包到一块,类似于pdf一样。直接把字体单个扣下来,而不是只用到了几个字就直接引入一个有多个字的字体文件。
- 减少HTTP请求-按需加载资源:根据用户行为或页面需要,动态加载资源,可以减少页面加载时间和资源浪费。
- 要请求地址写好,最好先预编码好。
- 缓存检查。
- 使用缓存-使用浏览器缓存和服务器缓存来减少对服务器的请求,减少重复加载资源的次数。
- 如使用get类型加查询字符串或数据参数这类请求来请求如json这类静态文件。
- 设置缓存策略:通过设置HTTP响应头中的Cache-Control和Expires字段,可以控制浏览器缓存的时间和方式。
- 版本控制:通过在文件名中添加版本号或使用文件内容的哈希值作为版本号,可以避免浏览器缓存旧版本的文件。
- 使用公共的文件,如react.js这一类,那么如果上一个页面也使用同样的地址,浏览器根据地址的一样,直接命中缓存,就不必向后面请求了。
- 缓存策略设置:根据页面特点和用户行为,设置合适的缓存策略,可以提高页面加载速度和用户体验。
- 条件请求:使用条件请求技术,如ETag、Last-Modified等,可以减少HTTP请求次数,提高页面加载速度。
- 使用缓存-使用浏览器缓存和服务器缓存来减少对服务器的请求,减少重复加载资源的次数。
- DNS解析。
- 使用CDN加速:使用内容分发网络(CDN)来加速静态资源的传输,将资源分发到离用户更近的服务器上。
- 将静态资源(如图片、CSS、JavaScript文件)托管到CDN上,可以加速资源的加载速度,减轻服务器负担。
- 使用DNS预解析:通过在页面中添加DNS预解析标签,可以提前解析页面中需要的域名,减少DNS查询时间,提高页面加载速度。
- 使用CDN加速:使用内容分发网络(CDN)来加速静态资源的传输,将资源分发到离用户更近的服务器上。
- TCP的三次握手。
- 浏览器与外网IP对应的服务器产生联系。
- 客户端和服务器之间的数据通信。服务器把资源给到浏览器。
- 压缩代码文件:使用CSS和JavaScript文件的最小化版本等,即使用.min.js这类文件。
- 这个也是由webpack等自动完成,去除console.log()等打印信息,以及把长变量名变短这类。
- 如UglifyJS、CSSNano等,可以减小文件大小,提高页面加载速度。
- 优化JavaScript代码:使用优化工具,如Closure Compiler、Terser等,可以减小文件大小,提高页面加载速度。
- 这个也是由webpack等自动完成,去除console.log()等打印信息,以及把长变量名变短这类。
- 压缩资源:压缩 HTML、CSS、JavaScript 和图片等资源,减小文件大小,提高加载速度。
- 如使用gzip来处理html文件的传输。
- 优化图片:使用适当的图片格式、压缩图片大小、使用懒加载或按需加载等技术来优化图片加载。
- 使用图片压缩工具,如TinyPNG、ImageOptim等,可以减小图片文件大小,提高页面加载速度。
- 可以选择jpg代替png。
- 这个也应该是webpack来做处理。
- 使用本地存储:使用浏览器的本地存储,可以减少HTTP请求次数,提高页面加载速度和用户体验。
- 使用服务器端缓存技术,如Memcached、Redis等,可以减少数据库查询次数,提高页面加载速度。
- 压缩代码文件:使用CSS和JavaScript文件的最小化版本等,即使用.min.js这类文件。
- TCP四次挥手。
- 把浏览器和服务器之间的连接通道断开。
- 客户端处理并渲染服务器返回的信息。
- 使用异步加载:使用异步加载JavaScript和CSS文件,避免阻塞页面渲染。
- 减少首屏空白时间。虽然都是一开始就要加载,但一般是先优先加载好DOM及css。
- 使用异步加载技术,如script标签的defer、async属性等,可以减少页面加载时间。
- 预加载和预渲染:通过预加载相关资源或预渲染页面来提前获取所需内容,减少用户操作时的延迟。
- 比如下载好了表格的第一页数据,就先下载第二页的数据。
- 优化JavaScript执行:避免长时间执行的JavaScript代码,使用节流和防抖等技术控制事件频率,减少不必要的计算和操作。
- 优化渲染性能:减少重排和重绘,使用CSS动画代替JavaScript动画,使用虚拟列表或分页加载等技术优化大量数据的展示。
- 使用CSS3动画:使用CSS3动画代替JavaScript动画,可以减少页面重排和重绘,提高页面性能。
- 避免频繁的DOM操作:减少DOM操作的次数和频率,可以减少页面重排和重绘,提高页面性能。
- 图片懒加载,图片在浏览器页面中显示时才开始请求。
- 延迟加载:对于大型的或不是首要显示的内容,延迟加载可以提高初始页面加载速度。
- 如vue组件懒加载、react组件懒加载。
- 如点击进某个页面后,才需要使用某些字体或某个第三方插件如pdf.js。
- 使用响应式设计:通过响应式布局和媒体查询,使网页能够适应不同屏幕大小的设备,提供更好的用户体验。
- 不用移动端的请求一次,PC端的也请求一次。
- 减少DOM操作:减少DOM操作的次数和频率,可以减少页面重排和重绘,提高页面性能。
- 移动优化:针对移动设备的特点和用户行为,进行页面和资源的优化,提高页面加载速度和用户体验。
- 如不使用jQuery,而是使用jquery-mobile。
- 预渲染:使用预渲染技术,将页面预先生成为静态HTML文件,可以提高页面加载速度和SEO效果。
- 服务端渲染:使用服务端渲染技术,将页面在服务器端生成为HTML文件,可以提高页面加载速度和SEO效果。
- 预加载关键资源:提前加载页面中必要的资源,可以提高页面加载速度和用户体验。
- 使用异步加载:使用异步加载技术,如AJAX、Web Workers等,可以减少页面加载时间。
- 而不是使用同步加载,在请求过程中,页面卡死。
- 选择轻量级框架:选择适合项目需求和页面特点的轻量级框架,可以提高页面加载速度和用户体验。
- 使用异步加载:使用异步加载JavaScript和CSS文件,避免阻塞页面渲染。
- 页面整体流程中:
- 监控和优化网页性能:使用性能监控工具分析网页加载过程中的性能瓶颈,进行针对性的优化。
- 性能调试工具:使用性能调试工具,如Chrome DevTools、Firebug等,可以分析页面的性能瓶颈和优化方案。
- 即在浏览器控制台的网络面板中,可以看到网页文件的具体传输时间。
- 在浏览器控制台的性能面板中,可以看到一个过程中,那个组件用的时间多。
- 借助vue-devtools及react-devtools辅助插件,也可以看到一些组件的性能及渲染时间。
- 性能调试工具:使用性能调试工具,如Chrome DevTools、Firebug等,可以分析页面的性能瓶颈和优化方案。
- 性能监控:使用性能监控工具,如Google Analytics、WebPagetest等,可以监控页面的加载速度和性能指标。
- 用户行为分析:使用用户行为分析工具,如Google Analytics、Mixpanel等,可以分析用户行为和需求,优化页面和资源。
- 监控和优化网页性能:使用性能监控工具分析网页加载过程中的性能瓶颈,进行针对性的优化。
- URL地址解析。