【笔记摘要】前端性能

前端领域提升性能,可以考虑以下几个关键方向:

网络优化:

减少HTTP请求:通过合并文件、使用雪碧图、CSS内联小图片等方式减少请求次数。
开启HTTP/2或HTTP/3:利用多路复用、头部压缩等特性提升传输效率。
DNS预解析:使用<link rel="dns-prefetch">预解析DNS,减少域名解析时间。
使用CDN:全球分布的内容分发网络加速资源加载。
资源缓存:合理设置缓存策略,如ETag、Cache-Control,减少重复下载。
页面渲染优化:

优化Critical Rendering Path(关键渲染路径),优先加载首屏所需资源。
使用<link rel="preload">预加载关键资源。
CSS放置于<head>,JavaScript置于</body>底部或异步加载,避免阻塞渲染。
通过Media Queries或<link rel="stylesheet" media="print">延迟非关键CSS加载。
JavaScript优化:

代码拆分与懒加载:利用动态导入(import()), webpack的code splitting等功能按需加载代码。
避免阻塞渲染的JavaScript:使用async或defer属性。
优化代码执行:减少DOM操作,使用事件委托,避免内存泄漏。
图片与媒体优化:

图片懒加载:只在图片进入可视区域时加载。
选择合适的图片格式:WebP、AVIF等现代格式提供更好的压缩率。
图像大小适配:生成不同尺寸图片,适应不同设备,使用srcset和sizes属性。
Webpack打包优化:

Tree Shaking:移除未使用的代码。
UglifyJS或Terser压缩代码。
SplitChunksPlugin 分割公共代码和库到单独文件。
框架特定优化:

Vue:合理使用v-if和v-show,避免不必要的重新渲染;利用Vue的异步组件和路由懒加载;优化v-for的key使用;及时销毁不再使用的事件监听器。
React:使用React.memo防止不必要的组件渲染;合理使用Context API代替props drilling;按需加载组件。
服务端渲染(SSR)或静态站点生成(SSG):

提供首屏快速渲染,改善SEO。
性能监控与分析:

使用Lighthouse、WebPageTest、Chrome DevTools等工具定期进行性能测试和审计。
监控真实用户性能指标(RUM),如First Contentful Paint (FCP)、 Largest Contentful Paint (LCP)、Time to Interactive (TTI)等。

渐进加载
渐进加载是指先加载低质量甚至模糊的图片,然后随着页面继续加载,使用LQIP(低质量图片占位符)技术替换为高质量的完整版本。

这种技术确实提高了首次进行有意义绘制的时间

————————————————————————————————————

arguments.callee是指当前正在执行的函数 匿名函数的递归调用
DOMContentLoaded事件必须等待其所属script之前的样式表加载解析完成后才会触发

循环中多次在刚给 DOM 更新样式位置后,立即通过 offsetTop 获取 DOM 位置。这样的操作会强制启动重排,因为浏览器并不清楚上一个循环内 DOM 有没有改变位置,必须立即重新布局才能计算 DOM 位置


preload本质:preload 是声明式的 fetch,可以改变浏览器加载资源的优先级,强制浏览器请求资源,同时不阻塞文档 onload 事件,也因此可以将 load 事件与脚本解析过程解耦
prefetch本质:让浏览器空闲的时候加载下一页可能需要的资源,同样的load和解析解耦
dns-fetch,让浏览器提前做dns预解析,当静态资源和html不在同一个域的时候,特别好用
async,defer是script的属性,其让html解析与下载并行,但是async下载完之后立即执行,而defer是html解析完之后再执行,一般按照顺序执行,但据说不是百分百靠谱

性能角度考虑,尽量不要把读操作和写操作,放在一个语句里面。DOM 的多个读操作(或多个写操作),应该放在一起。不要两个读操作之间,加入一个写操作
先将元素设为display: none(需要1次重排和重绘),然后对这个节点进行100次操作,最后再恢复显示(需要1次重排和重绘)。这样一来,你就用两次重新渲染,取代了可能高达100次的重新渲染。
第六条,position属性为absolute或fixed的元素,重排的开销会比较小,因为不用考虑它对其他元素的影响。
第七条,只在必要的时候,才将元素的display属性为可见,因为不可见的元素不影响重排和重绘。另外,visibility : hidden的元素只对重绘有影响,不影响重排。


