Skip to content

Latest commit

 

History

History
203 lines (163 loc) · 6.73 KB

性能优化目的、分析和方法.md

File metadata and controls

203 lines (163 loc) · 6.73 KB

性能优化

性能优化的目的

  1. 首屏时间
  2. 首屏可交互时间
  3. 首次有意义内容渲染时间

性能检测: https://developers.google.com/speed/pagespeed/insights

polyfill: https://polyfill.io/v3/url-builder

优化方法

只请求当前需要的资源

缩减资源体积

  • 打包压缩,webpack4版本已经内置
  • gzip,一种压缩算法,一般默认开启
  • 图片格式的优化,压缩 tinypng.com,根据屏幕分辨率展示不同分辨率的图片,webp(可以使图片在无损的情况下进行压缩,需要判断浏览器是否支持webp)
  • 尽量控制cookie的大小,每一个request header都要携带cookie,同域名请求都会带上所有的cookie,耗费多余的体积。

时序优化

通过一些代码能力影响资源的加载。

  • promise.all 并行执行promise,并发发请求
  • ssr 把打包放到服务端,好处是可以做缓存,更新更新的地方,并且seo友好
  • prefetch, prerender, preload
// 碰到这行代码后会立即请求dns解析,也就是预解析
<link rel="dns-prefetch" href="xxx.com" />
// 预建立网络连接,包括dns解析,TLS协商,TCP握手
<link rel="preconnect" href="xxx.com" />
//预加载
<link rel="preload" as='image' href="xxx.com/p.png" />

合理的利用缓存

cdn、cdn预热、cdn刷新。

cnd域名和业务域名通常是不一样的,为了避免cookie影响,增加请求消耗。

如果一段js执行时间非常长,怎么去分析

// 封装一个计时的装饰器函数
function measure(fn) {
  return async function () {
    console.time(fn.name);
    const ret = await fn.apply(this, arguments);
    console.timeEnd(fn.name);
    return ret;
  };
}

const fn = (name) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(name);
      resolve(name);
    }, 2000);
  });
};

measure(fn)("reonce");

阿里云oss支持通过链接后面品参数来做图片的格式转换,尝试写一下,把任意图片格式转换为webp,需要注意什么

首先应该判断浏览器是否支持webp。canisuse.com可以看浏览器支持性。

封装一个判断方法:

function checkWebp() {
  try {
    return (
      document
        .createElement("canvas")
        .toDataURL("image/webp")
        .indexOf("data:image/webp") === 0
    );
  } catch (error) {
    return false;
  }
}

// document.createElement("canvas").toDataURL("image/webp")转化如下
// 'data:image/webp;base64,UklGRtgCAABXRUJQVlA4WAoAAAAwAAAAKwEAlQAASUNDUBgCAAAAAAIYAAAAAAQwAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAAHRyWFlaAAABZAAAABRnWFlaAAABeAAAABRiWFlaAAABjAAAABRyVFJDAAABoAAAAChnVFJDAAABoAAAAChiVFJDAAABoAAAACh3dHB0AAAByAAAABRjcHJ0AAAB3AAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAFgAAAAcAHMAUgBHAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z3BhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABYWVogAAAAAAAA9tYAAQAAAADTLW1sdWMAAAAAAAAAAQAAAAxlblVTAAAAIAAAABwARwBvAG8AZwBsAGUAIABJAG4AYwAuACAAMgAwADEANkFMUEgSAAAAAQcQEREQkCT+/x9F9D/tf0MAVlA4IIAAAABwDQCdASosAZYAPm02mUmkIyKhICgAgA2JaW7hdrEbQAnsA99snIe+2TkPfbJyHvtk5D32ych77ZOQ99snIe+2TkPfbJyHvtk5D32ych77ZOQ99snIe+2TkPfbJyHvtk5D32ych77ZOQ99snIe+2TkPfasAAD+/9YAAAAAAAAAAA=='

通过创建一个 canvas 元素,将它转为base64格式的image/webp,如果浏览器支持,它的开头将带有 data:image/webp 的字符串。(如代码注释)。如果不存在或者报错,则返回false。

接下来看一下如何经过判断去拼接阿里oss:

const supportWebp = checkWebp();

export function getWebpImageUrl(url) {
  // 不存在url,抛出异常
  if (!url) {
    throw new Error("url不能为空");
  }
  // 如果url是base64格式,直接返回
  if (url.startsWith("data:")) {
    return url;
  }
  // 如果浏览器不支持,直接返回
  if (!supportWebp) {
    return rul;
  }
  // 拼接阿里oss, 假定为:x-oss-process=image/format,webp
  return `${url}?x-oss-process=image/format,webp`;
}

注意一个点,以上是默认图片都在oss上的

如果有巨量的图片需要展示,除了懒加载的方式,还有没有其他方法限制一下同时加载的图片数量

代码题,实现promise的并发控制,例如要求同时进行3个图片的加载,始终加载3个

这里不能用for循环+promise.all的原因是,后者是执行完3个再去执行3个,不符。

function limitLoad(urls, handler, limit) {
  const sequence = [].concat(urls);
  let promises = [];

  promises = sequence.splice(0, limit).map((url, index) => {
    return handler(url).then(() => {
      // 当执行完之后,再填补一个,所有需要知道哪个执行完了
      return index;
    });
  });

  // 通过竞速选出第一个执行完的
  // 补充,出现执行完的之后,其他的还会执行,只是race函数只返回了最快的。
  let p = Promise.race(promises);
  for (let i = 0; i < sequence.length; i++) {
    // 最终p会变成 p.then().then().then()... 它是通过链式调用的形式去不断的竞速和填充
    p = p.then((res) => {
      promises[res] = handler(sequence[i]).then(() => {
        return res;
      });
      return Promise.race(promises);
    });
  }
}
// 模拟url地址和加载时间
const mockUrls = [
  {
    url: "地址1",
    time: 2000,
  },
  {
    url: "地址2",
    time: 2300,
  },
  {
    url: "地址3",
    time: 4000,
  },
  {
    url: "地址4",
    time: 3000,
  },
  {
    url: "地址5",
    time: 2000,
  },
  {
    url: "地址6",
    time: 1000,
  },
];

// 设置要执行的任务
function loadImg(url) {
  return new Promise((resolve, reject) => {
    console.log("-----" + url.url + "start!");
    setTimeout(() => {
      console.log(url.url + "---OK!!!");
      resolve();
    }, url.time);
  });
}

limitLoad(mockUrls, loadImg, 3);

请说出三种减少页面加载时间的方法。

你如何对网站的文件和资源进行优化的