46
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

前回の記事はNuxt.jsでVue.jsのSSRのWebアプリケーションの制作の経験について紹介しました。そのWebアプリケーションをリリースしたあと、まずしなければならなかったことはサイトのパフォーマンスの向上でした。
今回はその時に学んだことや経験について紹介したいと思います。

node_modules.png

TL;DR

パフォーマンスが重要なのはなぜか?

まず、パフォーマンスの高いサイトはユーザーの体験がよくて、 パフォーマンスの低いサイトよりユーザーを引きつけられるでしょうか。

Googleの調査結果によると、ページロード時間が10秒削減したら、サイトに戻ってくるユーザー率が**123%**増加します。

mobile-page-speed-new-industry-benchmarks-01-21.png

実際の事例: Pinterest では、ユーザーが体感している待ち時間を**40%**削減した結果、検索エンジンのトラフィックとサインアップ数が15%増加しました。

また、SEOが必要なウェブサイトなら、もっと重要になりますね。
Googleはウェブサイトを評価するために、パフォーマンス(Page speed)は重要な評価点の一つのだからです。

チェック

まず、ウェブサイトの問題や改善方法をチェックします。

チェックするツールがたくさんありますが、
以下はGoogleの公式のサイトやツールであり、結構有名でよく使われています。

  • PageSpeed Insight
  • Lighthouse(今Chromeのデベロッパーツールのauditsパネルでもチェックできるようになりました。)

上記のツールでチェックしたら、色々なレポートと、問題点と、そのページを改善する最適化案を出してくれます。

パフォーマンス向上

サイトをチェックした後、レポートや改善案を参考して、サイトのパフォーマンスの改善を実施します。

画像の遅延読み込み

実はアプリケーションの開発の時に、既に画像の遅延読み込みを実装して、使いました。
ですが、Lighthouseツールを使ったらサイトにある画像の中にどれが遅延読み込む必要なのか以下のようなオフスクリーンイメージ監査という形で指摘してくれます。

offscreen-audit-1x.png

Vue.jsで画像の遅延読み込みを導入するには外部のVue.jsのプラグインがたくさんあり、簡単で導入できます。例えば: Vue-Lazyload

ただし、パフォーマンスの優先でもっと軽量な方法を使用したかったので、Lozad.jsという軽量なライブラリー(~1kb)を使って画像の遅延読み込み用のコンポーネントを作りました。

詳しく画像/動画の遅延読み込みについて知りたい方はこちらのGoogleの公式なガイドに参考してください。

外部のjsライブラリーの最適化

この改善の目的はアプリケーションのjsファイルのサイズを小さくすることです。

まず、使っているbundles(モジュール)のコンテンツやサイズを確認し、視覚化するために、Nuxt.jsは既にwebpack-bundle-analyzerという便利なライブラリーを入れ、使っています。

nuxt.config.jsファイルで設定を以下のように変更して、yarn nuxt build --analyzeコマンドを実行すると確認できます。

nuxt.config.js
export default {
  build: {
    analyze: true
  }
}

結果は以下のような形です。
スクリーンショット 2019-12-20 12.22.17.png

これをちゃんとチェックしたら、とりあえずどれが重いライブラリーなのかと、どのようにそのライブラリーの最適化できそうなのかわかりますね。

僕の場合、2つライブラリーの最適化をやっていました。

1.moment.js
改善前
スクリーンショット 2019-12-20 12.21.21.png

momentはi18nのため全部のlocalesをロードしていますが、日本語(ja)しか使っていないので、日本語だけロードすれば良さそうですね。

スクリーンショット 2019-12-20 12.32.07.png

moment-timezone用データファイルは重いですね。i18nのように日本の時間帯しか使っていないですので、日本の時間帯だけにすれば良さそうですね。

改善方法
上記の改修案を実現するためには、ContextReplacementPluginNormalModuleReplacementPluginというwebpackの2つプラグインを使いました。

詳しくは以下のようです。

nuxt.config.js
const webpack = require('webpack')
const path = require('path')
export default {
  build: {
    plugins: [
      new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /ja/),
      new webpack.NormalModuleReplacementPlugin(
        /moment-timezone[/\\]data[/\\]packed[/\\]latest.json$/,
        path.join(__dirname, '/config/data/momentTz.json')
      )
    ]
  }
}
momentTz.json
{
  "version": "2018g",
	"zones": [
		"Asia/Tokyo|LMT JST JDT|-9i.X -90 -a0|0121212121|-3jE90 2qSo0 Rc0 1lc0 14o0 1zc0 Oo0 1zc0 Oo0|38e6"
  ],
  "links": [
		"Asia/Tokyo|Japan"
  ]
}

momentTz.jsonmoment-timezoneのjsonデータファイルから日本時間帯用の設定だけを抜き出して、カスタマイズのファイルです。

改善後

スクリーンショット 2019-12-20 12.51.49.png スクリーンショット 2019-12-20 12.52.25.png

大分減らしましたね :rocket:

2.font-awesome
改善前
アプリケーションにfont-awesomeを導入するためには、nuxt-fontawesomeというパーケージとデフォルト設定で使いました。

nuxt.config.js
export default {
  modules: [
    ['nuxt-fontawesome', {
      imports: [
        {
          set: '@fortawesome/free-solid-svg-icons',
          icons: ['fas']
        },
        {
          set: '@fortawesome/free-regular-svg-icons',
          icons: ['far']
        }
      ]
    }]
  ]
}

デフォルトは全部solidregularのfontセットをロードしてしまいます。
スクリーンショット 2019-12-20 13.50.44.png

改善方法
使用しているフォントを定義することで、そのフォントだけロードするようにします。

nuxt.config.js
export default {
  modules: [
    ['nuxt-fontawesome', {
      imports: [
        {
          set: '@fortawesome/free-solid-svg-icons',
          icons: ['faAngleRight', 'faAngleLeft'] // 使用しているフォントの定義
        },
        {
          set: '@fortawesome/free-regular-svg-icons',
          icons: ['faAdjust', 'faArchive'] // 使用しているフォントの定義
        }
      ]
    }]
  ]
}

nuxt-fontawesomeのコードを見てみたら、それはtree-shaking技術のアイデアです。

例:

  • BAD
// 全部の関数インポート
import arrayUtils from "array-utils";
  • GOOD
// 必要な関数だけインポート
import { unique, implode, explode } from "array-utils";

改善後
スクリーンショット 2019-12-20 13.59.00.png

上記の2つの改善で最適化した後、vendors.app.jsファイルが**(Stat size: 2.15 MiB)から(Stat size: 249 KiB)**に削減しました。:tada::tada::tada:

終わりに

上記に紹介した改善方法の以外に、Dynamic importでVueコンポーネントの遅延読み込みの対策などもやってみましたが、あまり効果が出てなかったので、今回それを紹介しません。

ウェブサイトのパフォーマンス向上は困難なことで、色々改善をやったけど、ちょっと効果が出ることがよくありますね。:cold_sweat:

ですから、他の良い改善方法がある方はぜび共有お願いいたします。

参考

46
29
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
46
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?