渐进加载
渐进加载是指先加载低质量甚至模糊的图片,然后随着页面继续加载,使用LQIP(低质量图片占位符)技术替换为高质量的完整版本。

这种技术确实提高了首次进行有意义绘制的时间

浏览器每次处理 HTML 标记时,都会完成上述所有步骤:将字节转换为字符,确定令牌,将令牌转换为节点,然后构建 DOM 树。

对于较大的页面,此过程可能需要更长的时间。在制作流畅的动画时,如果浏览器必须处理大量 HTML,这很容易成为瓶颈。
DOM 树会捕获文档标记的属性和关系,但不会告知我们元素在渲染时的外观。这就是 CSSOM 

CSS 字节会依次转换为字符、令牌、节点,最后链接到一个称为“CSS 对象模型”(CSSOM) 的树形结构


阴影的计算和渲染“成本高昂”
CSS 是一种阻塞渲染的资源

CRP 主要包括以下几个阶段:
0. HTML 解析:
• 浏览器开始读取 HTML 文档并构建 DOM 树(Document Object Model)。
• HTML 的每个标签都会生成一个对应的 DOM 节点。
0. CSS 解析:
• 浏览器解析 CSS 文件和内联样式,生成 CSSOM 树(CSS Object Model)。
• CSSOM 树结合 DOM 树,产生一个渲染树,每个渲染树节点对应一个要显示的页面元素。
0. 布局(Layout):
• 浏览器根据渲染树为每个节点计算位置和尺寸,这一步也称为回流(reflow)。
0. 绘制(Paint):
• 将渲染树节点转换为屏幕上的像素,这个过程称为绘制。
0. 合成(Composition):
• 将不同的层(Layers,例如固定定位元素、动画元素等)合成一个最终的页面。
影响 CRP 的因素
0. 阻塞渲染的 CSS 和 JavaScript:
• CSS 文件是渲染阻塞的,因为浏览器必须先构建 CSSOM 才能正确渲染页面。
• JavaScript 文件也可能阻塞渲染,因为它们可能会修改 DOM 和 CSSOM,从而影响页面内容和样式。
0. 资源加载顺序:
• 资源的加载顺序和解析顺序会直接影响页面的显示时间。关键资源应尽量优先加载。
优化关键渲染路径
0. 最小化 CSS 阻塞:
• 内联关键 CSS:将关键样式内联到 HTML 中,减少外部 CSS 文件的请求时间。
• 延迟/异步加载非关键 CSS:使用媒体查询或 loadCSS 等工具延迟加载非关键 CSS。
0. 最小化 JavaScript 阻塞:
• 使用 async 或 defer 属性:对于外部 JavaScript 文件,使用 async 或 defer 属性异步加载脚本。
• 拆分脚本:将必要的脚本部分放在 <head> 中,延迟或异步加载非关键的脚本。
0. 优化资源加载:
• 压缩和合并资源:通过压缩和合并 CSS 和 JavaScript 文件减少 HTTP 请求和文件大小。
• 使用 HTTP/2:HTTP/2 通过多路复用请求提高资源加载速度。
• 缓存资源:利用浏览器缓存和服务器缓存策略减少重复加载时间。
0. 优化图像:
• 延迟加载图像(Lazy Loading):通过 Lazy Loading 技术,图片仅在需要显示时加载。
• 使用合适的图像格式:选择合适的图像格式(如 WebP)和压缩图像以减少文件大小。

最小组件集,并将它们批量处理为单个网络请求

一个组件到 JS 模块的映射,以告知客户端要加载哪些模块。通过将组件标记为延迟加载,JS 模块将稍后加载

静态import和动态import()都很有用。它们各自都有非常独特的用例。使用 staticimport来获取初始绘制依赖项,尤其是首屏内容。在其他情况下,请考虑使用 dynamic 按需加载依赖项import()。

