前端 性能优化 (图片与样式篇)

文章目录

  • 前端能够做哪些图片优化?
    • 1、减小图片体积
    • 2、图片缓存
      • 服务工作线程 (Service Workers)缓存
      • IndexDB缓存图片
      • LocalStorage缓存
    • 3、图片懒加载
      • 使用 loading="lazy" 属性
    • 4、不同分辨率下使用不同的图片
    • 5、使用webp格式的图片
    • 6、配置图片CDN
    • 7、减少图片和动图的使用
  • css样式如何优化?
    • 1、关键css优先,非关键css等页面加载完成再加载或引入
    • 2、使用 CSS 预处理器和后处理器
    • 3、利用 CSS 变量
    • 4、减少和优化选择器的复杂性
    • 5、删除无用的 CSS
    • 6、利用缓存
    • 7、编写代码时尽量减少重排和重绘

在这里插入图片描述

前端能够做哪些图片优化?

1、减小图片体积

压缩图片可以减小文件大小,提升页面加载速度。可以使用工具如 TinyPNG 或 ImageOptim 来优化图片。

2、图片缓存

浏览器缓存是最基础的前端缓存方式。通过设置HTTP响应头,指定缓存策略,可以控制浏览器对图片资源的缓存行为。

Cache-Control: 设置图片的缓存时长。例如,Cache-Control: max-age=31536000表示缓存一年。
Expires: 指定缓存过期日期,配合Cache-Control使用。
ETag 和 Last-Modified: 标记资源的版本号或最后修改时间,当浏览器再次请求该资源时,通过对比判断是否需要重新下载。

这些头信息可以在服务器端配置,常用于CDN或静态资源服务器。

服务工作线程 (Service Workers)缓存

Service Workers是一种更高级的缓存方式,通过注册Service Worker脚本,可以拦截图片请求并从缓存中返回内容。可以在应用初始化时加载图片资源并存储在Service Worker的缓存中,后续请求可以直接读取缓存内容。

// 安装阶段(Install Event),当 Service Worker 安装时触发
self.addEventListener('install', event => {
    // 使用 event.waitUntil 确保安装过程完成后才继续执行后续的步骤
    event.waitUntil(
        // 打开一个名为 'image-cache' 的缓存存储
        caches.open('image-cache').then(cache => {
            // 将图片资源添加到缓存中
            return cache.addAll([
                '/images/photo1.jpg', // 图片1
                '/images/photo2.jpg', // 图片2
                // 更多图片资源可以添加在这里...
            ]);
        })
    );
});

// 激活阶段,拦截网络请求并返回缓存数据(Fetch Event)
self.addEventListener('fetch', event => {
    // 判断请求是否是图片资源
    if (event.request.destination === 'image') {
        // event.respondWith 接受一个 Promise,返回响应数据
        event.respondWith(
            // 尝试从缓存中匹配请求
            caches.match(event.request).then(response => {
                // 如果缓存中存在图片,直接返回缓存的响应
                return response || 
                    // 如果缓存中没有对应的图片,则执行网络请求
                    fetch(event.request).then(fetchResponse => {
                        // 一旦网络请求返回图片数据,就将其缓存
                        return caches.open('image-cache').then(cache => {
                            // 将网络获取的图片存入缓存
                            cache.put(event.request, fetchResponse.clone());
                            // 返回从网络获取的图片响应
                            return fetchResponse;
                        });
                    });
            })
        );
    }
});

IndexDB缓存图片

IndexedDB一个适合存储较大数据(如图片二进制数据)的浏览器数据库。要存储图片,我们通常将图片文件转换为 Blob(二进制大对象),并存入 IndexedDB。这样,在后续需要加载缓存图片时,可以从 IndexedDB 中检索 Blob,然后将其转化为 URL 以加载到页面中。

初始化 IndexedDB 数据库和对象存储

