GAミント至上主義

Web Monomaniacal Developer.

既存のLaravelプロジェクトに入ってたVueまわりの環境を整備した

そもそも?

シニアジョブの求人サイトはLaravelをメインに一部でVueを使っています。

しかし、すでにVueコンポーネントの多くを書いた人はおらず、最初はLaravel mixで入れたようなので、Vue CLIやNuxtJSだといっしょに入れられるlint、フォーマットルールなども無いためファイルごとにインデントが違うなど混沌としていました。

Google Search ConsoleでCLSの警告が一部ページで出て、改善しようとソースコードをよく見たら「うわぁぁぁぁぁ」となったり、同僚の要望もあったので、これを機に根本的に整えることにしました。

ESlint, Prettierインストール

ここらへんを入れました。NuxtJSの設定をベースに使いました。

package.json

    "eslint-plugin-vue": "^7.0.0-beta.2",
    "eslint": "^7.7.0",
    "prettier": "^2.1.1",
    "eslint-config-prettier": "^6.11.0",
    "eslint-plugin-prettier": "^3.1.4"

eslintの設定

一見シンプルですが、extendsの並び順によって複数回--fixで自動フォーマットを実行するとインデントが崩れるなど問題がありました。正直よくわかってないけどこの並び順なら大丈夫だった。
変数名デフォはcamel caseですが、PHP側のリクエストパラメータに合わせてsnake caseが使われている箇所があったので無効にしました。

eslintrc.js

module.exports = {
  root: true,
  env: {
    browser: true
  },
  extends: [
    'eslint:recommended',
    'plugin:vue/recommended',
    'plugin:prettier/recommended',
    'prettier/vue',
  ],
  // add your custom rules here
  rules: {
    // 変数名をサーバー側の都合に合わせている場合があるのでOFF
    'vue/prop-name-casing': 'off',
  },
}

.prettierrc

これはNuxtJSのまんまだったような

{
  "semi": false,
  "singleQuote": true
}

lintコマンド追加

他のJSもたくさんあるので(混沌)、VueのSFCファイルのみを対象としたコマンドとしました。

{
  "scripts": {
    // 省略
    "lint-vue": "eslint path/to/components/*.vue",
    "lint-vue-fix": "eslint --fix path/to/components/*.vue"
  },

実行

開発環境はDockerで動いているので

docker-compose app exec yarn lint-vue`

で動くようになりました。
インデントやクォーテーションがばっちりそろって気持ちいいです。

あとは表示されたwarning, errorを直しまくって0にしました。

    • fixで直せないのは、ほとんどがv-forにkeyがついてないやつと、propsのデフォルト値周りでした。

JavaScript, CSSの容量削減

SEO、ユーザーメリット等考えるとむしろこっちがメインかも。
webpackでのビルド後のサイズがjsで600KiB、CSSで200KiBを超えてました・・・。
大きいなぁと思ってはいたけど見ないふりしてた。

使ってないパッケージ削除で容量削減

                         Asset       Size  Chunks                    Chunk Names
           /css/portal/app.css    210 KiB       1  [emitted]         /js/portal/app
             /js/portal/app.js    616 KiB       1  [emitted]  [big]  /js/portal/app

これまでの作業でだいたい把握したので、いらなそうなやつを削除することにしました。
まずLaravel mixがデフォルトで入れてたBootstrapやjQueryを削除。

jQueryはHTML側で普通にscriptタグでCDNのを読み込んでいるのでいらないを確信。むしろ2つ読み込んでるのでダメそう。
Bootstrapは一部モーダルで使っていることが判明したけど別のに書き換えたので大丈夫でした。

これだけでCSSはおよそ1/3、 jsも100KiB以上軽くできました。

           /css/portal/app.css   69.1 KiB       1  [emitted]         /js/portal/app  
             /js/portal/app.js    470 KiB       1  [emitted]  [big]  /js/portal/app

どんだけ無駄に読み込んでたんだ・・・。
表示を見ても問題なさそう。

これ以上の最適化は詳しい情報が必要なので、分析ツールを使うことにしました。

やっぱりこれ。
www.npmjs.com

Vue CLIやNuxtJSなら`yarn build --analyze`あたりで実行できるのでありがたいんですが、Laravelなので下記を使いました。

www.npmjs.com

f:id:uyamazak:20200831144744p:plain

jQuery、Bootstrapも消す前の結果ですがVue本体よりfontawesomeとlodashがでかいのが丸わかりです。

fontawesomeの読み込み最適化

fontawesomeは公式Vueのパッケージを使い、下記のようにドキュメントどおりに読み込んでいました。

github.com

import { faChevronCircleLeft, faChevronCircleRight, faMapMarkerAlt } from '@fortawesome/free-solid-svg-icons'

一見これで必要な3つだけ読み込んでいるように思えますが、データ量的にfree-solid-svg-iconsすべてのアイコンデータが読み込まれてしまうようです。

そのため、公式ドキュメントとは異なりますが、ソースコードをみて下記のように変更しました。
動きましたが、おすすめはできません。

import { faChevronCircleLeft } from '@fortawesome/free-solid-svg-icons/faChevronCircleLeft'
import { faChevronCircleRight } from '@fortawesome/free-solid-svg-icons/faChevronCircleRight'
import { faMapMarkerAlt } from '@fortawesome/free-solid-svg-icons/faMapMarkerAlt'

lodash

次にlodash。調べてみるとdebounceしか使ってませんでした。

同じ要領でこんなのだったのを

  const _ = require('lodash');

こうしました。

import debounce from 'lodash/debounce'

結果はこんなの。相対的にVueが一番大きくなったので納得感。この後popper.jsもBootstrapの依存だったので消せました。
f:id:uyamazak:20200831144959p:plain


最終的には

                         Asset       Size  Chunks                    Chunk Names
           /css/portal/app.css   69.2 KiB       1  [emitted]         /js/portal/app
             /js/portal/app.js    380 KiB       1  [emitted]  [big]  /js/portal/app

616 KiB → 380KiBに。1/3強減らせて、ビルド時間も早くなりました。

.editorconfig

ついでにインデントなどのルールがバラバラだったので追加しました。
PHP等他に影響させたくないので、Componentが入っているフォルダに置きました。
VSCode等ほどんどのエディタでプラグインを入れれば使えると思います。

root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

実際のパフォーマンスへの影響

PageSpeed Insightsの結果は、点数の影響は他の要因(タイミングやサーバーレスポンスとか)の方が大きく、平均すると10ぐらい良くなったかな?程度でした。
圧縮後のサイズだと100KBも減ってなさそうなのでそんなものでしょうか。でもいくつかのエラー項目が改善してました。

ユーザー環境での変化は引き続きGoogle Analytics、Search Consoleとかで追って行こうと思います。


ちなみにプルリクはクソでかかったです。
f:id:uyamazak:20200831152248p:plain

レビュー、動作確認に感謝。