1. ネットワークの最適化
YSlow には 23 のルールがあります。こちらを参照してください。これら数十のルールの主な目的は、不必要なネットワーク遅延を排除または削減し、送信する必要があるデータを最小限に圧縮することです。
1) CSS、JavaScript、画像、静的リソースの CDN キャッシュをマージおよび圧縮します
ビルド ツール Gulp を使用すると、開発中にマージと圧縮を一緒に行うことができます。
マージ圧縮の理由は次のとおりです: HTTP 1.x では、接続上の複数の応答データがインターリーブ方式 (多重化) で到着することが許可されていないため、次の応答の送信を開始する前に 1 つの応答を完全に返す必要があります。
つまり、クライアントが 2 つのリクエストを同時に送信し、CSS リソースが先に準備できている場合でも、サーバーは最初に HTML レスポンスを送信し、次に CSS を配信します。
CDN を使用する目的は、ユーザーがアクセスするときに最も近いリソースを使用できるようにし、往復の伝送時間を短縮することです。
HTTP2.0 は、HTTP1.x の多くの側面を改善します。
2) CSSは上部に配置され、JavaScriptは下部に配置されます
CSSは並行してダウンロードできますが、JavaScriptはロード後にブロックを引き起こします。
ただし、常に例外があります。スタイル シートの後にインライン スクリプトを配置すると、リソースのダウンロードが大幅に遅延します (その結果、スタイル シートがダウンロードされてインライン スクリプトが実行されるまで、後続のリソースのダウンロードを開始できません)。 )。
これは、インライン スクリプトには、document.getElementsByClassName() など、スタイルシート内のスタイルに依存するコードが含まれる可能性があるためです。
<head> <link rel="stylesheet" href="css/all-normal.css" type="text/css" /> </head> <body> <div id="content"></div> <script> var content = ''; for(i=1; i<1000000; i++) content += '写入页面'; document.getElementById('content').innerHTML = content; </script> <img src="images/ui.png" / alt="JavaScript の最適化とフロントエンド開発のヒント" > </body>
以下の Chrome ツールで確認してください:
3) DNS 解決を最適化し、リダイレクトを削減します
「女神選択イベント」を実行する場合、WeChat でユーザーの openID にアクセスする必要があります。WeChat 基本ユーザーの取得情報を得るにはいくつかの手順が必要です:
まずコードを取得し、次にコードを通じて openid を取得し、最後に静的ページにジャンプします。
同社は事業を複数のグループに分割しているため、3 つの短い手順を実行するには実際には 3 つのグループの協力が必要であり、複数のドメイン名をリダイレクトする必要があります。
下の図は最適化前のウォーターフォール チャートですが、静的ページにアクセスするのに 10 秒以上かかる場合があり、これはまったく許容できません。下の図では、4 つのドメイン名がジャンプされます。
その後、インデックスドメイン名にジャンプする代わりに、WeChatに直接ジャンプしてドメイン名を操作し、1つのドメイン名のジャンプを減らし、各グループのコードを最適化しましたが、その効果はまだ理想的ではありません。ほんの数秒速いだけです。
最後に、WeChat のサーバーと対話するときに DNS 解決に時間がかかりすぎることがわかりました。最後の手段として、サーバーのホストにレコードを追加し、IP を介してそれを直接指定します。
下の写真は最終的な最適化結果です。瞬時に開くことはできませんが、少なくとも許容範囲内です:
2. JavaScript の最適化
1) 画像のプリロード
「Qiu Mingshan アクティビティ」を実行するとき、画像のプリロードを使用します。このキャンペーンには 120 枚以上の画像があります。
プロセスは非常に簡単で、質問に答え、結果についてコメントし、共有するだけです。
一度にたくさんの写真を読み込むのは愚かな考えに違いないので、最終的に、ページが読み込まれるときに最初に一般的な写真をいくつか読み込むことにしました。
質問に答えるとき、ページにアクセスしたときに画像が直接表示されないように、現在のページに次のページの画像が事前に読み込まれます。画像も適切にマージされています。
テスト用に gtmetrix.com に Web サイトのアドレスを入力します。以下は最終的なウォーターフォール チャートです。ページができるだけ早くユーザーに表示されるように、画像が他の静的リソースの背後にあることがわかります。
优化还远远没有结束,在Chrome中分别模拟了good 2G、good 3G以及4G后,有结果的情况并不理想。
good 2G:
good 3G:
4G:
还有很大的优化空间可以做,关于这个预加载的原理,可以参考《图片预加载与懒加载》
2)减少分支
在写业务逻辑的时候,经常会用到if else,switch之类的逻辑判断,如果每次都做这么多判断,很容易影响性能。
所以可以通过多种方式来避免过多的判断。
1. 惰性模式
这是在看《JavaScript设计模式》的时候看到的。
减少每次代码执行时的重复性分支判断,通过对对象重定义来屏蔽原对象中的分支判断。
惰性模式分为两种:第一种文件加载后立即执行对象方法来重定义,第二种是当第一次使用方法对象时来重定义。
公司有个页面要提供给第三方APP,但是最终发现第三方APP不能使用localStorage缓存,最终只得做兼容的方式。
但为了避免每次引用方法的时候都做判断,就使用加载后立即重定义:
var getFn = function() { if (sore.enabled) return sore.get; return cookie.get; }(); var setFn = function() { if (sore.enabled) return sore.set; return cookie.set; }();
2. 建立映射关系
页面中经常需要弹出框提示,后面就自己做了一个,但弹出框会有很多款式。
如果用简单工厂模式创建的话,免不了switch分支判断,后面就直接用赋不同的key,还能缓存起来,只初始化一次。
/** * 弹出框单例模式 */ var factories = {}; var DialogFactory = function(type, options) { if (factories[type]) return factories[type]; return factories[type] = new iDialog(options); }; /** * 提示框 */ var Alert = function(content, options) { var d = DialogFactory('alert', options); //其他逻辑省略 return d; }; /** * 确认框 */ var Confirm = function(content, options) { var d = DialogFactory('confirm', options); //其他逻辑省略 return d; };
3)第三方代码异步加载
第三方代码,例如百度统计、微信SDK等,这些完全可以在将业务资源加载完后再添加。
/** * 百度统计设置 */ util.baidu = function(key) { global._hmt = global._hmt || []; (function() { var hm = document.createElement("script"); hm.src = "//hm.baidu.com/hm.js?" + key; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); };
4)cookie与localStorage缓存
有了缓存后,就能减少与服务器的通信,在本地操作。
公司有个查违章的业务,在本地添加好车辆后,再次进入页面的时候就需要能直接选择事先添加好的车辆。
最理想的方式就是添加好后,就在本地缓存起来,下次进入直接调取缓存。
我会优先使用localStorage,下面的表格就是对比:
cookie
localStorage
数据生命周期
可设置失效时间除非被清除,否则永久保存
数据大
大约4KB 大约5M
与服务器通信
每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题
不参与和服务器的通信
本地存储,之前的历史大概如下图所示:
localStorage在浏览器兼容方面,IE8居然也支持了。
5)事件委托
使用事件委托技术能让你避免对特定的每个节点添加事件监听器。
事件监听器是被添加到它们的父元素上,通过事件冒泡,触发执行。
在开发的时候,经常会出现动态添加元素的情况。
如果每次都重新绑定一次事件,那会有很多多余操作,而绑定在此元素的父级,就只需绑定一次即可。
document.getElementById('ul').onclick = function(e) { var e = e || window.event, tar = e.target || e.srcElement; if (tar.nodeName.toLowerCase() == 'li') { tar.style.background = 'black'; } }
6)节流与去抖动
节流(throttle):预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期。
例如mousemove 事件、window对象的resize和scroll事件。
去抖动(debounce):当调用动作n毫秒后,才会执行该动作,若在这n毫秒内又调用此动作则将重新计算执行时间。
例如文本输入keydown 事件,keyup 事件,做autocomplete等。
节流与去抖动最大的不同的地方就是在计算最后执行时间的方式上。著名的开源工具库underscore中有内置了两个方法。
在做公司内部的一个系统的时候,需要方希望在左右滚动表格的时候,能将第一列固定在最左边,方便查看。
为了让操作能更流畅,我再这里用了节流,有些浏览器会出现卡顿,就得需要增加周期时间。
三、小技巧
1)在手机中打印变量
在移动页面的时候经常需要调试字段,又不能用console.log,每次alert的话,碰到对象就看不到内容了。
只能自己写个小方法来打印出来,JSON.stringify,通过这个方法能够方便的实现功能。
var print = function(obj, space) { space = space || 4; var html = JSON.stringify(obj, null, space); html = html.replace(/\n/g, '<br>').replace(/\s/g, ' '); var pre = document.createElement('pre'); var div = document.createElement('code'); pre.style.cssText = 'border:1px solid #000;padding:10px;background:#FFF;margin-bottom:20px;'; div.innerHTML = html; pre.appendChild(div); var body = document.querySelector('body'); body.insertBefore(pre, body.children[0]); }; print({a:1, b:'demo', c:{text:'content'}});
2)chrome插件JSON-handle
服务器返回的很多都是JSON格式的数据,通常写好后给你个接口,顺便给你几个demo参数。
在浏览器中打开后,就是一串字符串,但要给人看的话,就得格式化一下了,这个插件就是用来让人看的。
更多JavaScript の最適化とフロントエンド開発のヒント相关文章请关注PHP中文网!