// 初始化 IndexedDB
function openDatabase() {
    return new Promise((resolve, reject) => {
        const request = indexedDB.open('imageCacheDB', 1);

        // 创建或更新数据库时触发
        request.onupgradeneeded = function(event) {
            const db = event.target.result;
            if (!db.objectStoreNames.contains('images')) {
                db.createObjectStore('images'); // 创建名为 "images" 的对象存储
            }
        };

        request.onsuccess = function(event) {
            resolve(event.target.result); // 成功打开数据库
        };

        request.onerror = function(event) {
            reject(event.target.error); // 打开数据库失败
        };
    });
}

将图片存储到 IndexedDB 中

// 将图片 Blob 存入 IndexedDB
function cacheImage(url, blob) {
    openDatabase().then(db => {
        const transaction = db.transaction('images', 'readwrite');
        const store = transaction.objectStore('images');
        store.put(blob, url); // 使用图片 URL 作为键
        transaction.oncomplete = () => {
            console.log('Image cached in IndexedDB');
        };
    }).catch(error => {
        console.error('Failed to cache image:', error);
    });
}

// 获取图片并缓存
function fetchAndCacheImage(url) {
    fetch(url)
        .then(response => response.blob())
        .then(blob => {
            cacheImage(url, blob); // 缓存图片
        })
        .catch(error => {
            console.error('Failed to fetch image:', error);
        });
}

从 IndexedDB 中读取图片并显示
当需要显示图片时,可以从 IndexedDB 读取 Blob 数据并生成一个 URL 给 标签使用

// 从 IndexedDB 中获取图片 Blob
function getCachedImage(url) {
    return new Promise((resolve, reject) => {
        openDatabase().then(db => {
            const transaction = db.transaction('images', 'readonly');
            const store = transaction.objectStore('images');
            const request = store.get(url);

            request.onsuccess = function(event) {
                if (event.target.result) {
                    resolve(event.target.result); // 返回图片 Blob
                } else {
                    reject('Image not found in cache');
                }
            };

            request.onerror = function() {
                reject('Failed to retrieve image from IndexedDB');
            };
        });
    });
}

// 使用缓存图片显示到页面
function displayImageFromCache(url, imgElementId) {
    getCachedImage(url)
        .then(blob => {
            const imgURL = URL.createObjectURL(blob);
            document.getElementById(imgElementId).src = imgURL;
        })
        .catch(error => {
            console.error('Error displaying cached image:', error);
        });
}

// 示例调用
const imageUrl = 'https://example.com/image.jpg';
fetchAndCacheImage(imageUrl); // 首次获取并缓存
displayImageFromCache(imageUrl, 'myImage'); // 从缓存中显示图片

LocalStorage缓存

// 保存图片到 localStorage
function cacheImage(url) {
    fetch(url)
        .then(response => response.blob())
        .then(blob => {
            const reader = new FileReader();
            reader.onload = function () {
                localStorage.setItem('cachedImage', reader.result); // 将Base64数据存入localStorage
            };
            reader.readAsDataURL(blob);
        });
}

3、图片懒加载

懒加载和占位图也是提升前端图片加载性能的技巧,虽然不算是严格意义的缓存。懒加载会等到图片在视窗中出现时才开始加载,减少初始页面加载的资源量,占位图则在图片未加载完成前提供一个小尺寸、模糊的占位图,让页面看起来更平滑。

假设你有多个图片,添加 data-src 属性存储图片的实际 URL,src 属性设置为占位符(比如一张模糊的小图或空白图片),这样只有当图片进入视口时,才会加载实际的图片。

<img class="lazy" data-src="https://example.com/photo1.jpg" src="placeholder.jpg" alt="Image 1" />
<img class="lazy" data-src="https://example.com/photo2.jpg" src="placeholder.jpg" alt="Image 2" />
<img class="lazy" data-src="https://example.com/photo3.jpg" src="placeholder.jpg" alt="Image 3" />
<!-- 更多图片 -->

使用 IntersectionObserver 来监视图片是否进入视口,如果进入视口,就把 data-src 的值赋给 src,从而触发图片加载。

// 创建一个 IntersectionObserver 实例,监视图片是否进入视口
const lazyLoadImages = document.querySelectorAll('img.lazy');