https://github.com/GoogleChrome/web-vitals


优化 JavaScript 和资源
• 消除阻塞渲染的资源。
• 拆分代码并使用动态import()。
• 将所有内容分成单独的部分,并延迟加载折叠下方的 HTML 文件。
• 按需执行并加载 JavaScript。
• <script>通过在标签上使用异步属性并与重要来源建立早期连接(资源提示,如dns-prefetch、preconnect和preload),识别缓慢的 JavaScript 资源并优化加载过程。
• 删除未使用的代码,并最小化和压缩代码。
• 使用 CDN。
• 使用 Service Worker和Workbox控制缓存。
优化图像
• 延迟加载首屏以下的图片。
• 使用 CDN 优化图像,提供适当大小的图像,压缩图像,并采用适合工作的图像格式(WebP、SVG、Web Fonts)。
优化 CLS
• 使用CSSaspect-ratio在图像加载时为图像保留所需的空间。
• min-height在元素延迟加载时使用 CSS来最小化布局偏移。


navigator.connection.effectiveType === '2g

scroll但事件侦听器本身会安排大量必须在主线程上运行的工作。这项工作导致主线程争用,从而增加了交互延迟,导致搜索页面上的 INP 不佳。
• scroll事件处理程序已去抖动,以减少事件回调在给定时间段内触发的次数。通过降低事件scroll回调运行的频率,主线程能够更快地响应搜索页面上的用户交互。
• 通过使用回调对最终的渲染工作进行优先排序requestAnimationFrame。requestAnimationFrame告诉浏览器回调中的工作必须在下一帧之前完成。
• 为了通过更早地触发延迟加载来改善用户体验和视觉性能,在搜索结果页面的倒数第二张卡片上获取了新一批结果。
• 延迟加载期间,每次网络调用获取的结果更少。通过将获取的结果从 30 个减少到 10 个,可以观察到 INP 范围从 870 到 900 减少到 350 到 370。


<input type="text"
         inputmode="numeric"
         autocomplete="one-time-code"
         pattern="\d{6}"
         required>


content-visibility,浏览器可以延迟对不可见内容的渲染
使用 content-visibility 延迟渲染屏幕外的元素


WebCodecs. 音视频编解码器。视频绘制在canvas
主要功能
• 视频编解码:编码和解码视频数据流。
• 音频编解码:编码和解码音频数据流。
• 低延迟:适用于实时应用,比如视频会议和游戏流媒体。
• 高性能:通过直接访问编解码器来提高性能,减少开销。
https://sketch.pixiv.net/

Asm.js 是 WebAssembly 的前身,可以认为是一种 WebAssembly 的“轻量级”实现。虽然 WebAssembly 现在通常更受欢迎,但 Asm.js 仍然是一个重要的技术,因为它不需要特定的浏览器支持(所有支持 JavaScript 引擎的浏览器均支持)。

重大更改(例如增加“html”元素的字体大小)将导致缓存失效、依赖和整个树的重新绘制

当你使用 will-change 属性时,浏览器会根据指定的属性或内容进行优化。例如,如果你告知一个元素的 transform 将会改变,浏览器可能会为该元素分配一个独立的图层,从而避免在动画或变换时触发重排 (reflow) 或重绘 (repaint)

图层是渲染树的一个优化机制,浏览器会将一些元素提升到单独的图层中进行绘制。这些图层最终会被合成(compositing)成一个完整的页面图像。图层可以减少重排(reflow)和重绘(repaint)操作的开销,因为图层中的元素变化不会影响其他图层。
图层的创建条件
浏览器通常在以下情况下创建新的图层:
0. CSS 属性:使用具有 3D 变换(如 transform: translateZ(0)),或其他可能导致提升为独立图层的属性(如 will-change)。
0. 显示属性:使用 CSS 属性 position: fixed 或 position: sticky。
0. 动画和过渡:对包含动画(如 @keyframes)的元素会尝试提升为图层,以提高动画性能。
0. CSS 滤镜和混合模式:使用 filter 或 mix-blend-mode。
0. Canvas 和 视频元素:HTML5 的 <canvas> 和 <video> 元素通常会被提升为独立图层

