H5 性能优化方案

1、减小cookie传输css

cookie传输会形成带宽浪费,能够:html

  • 减小cookie中存储的东西
  • 静态资源不须要cookie,能够采用其余的域名,不会主动带上cookie。

2.避免过多的回流与重绘webpack

3. Gizp 压缩web

4JavaScriptCssHtml压缩跨域

工程化项目中直接使用对应的插件便可,webpack的主要有下面三个:浏览器

  • UglifyJS
  • webpack-parallel-uglify-plugin
  • terser-webpack-plugin

5http2首部压缩缓存

6.webpack 的优化cookie

1DllPlugin 提高构建速度网络

2splitChunks 拆包antd

  1. 骨架屏幕,减小页面的回流和重绘
  2. 谷歌浏览器的light house插件。能够检测性能

本文主要介绍preload的使用,以及与prefetch的区别。而后会聊聊浏览器的加载优先级。

preload 提供了一种声明式的命令,让浏览器提早加载指定资源(加载后并不执行),在须要执行的时候再执行。提供的好处主要是

  • 将加载和执行分离开,可不阻塞渲染和 document 的 onload 事件
  • 提早加载指定资源,再也不出现依赖的font字体隔了一段时间才刷出

如何使用 preload

使用 link 标签建立

<!-- 使用 link 标签静态标记须要预加载的资源 -->

<link rel="preload" href="/path/to/style.css" as="style">

<!-- 或使用脚本动态建立一个 link 标签后插入到 head 头部 -->

<script>

const link = document.createElement('link');

link.rel = 'preload';

link.as = 'style';

link.href = '/path/to/style.css';

document.head.appendChild(link);

</script>

使用 HTTP 响应头的 Link 字段建立

Link: https://example.com/other/sty...; rel=preload; as=style

如咱们经常使用到的 antd 会依赖一个 CDN 上的 font.js 字体文件,咱们能够设置为提早加载,以及有一些模块虽然是按需异步加载,但在某些场景下知道其一定会加载的,则能够设置 preload 进行预加载,如:

<link rel="preload" as="font" href="https://at.alicdn.com/t/font_zck90zmlh7hf47vi.woff">

<link rel="preload" as="script" href="https://a.xxx.com/xxx/PcCommon.js">

<link rel="preload" as="script" href="https://a.xxx.com/xxx/TabsPc.js">

如何判断浏览器是否支持 preload

目前咱们支持的浏览器主要为高版本 Chrome,因此可放心使用 preload 技术。 其余环境在 caniuse.com 上查到的支持状况以下:

在不支持 preload 的浏览器环境中,会忽略对应的 link 标签,而若须要作特征检测的话,则能够用以下方法:

const isPreloadSupported = () => {

const link = document.createElement('link');

const relList = link.relList;

if (!relList || !relList.supports) {

return false;

}

return relList.supports('preload');

};

如何区分 preloadprefetch

  • preload 是告诉浏览器页面一定须要的资源,浏览器必定会加载这些资源;
  • prefetch 是告诉浏览器页面可能须要的资源,浏览器不必定会加载这些资源。

preload 是确认会加载指定资源,如在咱们的场景中,x-report.js 初始化后必定会加载 PcCommon.js 和 TabsPc.js, 则能够预先 preload 这些资源;

prefetch 是预测会加载指定资源,如在咱们的场景中,咱们在页面加载后会初始化首屏组件,当用户滚动页面时,会拉取第二屏的组件,若能预测用户行为,则能够 prefetch 下一屏的组件。

preload 将提高资源加载的优先级

使用 preload 前,在遇到资源依赖时进行加载:

使用 preload 后,无论资源是否使用都将提早加载:

能够看到,preload 的资源加载顺序将被提早:

避免滥用 preload

使用 preload 后,Chrome 会有一个警告:

如上文所言,若不肯定资源是一定会加载的,则不要错误使用 preload,以避免本末倒置,给页面带来更沉重的负担。

固然,能够在 PC 中使用 preload 来刷新资源的缓存,但在移动端则须要特别慎重,由于可能会浪费用户的带宽。