const imageObserver = new IntersectionObserver((entries, observer) => {
    entries.forEach(entry => {
        // 如果图片进入视口
        if (entry.isIntersecting) {
            const image = entry.target;
            // 将 data-src 的真实图片 URL 赋值给 src 属性
            image.src = image.dataset.src;
            // 一旦图片加载完毕,停止观察该图片
            image.onload = () => {
                image.classList.remove('lazy'); // 可选:移除懒加载样式
            };
            observer.unobserve(image); // 停止观察已加载的图片
        }
    });
}, {
    rootMargin: '0px', // 可选:在视口边缘触发加载(当图片接近视口时开始加载)
    threshold: 0.1  // 可选:当图片至少 10% 显示时开始加载
});

// 观察所有懒加载图片
lazyLoadImages.forEach(image => {
    imageObserver.observe(image);
});

代码解释
IntersectionObserver:
创建 IntersectionObserver 实例来观察图片元素是否进入视口。IntersectionObserver 会异步监测指定元素与视口的交集变化。
entries 是一个包含所有监测元素的数组,entry.target 是当前进入视口的图片元素。
isIntersecting 属性表示图片是否已经进入视口(或者与视口重叠)。当该属性为 true 时,图片就进入了视口。
rootMargin:

rootMargin 是视口的扩展区域。当图片距离视口边缘一定距离时就触发加载。可以使用类似 CSS 的值(如 10px 0px)。
threshold:

threshold 定义了当多少比例的图片进入视口时触发懒加载,0.1 表示图片至少 10% 进入视口时触发加载。
image.onload:

一旦图片加载完毕,可以执行一些操作,比如移除懒加载样式(如 lazy 类),表示图片已成功加载。
observer.unobserve(image):

加载完图片后,停止观察该图片,优化性能。

使用 loading=“lazy” 属性

使用 loading=“lazy” 属性可以非常简单地实现图片的懒加载。浏览器就会在图片进入视口时自动加载它。这是原生浏览器对懒加载的支持,无需额外的 JavaScript 代码。这个属性已经被大多数现代浏览器支持。

<img src="image1.jpg" alt="Image 1" loading="lazy" />
<img src="image2.jpg" alt="Image 2" loading="lazy" />
<img src="image3.jpg" alt="Image 3" loading="lazy" />

4、不同分辨率下使用不同的图片

<picture>
  <source media="(max-width: 600px)" srcset="image-small.jpg">
  <source media="(max-width: 1200px)" srcset="image-medium.jpg">
  <img src="image-large.jpg" alt="Responsive Image">
</picture>

或者

<img src="image-small.jpg" 
     srcset="image-small.jpg 500w, 
             image-medium.jpg 1000w, 
             image-large.jpg 2000w" 
     sizes="(max-width: 600px) 100vw, 
            (max-width: 1200px) 50vw, 
            33vw" 
     alt="Responsive Image">

5、使用webp格式的图片

使用 WebP 格式(如果浏览器支持)可以显著减小图片文件大小,从而提高加载速度。
可以通过 元素来根据浏览器支持选择图片格式。

<picture>
    <source srcset="image.webp" type="image/webp">
    <img src="image.jpg" alt="Responsive Image">
</picture>

6、配置图片CDN

  1. 选择和设置 CDN 服务提供商
    首先,选择一个合适的 CDN 服务提供商。常见的 CDN 提供商包括:

Cloudflare
AWS CloudFront
Fastly
KeyCDN
Alibaba Cloud CDN
Tencent Cloud CDN

  1. 上传图片到 CDN
    选择图片存储方式:

存储在对象存储服务中:你可以使用云服务提供商的对象存储(如 Amazon S3、Alibaba OSS、腾讯云 COS)来存储图片文件,并通过 CDN 进行分发。通过这种方式,你可以确保文件安全,并允许 CDN 节点从这些存储服务获取资源。

直接通过 CDN 上传:有些 CDN 服务商允许直接将图片资源上传到其 CDN 网络。