mix-blend-mode 是一个 CSS 属性,用于设置元素的内容与其父元素的背景或其他内容混合的方式


svg-sprite-loader svgo-loader webpack-ant-icon-loader 
preload-webpack-plugin

Storybook

——————————————————————————

top -H -p pid 进程cpu等命令
查看进程下各线程情况 top -H -p 623

ps aux

ps -aux|grep PID 通过进程号查找应用所在的位置

df -lh 磁盘占用命令

iostat 磁盘读写io

Tcp队列溢出
Netstat -s |egrep "listen|LISTEN"

telnet ip/域名 端口号 来查看网络是否连接

vmstat:监控内存和CPU

netstat -a 网络端口

查询运行的进程PID,命令:ps -ef | grep java


top命令:Linux命令。可以查看实时的CPU使用情况。也可以查看最近一段时间的CPU使用情况。
PS命令:Linux命令。强大的进程状态监控命令。可以查看进程以及进程中线程的当前CPU使用情况。属于当前状态的采样数据。
jstack:Java提供的命令。可以查看某个进程的当前线程栈运行情况。根据这个命令的输出可以定位某个进程的所有线程的当前运行状态、运行代码,以及是否死锁等等。
pstack:Linux命令。可以查看某个进程的当前线程栈运行情况。

font-spider 压缩字体 webfontloader

AVIF 更适合较小且加载速度更快的图像, Chrome 浏览器支持 AVIF,<picture>它来让浏览器选择它们支持的最佳格式


<link rel="preconnect" href="https://p.typekit.net" crossorigin />
<link rel="preconnect" href="https://use.typekit.net" crossorigin />
<link rel="preload" href="//hello.myfonts.net/count/3cde9e" as="style" />

let result = condition ? trueValue : falseValue;
2// 或者更短的 ES6 语法
3let result = condition && trueValue || falseValue;

HTTP/1.1 有很多不足,接下来列举 4 个比较有代表性的,如下所列:
0. 在传输中会出现队首阻塞问题。
0. 响应不分轻重缓急,只会按先来后到的顺序执行。
0. 并行通信需要建立多个 TCP 连接。
0. 由于HTTP是无状态的,所以每次请求和响应都会携带大量冗余信息。

下面会罗列几种内存泄漏的场景:
  第一种是全局变量,它不会被自动回收,而是会常驻在内存中,因为它总能被垃圾回收器访问到。
  第二种是闭包(closure),当一个函数能够访问和操作另一个函数作用域中的变量时,就会构成一个闭包,即使另一个函数已经执行结束,但其变量仍然会被存储在内存中。
  如果引用闭包的函数是一个全局变量或某个可以从根元素追溯到的对象,那么就不会被回收,以后不再使用的话,就会造成内存泄漏。
  第三种是事件监听,如果对某个目标重复注册同一个事件,并且没有移除,那么就会造成内存泄漏。
  第四种是缓存,当缓存中的对象属性越来越多时,长期存活的概率就越大,垃圾回收器也不会清理,部分不需要的对象就会造成内存泄漏


预加载可提升资源的优先级,预提取可降低资源的优先级,预连接可提前进行 TCP 连接或 DNS 查询。
  script 元素有延迟和异步两种运行机制,可有效地防止 HTML 解析的阻塞。

一般来说,TTFB 保持在 75ms 以内会比较完美,而在 200ms 以内会比较理想,若超过 500ms,用户就会感觉到明显地白屏。
  TTFB 常用的优化手段包括增加 CDN 动态加速、减少请求的数据量、服务器硬件升级、优化后端代码(引入缓存、慢查询优化等服务端的工作)。

优化手段包括剔除阻塞渲染的 JavaScript 和 CSS、优化图像、压缩合并文件、延迟加载非关键资源、使用 HTTP/2 协议、SSR 等。


