前端性能分析实战经验分享从基础到进阶的全面解析

秋花 Dev 移动 阅读 700
赞 23 收藏
二维码
手机扫码查看
反馈

优化前:卡得不行

最近有个项目,用户反馈说移动端加载速度慢得离谱,特别是在一些低端手机上,简直卡得受不了。我打开自己的手机测试了一下,首页加载时间竟然达到了5秒多,这明显是不可接受的。于是,我决定好好优化一下。

前端性能分析实战经验分享从基础到进阶的全面解析

找到症结了!

首先,我用了一些常见的性能分析工具来定位问题。主要用了Chrome DevTools的Performance面板和Lighthouse。通过Lighthouse跑了一次性能测试,发现主要问题集中在以下几个方面:

  • 图片资源过大
  • JavaScript代码执行时间过长
  • DOM操作过多

这些问题都导致了页面加载缓慢和卡顿。接下来,我就针对这些问题一一进行优化。

优化图片资源

图片资源过大是导致加载慢的主要原因之一。我先对所有图片进行了压缩,使用了tinypng.com这个在线工具,压缩后的图片大小显著减少。同时,我还引入了懒加载技术,只在用户滚动到图片位置时才加载图片。

原来的代码是这样的:

<img src="https://jztheme.com/images/big-image.jpg" alt="Big Image">

优化后的代码:

<img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://jztheme.com/images/compressed-image.jpg" alt="Compressed Image" class="lazyload">

这里使用了data-src属性来存储实际图片地址,并且使用了一个base64占位符来替代默认的src属性,这样可以避免图片一开始就加载。然后加上lazyload类,使用JavaScript来实现懒加载逻辑。

document.addEventListener("DOMContentLoaded", function() {
  const lazyImages = [].slice.call(document.querySelectorAll("img.lazyload"));

  if ("IntersectionObserver" in window) {
    let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          let lazyImage = entry.target;
          lazyImage.src = lazyImage.dataset.src;
          lazyImage.classList.remove("lazyload");
          lazyImageObserver.unobserve(lazyImage);
        }
      });
    });

    lazyImages.forEach(function(lazyImage) {
      lazyImageObserver.observe(lazyImage);
    });
  } else {
    // Fallback for browsers that don't support IntersectionObserver
    let lazyLoad = function() {
      lazyImages.forEach(function(lazyImage) {
        if (lazyImage.getBoundingClientRect().top = 0) {
          lazyImage.src = lazyImage.dataset.src;
          lazyImage.classList.remove("lazyload");
          lazyImages = lazyImages.filter(function(image) {
            return image !== lazyImage;
          });
          if (lazyImages.length === 0) {
            document.removeEventListener("scroll", lazyLoad);
            window.removeEventListener("resize", lazyLoad);
            window.removeEventListener("orientationchange", lazyLoad);
          }
        }
      });
    };

    document.addEventListener("scroll", lazyLoad);
    window.addEventListener("resize", lazyLoad);
    window.addEventListener("orientationchange", lazyLoad);
  }
});

优化JavaScript代码

JavaScript代码执行时间过长也是一个大问题。我检查了一下代码,发现有些地方确实有点冗余。比如,有些函数重复调用多次,还有一些不必要的DOM操作。于是我做了以下几点优化:

  • 合并重复的函数调用
  • 减少DOM操作,尽量批量修改
  • 使用Web Workers来处理一些计算密集型任务

原来的代码中,有一个函数会在多个地方被调用,而且每次调用都会进行一些DOM操作。我把它优化成了一个单一的函数,并且减少了DOM操作次数。

优化前的代码:

function updateUI(data) {
  document.getElementById("title").innerText = data.title;
  document.getElementById("description").innerText = data.description;
  document.getElementById("image").src = data.image;
}

fetch("https://jztheme.com/api/data")
  .then(response => response.json())
  .then(data => {
    updateUI(data);
  });

setTimeout(() => {
  fetch("https://jztheme.com/api/data")
    .then(response => response.json())
    .then(data => {
      updateUI(data);
    });
}, 1000);

优化后的代码:

function updateUI(data) {
  const titleElement = document.getElementById("title");
  const descriptionElement = document.getElementById("description");
  const imageElement = document.getElementById("image");

  titleElement.innerText = data.title;
  descriptionElement.innerText = data.description;
  imageElement.src = data.image;
}

fetch("https://jztheme.com/api/data")
  .then(response => response.json())
  .then(data => {
    updateUI(data);
  });

setTimeout(() => {
  fetch("https://jztheme.com/api/data")
    .then(response => response.json())
    .then(data => {
      updateUI(data);
    });
}, 1000);

通过这种方式,减少了DOM查询的次数,提高了性能。

优化DOM操作

DOM操作过多也是导致性能问题的一个重要原因。我通过减少不必要的DOM操作和批量修改来优化这一点。比如,原来有一些地方会频繁地插入和删除DOM元素,我改成了一次性生成所有需要的DOM元素,然后再一次性插入到页面中。

优化前的代码:

const items = [/* some data */];

items.forEach(item => {
  const itemElement = document.createElement("div");
  itemElement.innerHTML = 
    &lt;h3&gt;${item.title}&lt;/h3&gt;
    &lt;p&gt;${item.description}&lt;/p&gt;
  ;
  document.getElementById("container").appendChild(itemElement);
});

优化后的代码:

const items = [/* some data */];
let fragment = document.createDocumentFragment();

items.forEach(item => {
  const itemElement = document.createElement("div");
  itemElement.innerHTML = 
    &lt;h3&gt;${item.title}&lt;/h3&gt;
    &lt;p&gt;${item.description}&lt;/p&gt;
  ;
  fragment.appendChild(itemElement);
});

document.getElementById("container").appendChild(fragment);

通过这种方式,减少了DOM操作的次数,提高了性能。

优化后:流畅多了

经过以上这些优化,我再次用Lighthouse跑了一次性能测试,结果如下:

  • 加载时间从5秒降到了800毫秒
  • 性能得分从60分提高到了90分

优化效果非常明显,用户反馈也好多了。不过还是有一些小问题,比如在某些老旧设备上仍然有些许卡顿,但总体来说已经大大改善了。

总结

以上就是我在优化移动端性能过程中的一些经验分享。优化性能是一个持续的过程,需要不断测试和调整。如果你有更好的方案或者遇到类似的问题,欢迎在评论区交流。希望我的经验对你有帮助。

本文章不代表JZTHEME立场,仅为作者个人观点 / 研究心得 / 经验分享,旨在交流探讨,供读者参考。
发表评论

暂无评论