beta

Vue.jsのSPAでPreFetchを使ってコンテンツを先読みして高速化する

Vue.jsで構築したのSPAで、HTMLのPreFetchを使ってコンテンツを先読みして高速表示する方法をまとめました。

公開日:2019年9月19日

Vue.jsのSPAでprefetchを使ってコンテンツを先読みして高速化する

Vue.jsで構築したのSPAで、HTMLのprefetchを使ってコンテンツを先読みして高速表示する方法をまとめました。

構成イメージ

Vue.jsで構築されたSPAサイトで、コンテンツデータはAPIから取得するものとします。

サイト構成は、

  • 一覧ページ(List.vue)
  • 記事ページ(Detail.vue)

というブログ的な構成を例に解説していきます。

一覧ページで表示している記事のデータをHTMLヘッダのPreFetchを使って一覧を見ている間に先読みすることによって、記事ページに行く頃にはすでにデータのロードが終わっているというイメージです。

実装

List.vue

一覧ページ側では、

  • 一覧データをaxiosでAPIサーバーから取得
  • 取得したら、HTMLヘッダにlink rel=‘prefetch’を追加する

という作業をします。

完成したコードは以下です。

<script>
import axios from 'axios';

export default {
  name: "List",
  data() {
    return {
      lists: {},
    }
  },
  created () {
    this.getData()
  },
  methods: {
    getData(dir){
      const url = 'https://app.example.com/list.json'

      axios.get(url)
      .then((res) => {
        this.list = res.data
        this.setPreFetch()
      })
      .catch((e) =>{
        console.log(e);
      })
    },
    setPreFetch(dir, lists){
      let head = document.getElementsByTagName('head').item(0);

      for(let i in this.lists){
        const url = 'https://app.example.com/detail/' + this.lists[i].code + '.json'
        let link = document.createElement('link');
        link.rel = 'prefetch'
        link.href = url
        link.as = 'fetch'
        link.type = 'application/json'
        head.appendChild(link);
      }
    }
  }
}
</script>

getDataでAPIから一覧データ(https://app.example.com/list.json)を取得したら、setPreFetchを使ってリンク先になる詳細ページ(https://app.example.com/detail/記事コード.json)のデータを取得するためのlink rel=“prefetch”ヘッダを、HTMLヘッダに追加します。

Chromeの開発者ツールなどの「ネットワーク」で取得しているデータを確認すると、しっかりと詳細ページのデータが取得できていることがわかります。

Detail.vue

続いて、記事ページです。

こちらは、普通にaxiosでデータを取得するだけです。

<script>
import axios from 'axios';

export default {
  data() {
    return {
      data: {},
    }
  },
  created () {
    this.code = this.$route.params.code
    this.getData(this.code)
  },
  methods: {
    getData(code){
      const url =  'https://app.example.com/detail/' + code + '.json'
      
      axios.get(url)
      .then((res) => {
        this.data = res.data
      })
      .catch((e) =>{
        console.log(e);
      })
    },
  }
}
</script>

これだと、一見、記事ページに入った時に再度APIへのリクエストを投げてデータを取得しそうですが、ブラウザの開発者ツールで確認すると、対象データの取得ステータスが

Request Method: GET
Status Code: 200  (from prefetch cache)

となっていて、キャッシュから読み込まれていることになっています。

ネットワーク一覧を見てみてると、対象データのSizeのところが、実際のデータサイズではなく「prefetch cache」となっていて、数msとかで読み込まれているはずです。こうなっていれば、prefetchに成功しています。

キャッシュはファイルベースなので注意

上記の例では、ユニークなcode + .jsonというファイル名なので問題ありませんが、URLがユニークでもファイル名が同じ場合は、キャッシュは一番最初のものしかprefetchしません。

例えば、こういう場合、

<link rel="prefetch" href="https://app.example.com/detail/1111/index.json">
<link rel="prefetch" href="https://app.example.com/detail/2222/index.json">
<link rel="prefetch" href="https://app.example.com/detail/3333/index.json">

URLは違いますが、ファイルとしては全て「index.json」になるので、1111以外はキャッシュされません。

prefetchさせたい場合は、APIから吐き出すデータのファイル名にまで気を配る必要があります。

適宜削除しないと溜まり続ける

SPAの場合、ブラウザをリロードしないでページ遷移するため、HTMLヘッダに追加したprefetchは、そのまま残り続けます。

ページ遷移の度にprefetchを追加し続けると、HTMLヘッダがとても長くなるので、適宜削除するようにすると良いでしょう。

Safariではprefetchは使えない

2019年9月現在、AppleのSafariは、macOS版、iOS版ともにprefetchに対応していません。

日本のモバイル環境で利用の多いiOS Safariが対応していないのは残念ですね。


サクッとですが、Vue.jsで構築したSPAサイトでprefetchを使ってデータの先読みをする方法でした。

なんでもprefetchすると無駄なデータ通信が発生してしまいますが、適度に使うことで、SPAアプリを超高速化できますね。

Author

Koji Kadoma
Member of codit.work

新着ノート

新着コード