将同步 JavaScript 代码分解为可以作为任务队列的一部分异步运行的单独任务与代码拆分不同,代码拆分是将大型 JavaScript 包分解为较小的文件(对于提高性能也很重要)


在页面终止或丢弃之前,开发人员拥有的最后一个可靠回调visibilitychange是事件(当页面visibilityState变为隐藏时)。由于在隐藏状态下用户无法与页面交互,因此这是运行任何排队空闲任务的最佳时机

• INP 低于或等于 200 毫秒表示网页响应良好。
• INP 高于 200 毫秒且低于或等于 500 毫秒表示网页的响应能力需要改进。
• INP 高于 500 毫秒表示网页响应速度很差。

navigator.deviceMemory
<meta http-equiv="Accept-CH" content="Device-Memory">

https://github.com/GoogleChrome/web-vitals

预取
• 该prefetch函数在启动预取之前首先检查最低连接质量和设备内存。
• 然后,它使用来IntersectionObserver监视元素何时在视口中可见,然后将 URL 添加到列表中进行预取。
• 预取过程通过 进行调度requestIdleCallback,目的是prefetch在主线程空闲时执行该函数

• 对于 CLS,您必须使用服务器端技术动态查找嵌入的大小,并将其插入到您自己的嵌入属性存储中。然后,需要将嵌入传递到您的前端,以防止布局在加载时发生偏移。


后 LCP 方法的策略,该方法在 LCP 事件完成后立即加载 JavaScript 

如果页面上的任何元素加载时间过长或无响应,您的网站的 FID 分数就会受到影响。这可能是由于大量脚本试图同时加载同一页面而导致的。这可以通过延迟加载来解决,这是一种设计模式,允许网站的特定部分根据用户需要首先看到的内容按特定顺序加载

据 Google 称,WebP 无损图像比 PNG 图像小 26%。WebP 有损图像也比同类 JPEG 图像小 25-34%。

请谨慎使用 preconnect,因为它仍可能会占用宝贵的 CPU 时间,并可能导致其他重要资源延迟,尤其是在采用安全连接时。
但是,如果已知会提取第三方网域上的资源,则使用 preconnect 是正常的。如果只是偶尔在高流量网站上发生,preconnect 可能会触发不必要的 TCP 和 TLS 工作。因此,dns-prefetch 更适合第三方资源(例如社交媒体资源、数据分析等)提前执行 DNS 查找

在尺寸不明的网页上异步加载媒体(图片、视频、广告等)。媒体资源一旦加载,就会改变页面布局。
使用占位符
我们对已知尺寸的广告单元和媒体元素使用了样式化占位符,以避免在广告库加载并呈现页面广告时布局发生变化。这样可以确保通过为广告预留空间来消除布局偏移
定义的容器尺寸
我们已为所有图片和容器指定了显式尺寸,这样浏览器引擎在 DOM 元素的宽度和高度可用时便无需计算它们。这样可以避免不必要的布局偏移和额外的绘制工作。

FID
拆分较长的 JavaScript 任务
耗时较长的任务是指时长不短于 50 毫秒的任务。
推迟加载未使用的 JavaScript
我们将网页内容的优先级高于分析等第三方脚本,以确保网页的响应性更强。不过,某些库存在某些限制,因为它们需要在文档 <head> 中加载,才能准确跟踪用户历程。
减少 polyfill
我们减少了对某些 polyfill 和库的依赖,原因是浏览器支持现代 API,而使用 Internet Explorer 等旧版浏览器的用户正在减少。
延迟加载广告
延迟加载非首屏广告有助于缩短主线程阻塞时间,从而提升 FID

合理使用懒加载:对于在初始视口之外的图像和其他资源,结合使用 loading="lazy" 和 fetchpriority="low" 来延迟加载。


fetchpriority="high"

https://github.com/GoogleChromeLabs/idlize/blob/master/IdleQueue.mjs

