はじめに
Nuxt, TypeScriptで速度とかを深く考えず実装を進めていったら、
ページ表示速度が著しく遅かったので色々と勉強したメモ。
前提
Nuxt 2.11.0
TypeScript導入済み
Nuxt generateして運用
速度改善
どこが遅いのか、とかを色々しらべると
- 画像が多い画面なので画像の読み込みに時間がかかる。
- node moduleが重い
- componentsのimportが無駄なものがあったり、importの仕方がまずい
とかが原因と思われました。
ちなみに改善する前のGoogle のpagespeed insights で測ったら真っ赤っかでした。
画像の読み込み改善
画像の遅延読み込みの実装
vue-lazyloadを使います。
yarn add vue-lazyload
nuxtで使えるようにしていきます。
import Vue from 'vue'
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload, {
preLoad: 1.1,
attempt: 1,
observer: true,
observerOptions: {
rootMargin: '0px',
threshold: 0.1
}
})
オプションは、vue-lazyloadのドキュメントを読んでください。たぶん、このまま使って大丈夫です。
pluginをnuxt.config.tsで読み込みます。
plugins: [
{ src: '~plugins/vue-lazyload', ssr: false }
]
vue用に作られたmodulesをnuxtで使う場合pluginを書いて、configで読み込んだらだいたい使える気がします。
これでlazyloadの準備ができました。
実際componentsなどで使う場合
<template lang="pug">
div
img(v-lazy='hoge.jpg', alt='')
</template>
とう感じに、src
の代わりに v-lazy
を使ってください。
これでlazyloadが実装できました。
これだけで画像関連は十分ですが、せっかくなのでwebpも使える様にします。
Webpと通常の画像の出し分け
lazyloadの実装に使ったvue-lazyloadを使ったらいい感じにwebpの出し分けも実装できました。
pluginを書き直しましょう。
import Vue from 'vue'
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload, {
preLoad: 1.1,
attempt: 1,
observer: true,
observerOptions: {
rootMargin: '0px',
threshold: 0.1
},
filter: {
webp(listener: any, options: any) {
if (!options.supportWebp) return
listener.src = 'hoge.webp'
}
}
})
filter
を追加します。
ここで、ブラウザがwebpに対応していればwebpのパスを返す処理を追加しています。
もしくはパスの最後にパラメータを追加すると、変換して返してくれるような機能があればこんな感じで。
これはcontentfulです。
filter: {
webp(listener: any, options: any) {
if (!options.supportWebp) return
listener.src += '?fm=webp'
}
}
以上で、画像はlazyloadとwebpが実装できました。
ここまでやったら、多分だいたいOKなんじゃないかと思いますが、次へ。
componentsのdynamic import
Nuxt,vueでcomponentをimportする場合
import fuga from '~/components/fuga.vue'
だいたい、こうしますが。
const fuga = () => import('~/components/fuga.vue')
こうすると、dynamic importになってbundleサイズが軽くなって速度が改善されます。
これをしてエラーが出ないcomponentならこうやったほうがいいですが、
たまにエラーが出るので、その場合は臨機応変に、従来通りのimportするかエラーを直すか。
webpackのbundleの設定
nuxt でwebpackのbundleを分割するように設定します。
const nuxtConfig = {
splitChunks: {
layouts: true,
pages: true,
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
chunks: 'initial'
}
}
spliChunksの部分の設定をしてやると、よかったです。
おわり。
おわり
おわり
参考
https://webpack.js.org/guides/lazy-loading/
https://crieit.net/posts/Nuxt-Vue-dynamic-import-sed