硬件断点反跳似乎
by Atila Fassina
通过阿蒂拉·法西纳(Atila Fassina)
高性能应用程序:多路复用,反跳,系统字体和其他技巧 (High Performance Apps: Multiplexing, Debouncing, System Fonts, and other tricks)
Here are some performance tips for your client-side application that you can start using immediately.
这里是您的客户端应用程序的一些性能提示,您可以立即开始使用。
These will boost your app’s perceived performance significantly. And most of them only require quick tweaks to your app.
这些将大大提高您应用的感知性能 。 而且大多数只需要快速调整您的应用程序即可。
预加载您的资源 (Preload your resources)
rel="preload"
is a way of letting your browser know that a specific resource is important. This way, your browser will fetch the resource as quickly as possible. Then it will store it locally until it finds the expected reference in the DOM.
rel="preload"
是一种让浏览器知道特定资源很重要的方法。 这样,您的浏览器将尽快获取资源。 然后它将在本地存储它,直到在DOM中找到期望的引用为止。
Here are some examples of using a link
with this attribute:
以下是使用带有此属性的link
一些示例:
The as
attribute is mandatory here, because it tells the browser what filetype that it is fetching. This way it can interpret the request and add the proper headers. Otherwise, your request would have the incorrect mime/type
so your browser wouldn’t be able to parse it.
as
属性在这里是必需的,因为它告诉浏览器要获取的文件类型。 这样,它可以解释请求并添加适当的标头。 否则,您的请求将具有错误的mime/type
因此您的浏览器将无法解析它。
By the way, mime/type
is the file type declaration that developers use on the web. This is similar to the file extensions on your desktop operating system. If you have the incorrect mime/type
, the browser won’t know how to parse the file.
顺便说一句, mime/type
是开发人员在网络上使用的文件类型声明。 这类似于桌面操作系统上的文件扩展名。 如果您的mime/type
不正确,浏览器将不会解析该文件。
Font files are a bit trickier to preload. Here are some things to keep in mind:
字体文件要预加载有点棘手。 这里要记住一些事情:
crossorigin
—The W3C requires that font fetches be anonymous. In a nutshell, this means even when the request is coming from the same domain, it will be treated as a cross-origin request.crossorigin
— W3C要求字体提取是匿名的。 简而言之,这意味着即使请求来自同一域,也将其视为跨源请求。type
— This specifies which format the browser should use when fetching the font.type
—type
—指定浏览器在获取字体时应使用的格式。
Also, be sure to only add the first format to your font-face
declaration. Preloading multiple font formats is against best practices, is bad UX, and wastes your users’ bandwidth.
另外,请确保仅将第一种格式添加到您的font-face
声明中。 预加载多种字体格式违反了最佳实践,是糟糕的UX,并且浪费了用户的带宽。
You can read more about preloading here.
您可以在此处阅读有关预加载的更多信息 。
使用特定于操作系统的字体 (Use Operating System-specific fonts)
By using system fonts, it’s possible to emulate your users’ Operational System’s look and feel. This way, your application has a better chance of looking like a native one, while saving your user the trouble of downloading more resources.
通过使用系统字体,可以模拟用户操作系统的外观。 这样,您的应用程序更有可能看起来像本机应用程序,同时为用户节省了下载更多资源的麻烦。
Let's analyze more closely each of these declarations:
让我们更仔细地分析以下每个声明:
apple-system: as the name suggests, these target OSX/iOS-related systems
苹果系统 :顾名思义,这些目标与OSX / iOS相关的系统
system-ui: these target the system font, regardless of the system
system-ui :这些目标系统字体,与系统无关
BlinkMacSystemFont: Chrome’s font on MacOS
BlinkMacSystemFont :MacOS上的Chrome字体
Segoe UI: Windows/Windows Phone
Segoe UI :Windows / Windows Phone
Roboto: Android
Roboto :Android
This solution is widely used even though many developers don’t yet know about it. For example, at time of writing this article, it's used at:
即使许多开发人员对此尚不了解,该解决方案仍被广泛使用。 例如,在撰写本文时,它用于:
- GitHub 的GitHub
- Wordpress WordPress的
- Bootstrap 引导程序
- Medium 中
- Ghost 鬼
- Zeit 时代精神
And probably others that I haven't yet heard about.
可能还有其他我还没有听说过的东西。
消除和限制对服务器的呼叫 (Debounce and throttle calls to your server)
Some events get fired many times more than we intend to trigger them. For example: resize, scroll, keypress/keydown/keyup, or change.
有些事件比我们打算触发它们的次数要多得多。 例如:调整大小,滚动,按键/向下键/向上键或更改。
Resize and scroll, for instance, get fired on every pixel. That’s an awful lot of chatter if you just want to adjust some elements on breakpoint, or add a class to a header as the user scrolls down the page.
例如,调整大小和滚动会在每个像素上触发。 如果您只想调整断点上的某些元素,或者在用户向下滚动页面时将一个类添加到标头中,那将是非常麻烦的事情。
If you get an autocomplete, for example, you don’t want to fire on every key press. In most cases, it would be good to start autocompleting after the 3rd character. Especially if you plan to fetch information for that.
例如,如果您获得自动完成功能,则不想在每次按键时都触发。 在大多数情况下,最好在第三个字符之后开始自动填充。 特别是如果您打算为此获取信息。
Debounce holds up your trigger until the event stops firing for a given amount of time (usually 500 milliseconds).
防抖动可保持触发状态,直到事件在给定的时间(通常为500毫秒)内停止触发为止。
Throttle holds up your trigger if it attempts to fire more often than a given interval (usually 25o milliseconds).
如果节气门尝试触发的次数超过给定间隔(通常为25o毫秒),则它会阻止触发器。
使用异步/延迟 (Use async/defer)
Remember the good old window.onload
function? Or moving all the scripts to the bottom of your HTML? Yeah, well, async
and defer
are here to give you some better options.
还记得旧的window.onload
函数吗? 还是将所有脚本移到HTML的底部? 是的, async
和defer
功能可以为您提供更好的选择。
Async will download your script during the HTML parsing. It will run it asynchronously (if possible) — regardless of where it’s declared.
Async会在HTML解析期间下载您的脚本。 它将异步运行(如果可能的话)—无论在何处声明它。
Defer will also download your script during the HTML parsing, though it will only attempt to run your script after the parser is finished. Also, declaring multiple deferred scripts guarantees that they will be executed in declaration order.
Defer还将在HTML解析期间下载您的脚本,尽管它只会在解析器完成后尝试运行您的脚本。 此外,声明多个延迟脚本可确保它们将按声明顺序执行。
<script async src="./my-async-script.js"></script><script defer src="./my-deferred-script.js"></script>
数据:uri和<svg> (data:uri and <svg>)
When adding icons or small image files, an interesting technique is to use data-uri
. A data
URL is usually encoded as base64
and provides an easy way of embedding files into your DOM directly. In a similar way, you can add <s
vg> as markup. This way your SVG image will be parsed and rendered by the browser.
添加图标或小图像文件时,一种有趣的技术是使用data-uri
。 data
URL通常被编码为base64
并提供了一种将文件直接嵌入DOM的简便方法。 以类似的方式,您可以添加<s
vg>作为标记。 这样,您的SVG图像将被浏览器解析和呈现。
Note that using the <s
vg> instead of embedding as an
<img> or icon-font brings other functionalities that are beyond the scope of this article.
请注意,使用<s
vg>而不是as an
<img>或图标字体进行嵌入会带来其他功能,这些功能不在本文的讨论范围之内。
Adding the files straight into your markup instead of referencing them saves you one HTTP request each time. This is nice when your file is so small that it isn’t worth the trouble of making a roundtrip to the server. Especially while on mobile networks, since handshakes can be quite expensive.
直接将文件添加到标记中而不是引用它们,每次都可以节省一个HTTP请求。 当您的文件太小以至于不值得往返服务器时,就很好了。 特别是在移动网络上,因为握手可能会非常昂贵。
使用多路传输 (Use Multiplexing)
If your server is already working with HTTP2, embedding files might not be worthwhile. This happens because HTTP2 has a feature called Multiplexing.
如果您的服务器已经在使用HTTP2,则嵌入文件可能不值得。 发生这种情况是因为HTTP2具有称为多路传输的功能。
This means your browser can send multiple requests and receive multiple responses "bundled" into a single TCP connection. So the workload associated with DNS lookups and handshakes is saved for files coming from the same server.
这意味着您的浏览器可以发送多个请求并接收“ 捆绑 ”到单个TCP连接中的多个响应。 因此,与DNS查找和握手相关的工作负载将保存到来自同一服务器的文件中。
In addition, HTTP2 also provides you with Server Push. This means it’s possible to send files even before the user requests them. This increases the perceived performance significantly.
此外,HTTP2还为您提供服务器推送。 这意味着甚至可以在用户请求文件之前发送文件。 这显着提高了感知性能。
I hope these tips help you improve the perceived performance of your app. If you found this article helpful, give me some claps ?. You can also give me feedback on this on Twitter.
希望这些技巧能帮助您改善应用的感知性能。 如果您觉得这篇文章有帮助,请给我一些鼓掌? 您也可以就T witter给我反馈。
进一步阅读 (Further Reading)
在rel = preload上: (On rel=preload:)
在系统字体上: (On system fonts:)
硬件断点反跳似乎