加载时优化

从一个http申请产生(从输出URL到页面加载的全过程)的具体过程中挖掘一些可优化点

一、 缩小DNS查问, 应用正当范畴内的多个域名

放弃2~4个域名的折中计划,最大化下载线程(古代浏览器会有同域名限度并发下载数的状况),同时又能够肯定水平的缩小DNS解析的过程

二、缩小http申请数量、申请大小

  1. 图片应用精灵图,缩小http申请数量
  2. 压缩文件缩小http申请大小
  3. 合并文件缩小http申请数量

三、应用CDN加载动态资源

缓存源站的资源到各cdn节点上,用户就近获取资源,缓解服务器压力,晋升响应速度

四、按需加载,缩小冗余代码

  1. 图片懒加载
    外围思路:监听页面滚动事件,图片呈现在可视区域内则进行加载显示

    <img src=""  data-src="xxxxx">//  监听滚动事件img.src = img.getAttribute("data-src")
  2. 缩小babel转译过程中的冗余代码
    应用@babel/plugin-transform-runtime
    按需引入@babel/runtime中的辅助函数(helper)

五、服务端渲染SSR

服务端解析html内容, 浏览器端间接渲染

实现形式:
(1) JSP
(2) vue + nuxt
(3) express + react

与客户端渲染CSR的区别:
SSR利于首屏渲染、SEO优化;CSR实用于交互性强、不须要SEO的我的项目
局部场景混合搭配应用,例如next.js

六、css放头部,js置底部

保障页面失常渲染,js须要放头部可给script增加defer属性
用于提早加载

运行时优化(代码优化)

一、函数防抖、节流

两种实现形式:定时器和工夫戳

  1. 函数防抖
事件触发后通过一段时间触发响应,在这段时间内若再次触发则从新计时, 即"只有最初一次操作被触发"
function debounce(fn, delay) {    let timerId = null;    return function (...args) {        const context = this;        timerId && clearTimeout(timerId);        timerId = setTimeout(() => {            fn.apply(context, args);        }, delay);    };}const callback = function (e, data1) {    console.log(e, data1);};document.addEventListener('mousemove', debounce(callback, 3000));

利用场景:输入框搜寻、输入框输出验证、浏览器窗口resize

  1. 函数节流
指定工夫距离内,只执行一次
function throttle(fn, delay, params) {    let timerId = null;    return function (...args) {        const context = this;        if (!timerId) {            timerId = setTimeout(() => {                timerId = null;                fn.apply(context, args);            }, delay);        }    };}const callback = function (e, data1) {    console.log(e, data1);};document.addEventListener('mousemove', throttle(callback, 3000));

利用场景:长列表滚动加载、频繁点击事件(点赞、表单提交等操作)、输入框主动补全

二、缩小重排和重绘

三、代码上的细节优化

  1. 尾调用优化
只保留内层函数的调用帧, 用于解决js引擎最大递归深度问题(即最大嵌套调用次数, 个别为100000次)

目前大部分浏览器不反对

利用:尾递归

// 递归遍历let company = {  sales: [{name: 'John', salary: 1000}, {name: 'Alice', salary: 1600 }],  development: {    sites: [{name: 'Peter', salary: 2000}, {name: 'Alex', salary: 1800 }],    internals: [{name: 'Jack', salary: 1300}]  }};function sumSalaries(department) {  if (Array.isArray(department)) {    return department.reduce((prev, current) => prev + current.salary, 0);  } else {    let sum = 0;    for (let subdep of Object.values(department)) {      sum += sumSalaries(subdep);    }    return sum;  }}alert(sumSalaries(company)); // 7700// 递归结构例如链表构造,对于插入、删除操作,优于数组let list = {  value: 1,  next: {    value: 2,    next: {      value: 3,      next: {        value: 4,        next: null      }    }  }};// 尾递归优化function Fibonacci1 (n , ac1 = 1 , ac2 = 1) {  if( n <= 2 ) {return ac2};  return Fibonacci1 (n - 1, ac2, ac1 + ac2);}Fibonacci1(7) // 13

参考链接:
尾调用优化
递归、堆栈