GAミント至上主義

Web Monomaniacal Developer.

このブログについて(先頭固定)

【お約束】 投稿内容は個人の見解であり、所属する(していた)組織の公式見解ではありません。

名前:uyamazak(昔いた会社で上司が開発用Linuxサーバーのユーザー名に「yuyamazaki」が長いので勝手に作ってくれた。読み方わからないけどウヤマザク)

高校あたりからWEBサイトをやったり趣味の延長でWEB系を仕事にした感じの人間。

2020年1月から株式会社シニアジョブにジョイン。
まだ開発者の社員は2人、これからの会社なのでインフラからきれいな設計をしたい

アズールレーン@竹敷でモバイルのUI、UX研究中(初嫁ジャベリン)

GitHub: https://github.com/uyamazak/

これまでの主なプロジェクト

続きを読む

ブラウザだけでVtuber用動画をつくるツールをKonvaとVueでつくってる

動画サンプル

https://youtu.be/3t2l1OH00lU
youtu.be
声はまだない。

作ってるやつ(スマホ非対応)

uyamazak.github.io

使い方

STARTしていろんな操作して録画、STOPすると出てくるDOWNLOADボタンで落とせます。UIまじで並べただけ。

経緯

架空のVtuberを題材とした漫画を描くというのでツッコんでるうちにこうなった。声はまだない。


(断じてLive2Dはできない)

最初はJavaScriptで画像を指定した座標と時間で表示する紙芝居作るかぁと思いました。

でも、どうやらCanvasだと動画まで生成できることを知った。すごい。

MediaRecorder APIでCanvasを録画してみる | blog.kwst.site

画像の座標とかはVuetifyのSlidersでやるかぁと思いました。
vuetifyjs.com

リリースされたVue3使いたかったけどVuetifyや周辺がまだまだっぽいので2を使う。

うーんでもCanvasの操作は面倒だ、と思っていたらKonvaというライブラリがあり、さらにVue用の公式ライブラリもあるらしい。

konvajs.org

konvajs.org

使ってる技術

Canvas周りはKonva、データ周りはVue、UIはVuetify、録画にブラウザの」MediaRecorder API
ブラウザだけでどこまでVtuber動画作成ツールを作れるかの技術検証でもある。

詳細はソース
GitHub - uyamazak/marika_kitada: 架空のVtuber、北田まりかの動画をつくるためのWEBアプリ

公開先もGitHub Pages。サーバーサイド不要のクソアプリに最適でした。

ハマりどころ

録画できるcanvasは一つだけ

HTMLを見る感じKonvaはレイヤーごとにcanvasを作るようなので、v-layerは一つだけにしました。
それぞれ画像にして一つのcanvasにすることもできそうだけど録画は厳しそうだし、やってみると1レイヤーでも大丈夫そう。

vue-konvaだと生成されるcanvasにrefやidを貼れない

普通にKonvaを使うと自分で書いたcanvasにidを振って使うけど、vue-konvaだと自動で生成され手出しできなかった。
なんかいい方法ありそうだけど、上述の理由からページ上に一つしかcanvasはないため一旦下記で取得。

this.stream = document.getElementsByTagName('canvas')[0].captureStream()

動画はwebmでしか書き出せない(MacやChromeOSのChromeの場合)

なのでTwitterにはそのままアップできない。変換ツールはいろいろあるので問題なさそう。
Windowsだとできるのかな?)

filters()するとPCは大丈夫だけどスマホだと画像が消える

原因は未調査。重い処理だからかな?

フィルターデフォルトでいろいろあって遊べます。
Konva Namespace: Filters


Noise
f:id:uyamazak:20200928181321p:plain

Invert
f:id:uyamazak:20200928181217p:plain

Pixelate
f:id:uyamazak:20200928182935p:plain

白目の後ろが透けないようにおいた白い資格にfilter適応するの忘れてるのに気づいた。

これから

声まじでどうするの。
できたらブラウザでいっしょに動画に収めたい。
ブラウザでできることだけ、を貫く。
背景の株価とかも変動させたいなぁ。

北田まりかに興味がある人は
八神秋一@八木崎銀座 (@yagami_shuichi) | Twitter

北田まりか (@marika_kitada) | Twitter


技術的に興味ある人はGitHubTwitterで私になんかください。

このブログについて(先頭固定)

【お約束】 投稿内容は個人の見解であり、所属する(していた)組織の公式見解ではありません。

名前:uyamazak(昔いた会社で上司が開発用Linuxサーバーのユーザー名に「yuyamazaki」が長いので勝手に作ってくれた。読み方わからないけどウヤマザク)

高校あたりからWEBサイトをやったり趣味の延長でWEB系を仕事にした感じの人間。

2020年1月から株式会社シニアジョブにジョイン。
まだ開発者の社員は2人、これからの会社なのでインフラからきれいな設計をしたい

アズールレーン@竹敷でモバイルのUI、UX研究中(初嫁ジャベリン)

GitHub: https://github.com/uyamazak/

これまでの主なプロジェクト

続きを読む

既存の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

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