当記事では、CSS・JSファイルを遅延読みして表示速度を向上させる方法について注意点も含めて記します。
ユーザーがスクロールしたタイミングで遅延読み込み対象のファイルを読み込むという方法を採ります。
遅延読み込みのメリット
この記事を訪れていた方には説明の必要はないかもしれませんが、CSS・JSファイルを遅延読み込みするメリットについて一応述べさせていただくと、「ページの表示速度の劇的な向上が見込める」という事に尽きるかと思われます。
初期表示に必要のないスタイルやスクリプトの読み込みを遅らせる事でページの表示速度が向上します。遅らせるスタイルやスクリプト処理が重たいほど、劇的な表示速度向上が見込めます。
遅延読み込み対象のファイルは初期表示時には一切読み込まず、ユーザーがスクロールを行ったときに読み込むという方法を採ります。
遅延読み込みのコード(初級編)
動的にCSS・JSファイルを読み込む関数
まずは動的にCSS・JSファイルを読み込む関数を用意します。
引数でファイルのURLを受け取り、それぞれlinkタグ・scriptタグを生成しbodyに追加するというものです。
ここではファイル名をload-file.jsとしています。
function loadCss(url) {
const link = document.createElement('link')
link.rel='stylesheet'
link.href = url
document.body.appendChild(link)
}
function loadJs(url) {
const script = document.createElement('script')
script.src = url
document.body.appendChild(script)
}
遅延読み込みを実行するコード
ユーザーがスクロールを行ったタイミングで先ほど定義したloadCss関数とloadJs関数を呼び出して、CSS・JSファイルの遅延読み込みを行っています。
onceオプションを使用して一度だけイベントを実行するようにしています。
<script src="./js/load-file.js"></script>
<script>
window.addEventListener('scroll', function() {
loadCss('./css/style.css')
loadCss('./css/common.css')
loadJs('./js/function.js')
loadJs('./js/common.js')
},{once:true})
</script>
CSS・JSファイルの遅延読み込みにおける注意点2つ
注意点1:ファーストビューにかかわるCSSやJSを遅延読み込みさせてはいけない
上記で解説した方法は『スクロールされたタイミングでCSS・JSファイルを読み込む』というものなので、ファーストビューにかかわるCSSやJSを遅延読み込みさせてしまうと初期表示時の画面が崩れてしまったりします。
遅延読み込みするファイルはファーストビューに関わらないものだけを選定してください。
注意点2:遅延読み込みされる側のJSのイベントハンドラに注意
例えば、遅延読み込みされるJavascriptに下記のようなイベントがある場合、そのイベントの中身は実行されません。
DOMContentLoadedイベントはDOMが構築が完了したタイミングで実行されるが、ファイルが遅延読み込みされた時にはDOMの構築は完了してしまっているからです。
document.addEventListener('DOMContentLoaded', function() {
})
遅延読み込みで動かないコードは自分の認識では以下の4つです。
イベントの種類としてはDOMContentLoadedイベントとloadイベントの二つに集約されます。
document.addEventListener('DOMContentLoaded', function(){ })
window.addEventListener('load', function(){ })
window.onload = function(){ }
$(window).on('load', function(){ })
ただし、これは以下のように遅延読み込み実行時にdispatchEventで強制発火を行う事によって解決することができます。
window.addEventListener('scroll', function() {
loadCss('./css/style.css')
loadCss('./css/common.css')
loadJs('./js/function.js')
loadJs('./js/common.js')
/* ↓ 追記 ↓ */
setTimeout(function(){
window.dispatchEvent(new Event('load'))
document.dispatchEvent(new Event('DOMContentLoaded'))
},500)
},{once:true})
初級編コードの全体と上級編について
初級編のコードは以下で全てです。
window.addEventListener('scroll', function() {
loadCss('./css/style.css')
loadCss('./css/common.css')
loadJs('./js/function.js')
loadJs('./js/common.js')
setTimeout(function(){
window.dispatchEvent(new Event('load'))
document.dispatchEvent(new Event('DOMContentLoaded'))
},500)
},{once:true})
function loadCss(url) {
const link = document.createElement('link')
link.rel='stylesheet'
link.href = url
document.body.appendChild(link)
}
function loadJs(url) {
const script = document.createElement('script')
script.src = url
document.body.appendChild(script)
}
ここまでで、注意点も含めたCSS・JS遅延読み込み方法の解説が終わりました。
ここから先は上級編ですが、ユーザに提供する機能に変化はなく『遅延読み込みを行う事で表示速度を向上する』以上のことはできません。
ここから先はあくまでソースコードを書く上で作りやすいように初級編のコードをリファクタリングするだけです。
以下二つの事を行います。
・遅延読み込みの処理も関数側に移し再利用性を高める
・遅延読み込みするファイルのURLを設定ファイルで管理できるようにする
興味ある方のみお進みください。
遅延読み込みのコード(上級編)
以下のような関数群を用意します。
引数でCSS・JSファイルのURL配列と強制発火イベント配列をオブジェクト形式で受け取り、ユーザーがスクロールを行ったときに遅延読み込みとイベントの強制発火を行ってくれる関数です。
ここではファイル名をlazy-file.jsとしています。
function lazyFile({css=[], js=[], events=[]}) {
window.addEventListener('scroll', () => {
css.map((url) => loadCss(url))
js.map((url) => loadJs(url))
fireEvents(events)
},{once:true})
}
function fireEvents(events) {
setTimeout(() => {
events.map((event) => {
window.dispatchEvent(new Event(event))
document.dispatchEvent(new Event(event))
})
},500)
}
function loadCss(url) {
const link = document.createElement('link')
link.rel = 'stylesheet'
link.href = url
document.body.appendChild(link)
}
function loadJs(url) {
const script = document.createElement('script')
script.src = url
document.body.appendChild(script)
}
先ほど用意したlazyFile関数を使用して、遅延読み込みを行えます。
<script src="./js/lazy-file.js"></script>
<script>
lazyFile({
css: [
'./css/style.css',
'./css/common.css',
],
js: [
'./js/function.js',
'./js/common.js',
],
events: [
'load',
'DOMContentLoaded',
]
})
</script>
ファイルURLと強制発火したいイベントを配列形式にしたため、この部分を設定値として外部ファイルに持たせる事もできるようになりました。
例えば、下記のような設定ファイルを用意して。。
const Const = {
LAZY_CSS: [
'./css/style.css',
'./css/common.css',
],
LAZY_JS: [
'./js/function.js',
'./js/common.js',
],
LAZY_EVENTS: [
'load',
'DOMContentLoaded',
]
}
以下のように遅延読み込みを行えます。
手続きのコードがとてもスッキリしました。
<script src="./js/lazy-file.js"></script>
<script src="./js/const.js"></script>
<script>
lazyFile({
css: Const.LAZY_CSS,
js: Const.LAZY_JS,
events: Const.LAZY_EVENTS
})
</script>
以上、CSS・JSファイルを遅延読みする方法でした!