避免混用 preloadprefetch

preload 和 prefetch 混用的话,并不会复用资源,而是会重复加载。

<link rel="preload" href="https://at.alicdn.com/t/font_zck90zmlh7hf47vi.woff" as="font">

<link rel="prefetch" href="https://at.alicdn.com/t/font_zck90zmlh7hf47vi.woff" as="font">

使用 preload 和 prefetch 的逻辑可能不是写到一块儿,但一旦发生对同一资源 preload 或 prefetch 的话,会带来双倍的网络请求,这点经过 Chrome 控制台的网络面板就能甄别:

避免错用 preload 加载跨域资源

若 css 中有应用于已渲染到 DOM 树的元素的选择器,且设置了 @font-face 规则时,会触发字体文件的加载。 而字体文件加载中时,DOM 中的这些元素,是处于不可见的状态。对已知必加载的 font 文件进行预加载,除了有性能提高外,更有体验优化的效果。

在咱们的场景中,已知 antd.css 会依赖 font 文件,因此咱们能够对这个字体文件进行 preload:

<link rel="preload" as="font" href="https://at.alicdn.com/t/font_zck90zmlh7hf47vi.woff">

然而我发现这个文件加载了两次:

缘由是对跨域的文件进行 preload 的时候,咱们必须加上 crossorigin 属性:

<link rel="preload" as="font" crossorigin href="https://at.alicdn.com/t/font_zck90zmlh7hf47vi.woff">

再看一下网络请求,就变成一条了。

W3 规范是这么解释的:

Preload links for CORS enabled resources, such as fonts or images with a crossorigin attribute, must also include a crossorigin attribute, in order for the resource to be properly used.

那为什么会有两条请求,且优先级不一致,又没有命中缓存呢?这就得引出下一个话题来解释了。

不一样资源加载的优先级规则

咱们先来看一张图:

这张表详见:Chrome Resource Priorities and Scheduling

这张图表示的是,在 Chrome 46 之后的版本中,不一样的资源在浏览器渲染的不一样阶段进行加载的优先级。 在这里,咱们只须要关注 DevTools Priority 体现的优先级,一共分红五个级别:

  • Highest 最高
  • Hight 高
  • Medium 中等
  • Low 低
  • Lowest 最低

html 主要资源,其优先级是最高的

css 样式资源,其优先级也是最高的

CSS(match) 指的是对已有的 DOM 具有规则的有效的样式文件。

script 脚本资源,优先级不一

前三个 js 文件是写死在 html 中的静态资源依赖,后三个 js 文件是根据首屏按需异步加载的组件资源依赖,这正验证了这个规则。font 字体资源,优先级不一

css 样式文件中有一个 @font-face 依赖一个 font 文件,样式文件中依赖的字体文件加载的优先级是 Highest; 在使用 preload 预加载这个 font 文件时,若不指定 crossorigin 属性(即便同源),则会采用匿名模式的 CORS 去加载,优先级是 High,看下图对比: 第一条 High 优先级也就是 preload 的请求:

第二条 Highest 也就是样式引入的请求:

能够看到,在 preload 的请求中,缺乏了一个 origin 的请求头字段,表示这个请求是匿名的请求。 让这两个请求能共用缓存的话,目前的解法是给 preload 加上 crossorigin 属性,这样请求头会带上 origin, 且与样式引入的请求同源,从而作到命中缓存:

<link rel="preload" as="font" crossorigin href="https://at.alicdn.com/t/font_zck90zmlh7hf47vi.woff">

这么请求就只剩一个:

在网络瀑布流图中,也显示成功预加载且后续命中缓存再也不二次加载:

总结

preload 是个好东西,能告诉浏览器提早加载当前页面必须的资源,将加载与解析执行分离开,作得好能够对首次渲染带来不小的提高,但要避免滥用,区分其与 prefetch 的关系,且须要知道 preload 不一样资源时的网络优先级差别。

preload 加载页面必需的资源如 CDN 上的字体文件,与 prefetch 预测加载下一屏数据,兴许是个不错的组合。

相关文章
相关标签/搜索