上传图片:将图片上传到选定的存储服务(如 S3),并记录图片的 URL。

  1. 配置 CDN
    创建 CDN 加速域名:

登录你的 CDN 提供商控制台,创建一个加速域名(例如 cdn.yoursite.com)。
配置源站点(通常是你存储图片的服务器或对象存储服务)。源站点是 CDN 获取图片资源的地方。
设置缓存策略:

配置缓存时间(TTL,生存时间),指示 CDN 节点在没有更新时缓存图片的时间。一般情况下,静态资源(如图片)可以设置较长的缓存时间,如一周或一月。
启用 图片优化 功能(如果支持),以便根据设备类型和网络状况自动调整图片的大小和质量。
4. 修改图片 URL
在网页中引用 CDN 提供的图片 URL。假设你的 CDN 域名是 cdn.yoursite.com,你可以像这样引用图片:

<img src="https://cdn.yoursite.com/images/photo1.jpg" alt="Image 1" />
<img src="https://cdn.yoursite.com/images/photo2.jpg" alt="Image 2" />

将原本直接指向服务器的图片 URL 替换为指向 CDN 的图片 URL。

7、减少图片和动图的使用

这可能需要有较强的canvas功底,和较多的开发时间。但的确是能大幅度优化图片的方案。
能用css实现的简单动画,就别用动态图片。能用css实现的样式,就别用图片。

css样式如何优化?

1、关键css优先,非关键css等页面加载完成再加载或引入

在优化 CSS 加载时,遵循“先加载关键 CSS,再懒加载非关键 CSS”的策略,可以显著提升页面加载速度。

1、提取关键css
这就要分析一个页面的功能样式,是否可以分离为进入页面就要展示的css和等用户操作后才展示的css