• preload:当某个资源对页面的初始加载至关重要时使用。例如,关键的 CSS 文件、必须立即执行的 JavaScript 文件和首屏图片。
• prefetch:当某个资源在未来可能会用到,但并不对页面的初始加载至关重要时使用。例如,页面可能导航到的下一步页面的资源


prefers-color-scheme:
window.matchMedia

为了确保面向用户的重要任务先于优先级较低的任务发生,您可以通过短暂中断任务队列来让出主线程
await scheduler.yield()
function yieldToMain () {
  return new Promise(resolve => {
    setTimeout(resolve, 0);
  });
}
function yieldToMainUiBlocking () {
  return new Promise((resolve) => {
    if ('scheduler' in window) {
      if ('yield' in window.scheduler) {
        return window.scheduler.yield().then(() => resolve(true));
      }

      if ('postTask' in window.scheduler) {
        return window.scheduler.postTask(() => resolve(true), { priority: 'user-blocking' });
      }
    }

    resolve(false);
  });
};
function yieldToMainBackground () {
  return new Promise((resolve) => {
    if ('scheduler' in window) {
      if ('yield' in window.scheduler) {
        return window.scheduler.yield().then(() => resolve(true));
      }

      if ('postTask' in window.scheduler) {
        return window.scheduler.postTask(() => resolve(true), { priority: 'user-visible' });
      }
    }

    setTimeout(() => { resolve(true) }, 0);
  });
};

setTimeout 是拆分任务的有效方式,但也有一个缺点:当您通过推迟在后续任务中运行代码来让出主线程时,该任务会被添加到队列的末尾

些用户事件中存在较长的任务,可以通过经常让位于主线程来拆分这些任务


model-viewer

导致 INP 不佳的原因。有很多潜在原因,例如第三方脚本在主线程上调度许多任务、DOM 大小较大、事件回调开销大以及其他问题

扁平化 DOM 结构来简化它们。这样做可以减少 DOM 元素的数量。如果您担心扁平化 DOM 结构对样式设置的影响,建议您使用更现代(且速度更快)的布局模式,例如 flexbox 或 grid。延迟加载 HTML

content-visibility 属性,该属性实际上是一种延迟渲染屏幕外 DOM 元素的方式


display: none -> 空闲的时间点requestIdleCallback 删除dom

去掉css文件内import 内联字体改成link方式

font-spider 压缩字体 webfontloader

——————————————————————————————————————

 https://dev.to/

https://squoosh.app/

heapdump.cn

https://pagespeed.web.dev/

https://www.webgamedev.com/resources/people

https://taligarsiel.com/Projects/howbrowserswork1.htm

https://juejin.cn/post/6844904131346300942

https://hpbn.co/

https://jakearchibald.com/

https://github.com/sisterAn/blog/issues/63

https://tsejx.github.io/webpack-guidebook/best-practice/optimization/collection/

https://juejin.cn/post/7351300892572745764

https://martinfowler.com/

Medium: (https://medium.com/)上有大量技术博客,很多开发者和团队会在这里分享项目经验、技术选型理由、遇到的挑战及解决方法。内容覆盖广泛,从前端到后端,从AI到区块链都有。

Reddit: (https://www.reddit.com/r/programming/)特别是r/programming、r/webdev、r/softwareengineering等子版块,经常有技术讨论和项目分享,社区活跃,可以直接与他人交流。

Tech Blogs and Personal Websites: 许多知名开发者和技术领导者有自己的博客,他们会详细记录项目经验、技术选型、架构设计思路以及遇到的技术难题和解决方案。例如Martin Fowler的博客(https://martinfowler.com/)就非常有名。

LinkedIn Pulse: (https://www.linkedin.com/pulse/)LinkedIn上的Pulse板块,许多专业人士会在这里分享行业见解、项目经历和职业发展经验。

Project Management Websites: 如PMI(Project Management Institute)的博客(https://www.pmi.org/learning/thought-leadership/blog)或Trello的博客(https://blog.trello.com/),提供了项目管理和团队协作的洞见和案例分析

 

posted @ 2024-08-10 15:21  创业男生  阅读(8)  评论(0编辑  收藏  举报