かめ。ブログ

フロントエンドエンジニアが「Web」「Youtube」「3D」「お金」「お買い物情報」など、興味があることについて深堀っていくブログです。

【LightHouse Performance 100点を目指した】scriptをユーザー操作があってから遅れて読み込むことでスピード改善

2021年10月11日

2021年12月30日

Google AdsenseやTwitter Widgetで外部のjsを読み込んだらLightHouseのPerformanceが20点ぐらいまで下がってしまったので対策しました。


あと少し..!

考え方

ユーザーがスクロール、マウス操作を行った際に、scriptタグを生成して後からjsを実行するようにしました。

コード

lazyLoad.ts

export const lazyLoad = (src: string) => {
  let isLazyLoad = false

  const createScript = () => {
    const ad = document.createElement('script')
    ad.type = 'text/javascript'
    ad.async = true
    ad.src = src
    const sc = document.querySelector('script')
    sc?.parentNode?.insertBefore(ad, sc)
  }

  const onLazyLoad = () => {
    if (isLazyLoad === false) {
      isLazyLoad = true;
      window.removeEventListener('scroll', onLazyLoad)
      window.removeEventListener('mousemove', onLazyLoad)
      window.removeEventListener('mousedown', onLazyLoad)
      window.removeEventListener('touchstart', onLazyLoad)

      createScript()
    }
  }

  window.addEventListener('scroll', onLazyLoad)
  window.addEventListener('mousemove', onLazyLoad)
  window.addEventListener('mousedown', onLazyLoad)
  window.addEventListener('touchstart', onLazyLoad)

  if (document.documentElement.scrollTop != 0 || document.body.scrollTop != 0) {
    onLazyLoad()
  }
}

Nextで使う場合(layout.tsx)

import Header from '~/components/common/Header'
import Footer from '~/components/common/Footer'
import { useEffect } from 'react'
import { lazyLoad } from '~/utils/lazyLoad'

const Layout: React.FC<Footer> = props => {
  useEffect(() => {
    lazyLoad('https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-************')
  }, [])
  return (
    <>
      <Header />
      {props.children}
      <Footer />
    </>
  )
}
export default Layout

useEffectをつかて初回にlazyLoad実行するようにしています。

コードの解説

引数にsrcを渡すとそのurlが遅延ロードされる

export const lazyLoad = (src: string) => {

スクリプトの作成

scriptタグを取得して、その一つ上(headタグ)のタグ内の最初にscriptタグを生成する。

const createScript = () => {
  const ad = document.createElement('script')
  ad.type = 'text/javascript'
  ad.async = true
  ad.src = src
  const sc = document.querySelector('script')
  sc?.parentNode?.insertBefore(ad, sc)
}

isLazyLoadがfalseの場合のみ1回だけcreateScriptを実行する

さらにそれぞれのイベントを削除します。

const onLazyLoad = () => {
  if (isLazyLoad === false) {
    isLazyLoad = true
    window.removeEventListener('scroll', onLazyLoad)
    window.removeEventListener('mousemove', onLazyLoad)
    window.removeEventListener('mousedown', onLazyLoad)
    window.removeEventListener('touchstart', onLazyLoad)

    createScript()
  }
}

onLazyLoadが実行されるイベント登録

window.addEventListener('scroll', onLazyLoad)
window.addEventListener('mousemove', onLazyLoad)
window.addEventListener('mousedown', onLazyLoad)
window.addEventListener('touchstart', onLazyLoad)

スクロール量が0じゃない場合はonLazyLoadを実行する

if (document.documentElement.scrollTop != 0 || document.body.scrollTop != 0) {
  onLazyLoad()
}

参考サイト

遅延読み込みでGoogle AdSenseを貼っていてもPageSpeed Insightsの点数を上げる : トイレのうず/ブログ

まとめ

パフォーマンス面はサイトを作る上で気をつけないといけないポイントなので
日々気をつけつつ、改善していきたいですね。
参考サイトに記載されていたものを自分なりに直したり、Typescriptに書き換えたりさせていただいておりますm

おすすめの本

Javascriptを勉強する際に読んでおくと良いなと思った本たちです。
特にリーダブルコードは綺麗なコードを書く考え方が身に付きます。いまでもその考え方が根付いています。

よくみられてる記事