前端性能优化(图文并茂,通俗易懂)

寒水寺一禅 -
前端性能优化(图文并茂,通俗易懂)
一、静态和动态导入

默认情况下,我们静态导入的所有模块都会添加到初始捆绑包中。使用默认 ES2015 导入语法 导入的模块将静态导入。
import module from 'module'

image.png

实际上,我们可以而把那些在需要时展示的组件,通过动态导入来实现

import("b.vue").then()  //动态导入,在打包时会自动chunk

image.png

如上图,在点击时 emoji 时,才去加载 emoji-picker 组件。

动态路由和动态组件会自动拆分bundle。

二、可见性导入

除了用户交互之外,我们通常还有在初始页面上不可见的组件。一个很好的例子是延迟加载图像,这些图像在视口中不直接可见,但只有在用户向下滚动后才会加载。

image.png

三、交互时导入(懒惰式加载)

当用户与需要它的 UI 交互时,延迟加载非关键资源

您的页面可能包含不是立即必需的组件或资源的代码或数据。例如,用户看不到用户界面的一部分,除非他们单击或滚动页面的某些部分。例如模态框、列表的详情页、视频播放器或聊天小部件、第三方资源等等

与其立即加载这些资源,不如在更合适的时刻加载它们,例如:

当用户首次单击以与该组件进行交互时将组件滚动到视图中或延迟该组件的加载,直到浏览器空闲(通过 requestIdleCallback API)。

加载资源的不同方法概括如下:

立即加载资源(加载脚本的正常方式)Lazy (路由)- 当用户导航到路由或组件时加载Lazy (交互时) - 当用户单击 UI 时加载(例如显示聊天)Lazy (在视口中)- 当用户滚动到组件时加载Prefetch - 预拉取Preload - 预加载

如: 第三方 UI
image.png

如: 视频播放器嵌入
image.png

如: 认证
image.png

如:聊天小部件
image.png

如: 帮助页
image.png

四、基于路由的拆分

根据当前路由动态加载组件

{
    path: "/home",
    component: () => import(/* webpackChunkName: "home"*/  "@/components/layout/Index.vue"),
    children: [
      //todo     
    ],
},

image.png

五、捆绑拆分

将代码拆分为可重用的小块

构建现代 Web 应用程序时,打包器例如,Webpack或rollup获取应用程序的源代码,并将其打包到一个或多个bundle中,
当用户访问网站时, bundle请求并加载,以便将数据显示到用户的屏幕。

bundle越大,则浏览器引擎到达进行第一次呈现调用的行所需的时间越长。在那之前,用户必须盯着空白屏幕相当长一段时间,这可能是.非常令人沮丧!

我们希望尽快向用户显示数据。更大的bundle导致加载时间、处理时间和执行时间增加.如果我们能减小这个捆绑包的大小,以便加快速度,那就太好了。

image.png

六、断续器模式

通过预缓存、延迟加载和最小化往返来优化初始负载

当我们想要访问一个网站时,我们首先必须向服务器发出请求才能获得这些资源。入口点指向的文件从服务器返回,这通常是我们应用程序的初始HTML文件!浏览器的 HTML 解析器在开始从服务器接收此数据后立即开始解析此数据。如果解析器发现需要更多资源(如样式表或脚本),则会向服务器发送另一个 HTTP 请求以获取这些资源!

image.png

断续器模式侧重于四个主要的性能注意事项:

有效地推送关键资源,从而最大限度地减少到服务器的往返量并减少加载时间。尽快渲染初始路由,提升用户体验在后台为经常访问的路由预缓存资源,以最大限度地减少对服务器的请求量并实现更好的脱机体验懒惰地加载不经常请求的路线或资源

image.png

七、Tree Shaking

通过消除死代码来减小捆绑包大小

我们可能会将代码添加到我们的捆绑包中,而这些代码在应用程序中的任何地方都没有使用。这段死代码可以消除,以减小捆包的尺寸,并防止不必要地加载更多数据!消除死代码的过程在将其添加到我们的捆绑包之前,称为tree-shaking

image.png

八、Preload

在发现关键资源之前通知浏览器(指关键资源加载完后,会接着加载preload的资源。)

<link rel="preload"> 方式
image.png

webpackPreload: true 方式(Webpack 4.6.0+)

const EmojiPicker = import(/* webpackPreload: true */ "./EmojiPicker");

image.png

九、Prefetch

获取和缓存可能很快请求的资源(指关键资源加载完后,不一定会加载prefetch的资源,可能等到具体需要时才加载)

<link rel="prefetch">方式
image.png

webpackPrefetch: true方式

const EmojiPicker = import(/* webpackPrefetch: true */ "./EmojiPicker");

image.png

十、虚拟列表

