今回は、ページ最適化の方法と、ページ最適化のための注意点についてまとめてみました。実際の事例を見てみましょう。
公式ウェブサイトのホームページの読み込みを高速化し、ユーザーの操作により迅速に応答し、ユーザーによりフレンドリーなエクスペリエンスを提供します。
ページリクエストの数を減らし、リクエストによって占有される帯域幅を減らし、リソースを節約します。
は、粒度に応じて 2 つのカテゴリに分類されます:
ページ レベルの最適化 (HTTP リクエストの数、リソースの結合と圧縮、リソースの読み込みタイミングなど)
コード レベルの最適化 ( DOM操作の最適化、CSSの選択文字の最適化、HTML構造の最適化)
ページレベルの最適化の目標は、基本的にHTTPリクエストの数を減らし、リクエストされるリソースの量を減らす方法です。各リクエストには、時間コストとリソース コストの両方を含むコストがかかります (完全なリクエストには、DNS アドレス指定、サーバーとの接続の確立、データの送信、サーバーの応答の待機、データの受信などの「長い」プロセスが必要です。複雑です)。 process)
静的ファイルの種類に応じて、gulp ツールを使用して js ファイルと css ファイルをマージおよび圧縮できます。
たとえば、公式 Web サイトのプロジェクトには 7 つの CSS ファイルと 10 ~ 20 を超える js ファイルがあり、静的リソースをマージして圧縮すると、HTTP オーバーヘッドを削減できます。
頻繁に変更されないすべてのリソース (jquery、さまざまなライブラリ、プラグインなど) を、vender.css、vender.js という名前の 1 つのファイルにマージして圧縮します。オンラインで頻繁に変更されるファイルは、index.css、index.js という名前で 1 つのファイルに結合および圧縮され、ハッシュ スタンプが追加されます。インデックスなどのファイルの内容は、基本的にオンラインになるたびに変更されるため、ハッシュは後で追加されます。 gulp は自動的に構築されます。poke も異なりますが、レンダリング タイプは変更されないため、ブラウザのキャッシュ メカニズムを合理的に使用できます。
jq の lazyload
プラグインを使用して、画像の遅延読み込みを実装します。必要な画像リソースをロードする前に、スクロール バーが対応する場所までスクロールするまで待ちます。 lazyload
插件实现图片懒加载。等滚动条滚动到对应的地方再加载所需要的图片资源。
不直接使用设计给的两倍图,用css的devicePixelRatio
检查设备的像素比,辅助区分视网膜设备还是非视网膜设备来决定加载两倍图还是原始大小的图片。
图片上传到cdn之前在保证不失真的情况下,用gulp-imagemin
工具压缩下大小。
将下图这样的小图片全部做成雪碧图,单色可以考虑用icon-font
来实现。或者直接在页面写svg代码和转成base64写到页面也行,总之是要减少http的请求数。
将首屏第一时间呈现给用户。
具体的做法是除了首屏dom元素之外,将所有的dom元素用一个template
元素进行包裹,等window监听到load事件后,将剩余的dom部分全部插到页面中。(tips:为避免用户可能还没等到window的load事件就开始滚动页面,可以将首屏的范围扩大。)
DNS预读取是一项使浏览器主动去执行域名解析的功能。DNS请求需要的带宽非常小,但是延迟却有点高。
下面是引用MDN的一句话:
在某些浏览器中这个预读取的行为将会与页面实际内容并行发生(而不是串行)。正因如此,某些高延迟的域名的解析过程才不会卡住资源的加载。
这样可以极大的加速(尤其是移动网络环境下)页面的加载。在某些图片较多的页面中,在发起图片加载请求之前预先把域名解析好将会有至少 5% 的图片加载速度提升。
具体做法:head
标签里加上
<link rel="dns-prefetch" href="https://data.dadaabc.com/">
data.dadaabc.com
devicePixelRatio
を使用してデバイスのピクセル比を確認し、Retina デバイスと非 Retina デバイスを区別して、デザインによって提供される二重画像を直接使用しないでください。ダブル画像またはオリジナルサイズの画像をロードします。 🎜🎜🎜🎜画像を cdn にアップロードする前に、gulp-imagemin
ツールを使用して、歪みなくサイズを圧縮します。 🎜🎜🎜🎜以下のような小さな画像をすべてスプライト画像にします。モノクロの場合は、icon-font
を使用して実現することを検討できます。または、svg コードをページに直接記述し、それを Base64 に変換してページに書き込むこともできます。つまり、http リクエストの数を減らす必要があります。 🎜🎜🎜🎜🎜🎜3. 🎜🎜 をロードすると、最初の画面がすぐにユーザーに表示されます。 🎜具体的な方法は、最初の画面の DOM 要素を除くすべての DOM 要素を template
要素でラップし、ウィンドウが読み込みイベントを監視した後、残りのすべての DOM 部分をページに挿入することです。 (ヒント: ウィンドウの読み込みイベントを待つ前にユーザーがページのスクロールを開始しないようにするには、最初の画面の範囲を拡張できます。) 🎜🎜4. DNS 事前読み取り🎜🎜 DNS 事前読み取りは、次のことを可能にする方法です。ブラウザはドメイン名解決機能をアクティブに実行します。 DNS リクエストに必要な帯域幅はほとんどありませんが、遅延は少し高くなります。 🎜以下は MDN からの引用です: 🎜一部のブラウザでは、このプリフェッチ動作は、ページの実際のコンテンツと (逐次ではなく) 並行して発生します。このため、一部の高遅延ドメイン名の解決プロセスでは、リソースの読み込みがブロックされません。 🎜これにより、ページの読み込みが大幅に高速化されます (特にモバイル ネットワーク環境)。多くの画像を含む一部のページでは、画像の読み込みリクエストを開始する前にドメイン名を事前解決すると、画像の読み込み速度が少なくとも 5% 向上します。🎜具体的な方法: 🎜
head
タグに、🎜var ele = document.getElementById('myp'); ele.style.borderLeft = '1px'; ele.style.borderRight = '2px'; ele.style.padding = '5px';
data.dadaabc.com
を追加します (他に静的リソースがある場合)。リンクされたドメイン名をすべて一緒に追加します。 🎜同域下浏览器能并发的请求有限,为了增加并发,尤其是一些静态资源上,可以使用多个域名。但由于域名DNS解析本身也是耗时的,所以也不是越多越好,chrome最大支持6路并发,所以一般设置2-4个域名较为合适。
具体的做法是:再增加cdn域名来下载静态资源。比如图片全部用img.dadaabc.com/
域名,css资源全部用css.dadaabc.com/
域名,这些域名最终全部指向同样的cdn服务器。静态资源域名加前缀可以用gulp-rev-replace
来实现。
统计代码全部放到window的load事件之后执行。为了便于管理统计代码,例如页面加上一些埋点,增加删除统计产品,我们可以借助Google Tag Manager
工具来统一管理。
具体做法是:页面只拉取Google Tag Manager
提供的gtm
代码,该js代码含有全部的统计产品,例如百度、Inspelect等, 这些统计产品也都是通过创建script标签来动态插入到页面中的。另外需要注意的是,google提供的gtm
代码是在google服务器上的,为了让获取该代码的速度更快,我们可以在自己的服务器上执行crontab
定时任务,每分钟获取一次,然后gtm
代码直接从自己服务器上获取。
css文件全部放到head
里,script文件全部放到body
的最底部。
原因:
把样式表移到head
里允许页面逐步渲染。
浏览器负责渲染的GUI渲染线程与JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起(相当于被冻结了),GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。
参考资料:从浏览器多进程到JS单线程,JS运行机制最全面的一次梳理
举个例子:
var ele = document.getElementById('myp'); ele.style.borderLeft = '1px'; ele.style.borderRight = '2px'; ele.style.padding = '5px';
三个样式属性被改变,每一个都会影响元素的几何结构,虽然大部分现代浏览器都做了优化,只会引起一次重排,但是像上文一样,如果一个及时的属性被请求,那么就会强制刷新队列,而且这段代码四次访问DOM,一个很显然的优化策略就是把它们的操作合成一次,这样只会修改DOM一次:
var ele = document.getElementById('myp'); ele.style.cssText = 'border-left: 1px; border-right: 2px; padding: 5px;';
总结:同一个DOM的多个属性改变可以写在一起(减少DOM访问,同时把强制渲染队列刷新的风险降为0)
fragment是个轻量级的document对象,它的设计初衷就是为了完成更新和移动节点这样的任务。fragment的一个便利的语法特性是当你附加一个片断到节点时,实际上被添加的是该片断的子节点,而不是片断本身。只触发了一次重排,而且只访问了一次实时的DOM。
例如:
var fragment = document.createDocumentFragment(); var li = document.createElement('li'); li.innerHTML = 'apple'; fragment.appendChild(li); var li = document.createElement('li'); li.innerHTML = 'watermelon'; fragment.appendChild(li); document.getElementById('fruit').appendChild(fragment);
触发大量回调函数的事件,例如拖拽时的mousemove
事件,window对象的resize
、scroll
事件,文字输入、自动完成的keyup
事件等,需要合理使用函数防抖和函数节流机制。具体可以参考我的另外一篇文章函数防抖和函数节流
CSS选择器的解析式其实是从右到左的,例如:
#p1 a { color: red }
如上面的选择器,浏览器必须遍历查找所有的a元素,再去找ID为p1的元素,这样查找的方式显然很低效。
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
以上がページ最適化方法のまとめの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。