<style>
  /* 关键 CSS */
  body { margin: 0; font-family: Arial, sans-serif; }
  header { background-color: #333; color: white; padding: 10px; }
  /* 添加更多关键样式 */
</style>

2、 懒加载非关键 CSS
如果页面有复杂特效(如动画、hover 状态、特定 JavaScript 动画等),可以将这些 CSS 动效代码延迟到页面加载完成后再应用,从而加快页面初始渲染速度。通过在 标签中添加 media=“print” 和 onload 事件来实现非阻塞加载。

<link rel="stylesheet" href="non-critical.css" media="print" onload="this.media='all'">

3、使用 rel=“preload” 优化 CSS 加载
对于需要优先加载的非关键 CSS,可以用 preload 指令提前加载,提高资源加载效率。

<link rel="preload" href="important.css" as="style" onload="this.οnlοad=null; this.rel='stylesheet'">

除了上述处理非关键css,还可以使用js直接引入

window.addEventListener('load', function() {
  let link = document.createElement('link');
  link.rel = 'stylesheet';
  link.href = 'additional-styles.css';
  document.head.appendChild(link);
});

2、使用 CSS 预处理器和后处理器

预处理器如 SCSS、LESS 可以更简洁地编写和管理 CSS。
后处理器如 PostCSS 可以根据浏览器的兼容性要求,自动添加前缀、压缩代码、处理变量等。

3、利用 CSS 变量

使用 CSS 变量可以减少重复代码,便于动态调整样式。比如色彩、尺寸等样式都可以用 CSS 变量来定义,从而减少代码量并优化可维护性。

:root {
  --main-color: #4CAF50;
  --padding: 10px;
}

body {
  color: var(--main-color);
  padding: var(--padding);
}

4、减少和优化选择器的复杂性

尽量使用简单的选择器,避免使用深层嵌套或复杂选择器。深层嵌套和通配符(如 *)会增加浏览器的解析成本。

5、删除无用的 CSS

使用工具如 PurgeCSS 或 UnCSS 来移除未使用的 CSS 代码。这样可以极大地减少 CSS 文件体积,提高加载速度。

6、利用缓存

为 CSS 文件设置长缓存时间。通过配置缓存策略,浏览器可以在多次访问时直接加载缓存中的 CSS 文件,避免重新请求 (前端的缓存策略,无非就是 Localstorage,service work)

7、编写代码时尽量减少重排和重绘

尽量避免频繁修改布局属性(如 width、height、padding),减少重绘和重排。可以使用 transform、opacity 等性能友好的属性,进行页面更新。
transform 调用的GPU来实现渲染 ,减少使用translate

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/914821.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【MySQL 保姆级教学】事务的自动提交和手动提交(重点)--上(13)

目录 1. 什么是事务&#xff1f;2. 事务的版本支持3. 事务提交的方式3.1 事务提交方式的分类3.2 演示的准备的工作3.2.1 创建表3.2.2 MySQL的服务端和客户端3.2.3 调低事务的隔离级别 4. 手动提交4.1 手动提交的命令说明4.2 示例一4.3 示例二4.4 示例三4.5 示例四 5. 自动提交5…

C++ | Leetcode C++题解之第546题移除盒子

题目&#xff1a; 题解&#xff1a; class Solution { public:int dp[100][100][100];int removeBoxes(vector<int>& boxes) {memset(dp, 0, sizeof dp);return calculatePoints(boxes, 0, boxes.size() - 1, 0);}int calculatePoints(vector<int>& boxes…

RK3588部署ppocr流程及安装环境_笔记1

前言&#xff1a; RK3588部署ppocr流程及ubuntu安装环境 目录 一、NoMachine安装使用 二、把ubuntu系统从英文修改为中文界面 三、安装conda 没有报错说明没有问题&#xff0c;如果source的时候报错&#xff0c;查看 ​编辑 报这种错&#xff1a; 5、需要添加国内镜像源…

二分查找习题篇(下)

二分查找习题篇(下) 1.山脉数组的峰顶索引 题目描述&#xff1a; 给定一个长度为 n 的整数 山脉 数组 arr &#xff0c;其中的值递增到一个 峰值元素 然后递减。 返回峰值元素的下标。 你必须设计并实现时间复杂度为 O(log(n)) 的解决方案。 示例 1&#xff1a; 输入&#xf…

Linux学习笔记之shell快速入门及相关变量

Shell是什么 Shell是一个命令解释器&#xff0c;它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序&#xff0c;用户可以通过Shell来启动、挂起甚至编写一些程序。 Shell脚本执行方式 脚本格式要求 脚本以#!/bin/bash开头脚本需要有可执行权限 脚本的常…

el-table 行列文字悬浮超出屏幕宽度不换行的问题

修改前的效果 修改后的效果 ui框架 element-plus 在网上找了很多例子都没找到合适的 然后这个东西鼠标挪走就不显示 控制台也不好调试 看了一下El-table的源码 他这个悬浮文字用的el-prpper 包着的 所以直接改 .el-table .el-propper 设置为max-width:1000px 就可以了 吐槽一…

ApiSmart x Qwen2.5-Coder 开源旗舰编程模型媲美 GPT-4o, ApiSmart 实测!

通义千问代码模型开源版。Qwen2.5-Coder相比CodeQwen1.5有了实质性的改进。Qwen2.5-Coder在包含5.5万亿Token的编程相关数据上进行了训练&#xff0c;使即使较小的编程专用模型也能在编程评估基准测试中表现出媲美大型语言模型的竞争力。 阿里云-2024年11月12日 Qwen2.5-Coder …

Java项目实战II基于微信小程序的个人行政复议在线预约系统微信小程序(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 基于微信小…

MyBatis xml 文件中 SQL 语句的小于号未转义导致报错

问题现象 在 MyBatis 的 xml 文件中添加了一个 SQL 语句 <select id"countXxx" resultType"int">select count(*) from t1 where count < 3 </select>启动 Spring Boot 应用程序后报错&#xff1a; Caused by: org.apache.ibatis.builde…

C++20 STL CookBook 7 Containers(II)

让vector在插入删除的时候仍然保证是有序的 首先&#xff0c;STL的确提供了一种办法来检查我们的目标容器是不是有序的&#xff1a;std::is_sorted - cppreference.com&#xff0c;也就是std::is_sorted。我们当然可以这样做&#xff1a; #include <iostream> #include…

FlinkSql读取kafka数据流的方法(scala)

我的scala版本为2.12 <scala.binary.version>2.12</scala.binary.version> 我的Flink版本为1.13.6 <flink.version>1.13.6</flink.version> FlinkSql读取kafka数据流需要如下依赖&#xff1a; <dependency><groupId>org.apache.flink&…

语音 AI 革命:未来,消费者更可能倾向于与 AI 沟通,而非人工客服

「未来&#xff0c;消费者更可能倾向于与 AI 沟通&#xff0c;而非人工客服&#xff0c;因为这将成为解决问题的最高效途径。」 这篇来自 Bessemer Venture Partners 的报告&#xff0c;是目前为止对语音 AI 在企业应用上最完整清晰的一次梳理。 核心要点&#xff1a; 尽管市…

【t365】基于springboot的高校疫情防控系统

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对信息管理混乱&#xff0c;出错率高&#xff0c;信息安全性差&#x…

DAY27|贪心算法Part01|LeetCode:455.分发饼干、376. 摆动序列、53. 最大子序和

贪心算法 贪心的本质是选择每一阶段的局部最优&#xff0c;从而达到全局最优。 贪心算法并没有固定的套路&#xff0c;最难想的就在于如何通过局部最优去推出全局最优。在做一个题目的时候&#xff0c;靠自己手动模拟&#xff0c;如果模拟可行&#xff0c;就可以试一试贪心策略…

四万字长文SpringBoot、Spring、SpringMVC等相关面试题(注:该篇博客将会持续维护 最新维护时间:2024年11月12日)

&#x1f9f8;本篇博客重在讲解SpringBoot、Spring、SpringMVC等相关面试题&#xff0c;将会实时更新&#xff0c;欢迎大家添加作者文末联系方式交流 &#x1f4dc;JAVA面试题专栏&#xff1a;JAVA崭新面试题——2024版_dream_ready的博客-CSDN博客 &#x1f4dc;作者首页&…

免费HTML模板和CSS样式网站汇总

HTML模板&#xff1a;&#xff08;注意版权&#xff0c;部分不可商用&#xff09; 1、Tooplate&#xff0c;免费HTML模板下载 Download 60 Free HTML Templates for your websitesDownload 60 free HTML website templates or responsive Bootstrap templates instantly from T…

深入理解接口测试:实用指南与最佳实践5.0(二)

✨博客主页&#xff1a; https://blog.csdn.net/m0_63815035?typeblog &#x1f497;《博客内容》&#xff1a;.NET、Java.测试开发、Python、Android、Go、Node、Android前端小程序等相关领域知识 &#x1f4e2;博客专栏&#xff1a; https://blog.csdn.net/m0_63815035/cat…

SpringBoot技术:共享汽车行业的新动力

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了共享汽车管理系统的开发全过程。通过分析共享汽车管理系统管理的不足&#xff0c;创建了一个计算机管理共享汽车管理系统的方案。文章介绍了共享汽车管理系统的系…

Java Review - 线程池原理源码解析

文章目录 Pre为什么要用线程池线程池的优点&#xff08;1&#xff09;重复利用线程&#xff08;2&#xff09;控制线程的数量 线程池实现原理线程池ThreadPoolExecutor类关系线程池的工作流程任务队列空闲线程的存活时间参数ThreadFactory拒绝策略被拒绝后的任务如何再次执行 向…

昇思大模型平台打卡体验活动:项目4基于MindSpore实现Roberta模型Prompt Tuning

基于MindNLP的Roberta模型Prompt Tuning 本文档介绍了如何基于MindNLP进行Roberta模型的Prompt Tuning&#xff0c;主要用于GLUE基准数据集的微调。本文提供了完整的代码示例以及详细的步骤说明&#xff0c;便于理解和复现实验。 环境配置 在运行此代码前&#xff0c;请确保…