这是在动态列表中仅呈现可见内容行而不是整个列表的想法。呈现的行只是完整列表的一小部分,当用户滚动时,可见的内容(窗口)会移动。这可以提高渲染性能。

image.png

十一、压缩脚本

减少通过网络传输脚本所需的时间

1、Gzip 和 Brotli 是两种最常用的被现在浏览器所支持的 压缩js 方式(需要和nginx配置使用)2、Brotli 在相似的压缩级别下提供了更好的压缩比(但是需要https,而gzip在http下也可以)3、如果你使用 webpack来打包你得代码,你可以使用 CompressionPlugin 压缩为gzip 或者 使用 BrotliWebpackPlugin 压缩为brotli,如果使用rollup,则使用rollup-plugin-gzip插件4、Gzip压缩切换到Brotli压缩,文件体积大小会降低15%-25%左右。5、compress(a + b) <= compress(a) + compress(b) - 单个大捆绑包将比多个较小的捆绑包提供更好的压缩

HTTP 数据压缩可以以不同的方式进行分类。其中之一是有损与无损。
有损压缩意味着压缩-解压缩循环会导致文档略有更改,同时保持其可用性。最终用户大多无法察觉到这种变化。有损压缩最常见的示例是图像的 JPEG 压缩。
使用无损压缩,压缩和后续解压缩后恢复的数据将与原始数据精确匹配。PNG 图像是无损压缩的一个示例。无损压缩与文本传输相关,应应用于基于文本的格式,如 HTML、CSS 和 JavaScript。

有多个工具可用于缩小 HTML、CSS 和 JS 资源。Terser 是 ES6+ 中流行的 JavaScript 压缩工具,默认情况下,Webpack 包含一个用于此库的插件,用于创建缩小的构建文件。
也可以使用esbuild压缩,它是一种比terser速度还快的压缩方式。能快10-100倍

静态与动态压缩

缩小有助于显著减小文件大小,但压缩 JS 可以提供更显著的增益。可以通过两种方式实现服务器端压缩。
静态压缩:可以使用静态压缩来预压缩资源,并在生成过程中提前保存它们。常用于打包时压缩。比如webpack或者rollup在打包时,就提前压缩为gzip,然后放到 nginx上,配置 gzip_static:on;这样在http请求时,会获取 gzip的文件,然后浏览器解压缩,显示页面。
动态压缩:通过此过程,当浏览器请求资源时,压缩会动态进行。常用于接口中的数据压缩,在请求接口时,服务器动态压缩数据,然后返回到浏览器。

Gzip 和Brotli算法

Gzip压缩格式已经存在了近30年,是一种基于Deflate算法的无损算法。Deflate算法本身使用LZ77算法和霍夫曼编码的组合。
LZ77 算法标识重复的字符串,并将它们替换为反向引用,反向引用是指向它以前出现的位置的指针,后跟字符串的长度。随后,霍夫曼编码识别常用的引用,并用具有较短位序列的引用替换它们。较长的位序列用于表示不经常使用的引用。

image.png

所有主流浏览器都支持 Gzip。

Brotli
2015年,谷歌推出了Brotli算法和Brotli压缩数据格式。与GZip一样,Brotli也是一种基于LZ77算法和霍夫曼编码的无损算法。此外,它还使用二阶上下文建模以类似的速度产生更密集的压缩。上下文建模是一项功能,它允许在同一块中对同一字母表使用多个霍夫曼树。Brotli 还支持更大的窗口大小用于反向引用,并具有静态字典。这些功能有助于提高其作为压缩算法的效率。
Brotli目前受到所有主要服务器和浏览器的支持,并且越来越受欢迎。

比较gzip和brotli

下表显示了不同压缩级别的 Brotli 和 Gzip 压缩率和速度的基准比较。
image.png

启用压缩

webpack配置

module.exports = {
 //...
 plugins: [
   //...
   new CompressionPlugin()
 ]
}

Nginx 这样的 HTTP 代理上启用它

server {
        listen 8080;
        server_name localhost;

        # 需要http_gzip_static_module 模块
        gzip_static on;  
        
        location / {
            alias html
            index index.html index.htm;
            try_files $uri $uri/ /html/index.html;
        }
}

浏览器通过请求中的 Accept-Encoding HTTP 标头传达它支持的压缩算法,这表明浏览器支持 Gzip 和brotli
Accept-Encoding: gzip, br

服务器将返回 Content-Encoding HTTP 响应标头,以指示响应中使用的压缩算法。例如,
Content-Encoding: br

image.png

特别申明:本文内容来源网络,版权归原作者所有,如有侵权请立即与我们联系(cy198701067573@163.com),我们将及时处理。

Tags 标签

前端javascript性能优化node.jswebpack

扩展阅读

加个好友,技术交流

1628738909466805.jpg