2019年3月13日水曜日

最近のWebサービス開発の最適化ポイントまとめ

久々にサービス作った際に、忘れていたり、触っていなかった事によって無駄に時間が掛かった最適化ポイントをまとめてみました。
HTML/CSS/JavaScriptの最小化や圧縮、サーバの設定などは元からできるものとして、最近変化した事や私が忘れていた事、気付いた事のまとめです。 事前に知ってると3日くらい実装時間を短縮できるかも知れない。 次回作る時のためのメモ。

faviconの作り方は変わっていない

faviconの種類は肥大化し続けている。自力での対応は面倒なのでFavicon Generatorに頼ると良い。 またfaviconの編集も割と面倒である。 画像編集ソフトを山ほどインストールしたけど、一番便利だったのはPinta。 私はいつもフリー素材で作ってるので、透過PNGをそのまま編集できて、レイヤをコピペで合成できる機能だけあれば十分なんだけど、 何年経ってもPintaが一番簡単に思う。

faviconはインライン化する必要がない

画像をインライン化するとレスポンスが良くなりますが、 最近のブラウザはfaviconを遅延ロードしてくれるのでインライン化は不要です。 最近はfaviconの種類が増え過ぎて、インライン化すると端末依存の不要なものを読み込んでしまい、むしろ遅くなります。

14KB/98KBを意識する

4Gネットワークでは50~100ミリ秒のラウンドトリップ時間が発生する。 1パケットは14KBに制限されているので、1ファイルはなるべく14KB以内に収まるようにする。 またスクロールせずに見れるATFコンテンツを98KB未満にすれば3回のラウンドトリップでページを表示できる。 PageSpeed Insightsの指針に従って最適化しましょう。

<link rel="preload"> ができていた

linkタグにCSSのレンダリングをブロックしないための属性ができていた。 ファーストビュー部分をインライン化しておいて、残りをpreloadで読み込めば、高速化が簡単にできるようになった。 現時点では対応していないブラウザが多めなので、loadCSSを併用する。
これも楽にはなったけど完璧ではないです。 CSSをpreloadでロードした後にdeferしたscriptを実行するためには、今のところライブラリが必要です。 loadCSSでは以下のように実装すると、#loadcssタグの前にCSSを読み込んだ後にスクリプトを実行してくれる。
<script id="loadcss">
  loadCSS("path/to/mystylesheet.css", document.getElementById("loadcss"));
  :  // 何らかの処理
</script>
preloadよりは、後述するファーストビューのインライン化を先にやるべき。

ファーストビューのインライン化ツールができていた

ファーストビューのインライン化はUnCSS, Criticalの2つが有名みたいです。 説明は少し長くなるのでこちらを参考ください。 ファーストビューのインライン化は起動時間短縮にかなり効果があって、今回のサービスでも100msくらい早くなりました。

PageSpeed Optimizationモジュールができていた

h2oでサーバの設定が終わってから気付いたので、これも今回は使っていない。 これを使えば面倒臭いインライン化回りを自動化できて開発が楽になる気がします。 今回はpreload回りのコードをビルドツールに組み込んでしまったのでセーフという事にしておいた。 他にもGoogleがいくつか新しい最適化ツールを推奨し始めた

headタグに書ける事が増えた

Twitter Cardとか構造化マークアップとか出たらしい。 構造化マークアップでパンくずリストを作れるのは割と便利かも知れない。 でも今回は何も使ってない。 明らかに参考になって今後も使えそうなページだけ載せておくと以下。 Googlebotの機能を見るに、実はほとんど書かなくて良いのではないかという気がしている。

iOS WebKit Debug Proxyができていた

Macを使わなくてもiPhoneのデバッグできるようになったので、Linux使いの私は捗るようになった。 なおWindowsでは動かないらしい。

iOS12以降でBasic認証の処理が色々とよくわからなくなった

よくわからないけどまともに動かなくなってデバッグつらい。これはマジでつらい。 デモで見せたい時とか超困る。 適当なtokenをキーとしたページをでっちあげて短縮URLで送るくらいしか抜け道を思い付かないが…。

iOSでWebページを最大化表示できるようになった

Androidは以前からこの機能がありましたが、iOSでも対応しました。 ホーム画面に登録するとアプリっぽく動作してくれるようになります。 iOS/Androidの両方で最大化表示できるようにするには以下のように書きます。
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">

iOSでWebアプリをホーム画面に追加するとリロードが効かなくなる

iOSでホーム画面にWebページを登録すると、独自の更新間隔でキャッシュをリロードするようになります。 HTTPサーバのキャッシュ情報が使い物にならなくなるので、検証中は content="no" にしないと検証が困難に。
<meta name="apple-mobile-web-app-capable" content="no">
日本語情報はまったく見つからなかったけど、海外ではハマっている人が結構居た。 キャッシュを消すためには、端末のデータを直接弄って消すか、iOSのキャッシュを削除した上で content="no" にするしかないのかなあ。 運用時もキャッシュが効き過ぎて割と困る。 PWAを設定するとService Workerを見てくれてその更新モードが適用されるみたいなので、PWAの利用を前提に使ったほうが良さそう。 これはPWAに対応していない古めのiOSやSafariのバージョンをどうするかという話にも繋がってくる。

PWAができていた

iOS 11.3 / Safari 11.1からiPhone/iPadでも対応し始めたらしい。 色々な使い方があるけど、コンテンツキャッシュとアドレスバーを消してアプリっぽく利用できるようにするためだけに利用している。 最近のスマホだとPWAを使えば先に述べた指定をしなくてもアプリっぽくなる。 PWAのキャッシュ更新は手動で調整できて嬉しい
PWAのおかげでかなり早く起動できるようになった。対応も簡単なので、これはどんなサイトでもやったほうが良い。 今回は使ってないけどGoogleフォントはPWAに対応しているし、結構色々なものがキャッシュできる。 適当な実感値だとスマホは200msくらい改善できる気がする。 他にもPWAは設定しているだけで簡易的なF5アタックブロッカーになるので、割と良い仕組みだと思った。

Desktop PWAができていた

Chrome 67からデスクトップでもPWAが使えるようになった。 インストールするとデスクトップにアイコンまで作ってくれる。Electronより楽かも? スマホほどの速度改善は期待できないし、まだ試験的機能でしかないけど、将来には期待が持てる。
いずれ解決される気がするけど気になる動作が色々。 DevToolsのネットワークのロード時間がService Workerのせいでおかしくなる。 遅くなっているように見えても実際には早くなってるので注意が必要。 他にも普段からキャッシュが効きまくってデバッグがしにくくなる問題もある。 毎回キャッシュを消して確認してる。

AMPができていた

CSS/HTML/JavaScriptに様々な制限を加えてキャッシュする事で高速な表示を可能にする技術。 こちらは対応が面倒臭い。 制限がキツ過ぎて、正直いくら早くなると言ってもJavaScriptバリバリのサイトへの適用は困難を極める。 そもそもファーストビューのインライン化では !important を使ったほうが楽だけど、使ってしまうとAMP化できなくなる。これはキツイ。 今回作ったサイトでは使えそうもないので使ってない。

jQueryがボトルネックになった

様々な最適化ツールの進化によって、今回のサービスで一番のボトルネックは外部サービスの遅さとjQueryのロードの遅さになりました。 ネットワークとDBの細かなボトルネックをきちんと処理して負荷が大きく掛かってない状態なら、確かにjQueryはキャッシュが効いていなければ100ms近く掛かってしまうので、現状一番重いです。 jQueryより前に色々処理するのが最初の対策ですが、残りの部分はやはりjQueryを使う事になるのでどうしても遅くなる。 うまくネイティブ化して50ms以下にしたい気持ちはあるけど未着手です。

BootstrapVueが出ていた

先に述べたようにロード時間のほうが問題なので、ほとんど使ってないjQueryでも良いかなと思ってるんだけど、今も採用の候補にはある。仮想DOMを自前で処理してると別にフレームワーク自体の機能はそんなに関係ないんだよなあ。 一番気になるのはPWAの進化に対してVue Nativeなどのネイティブ化技術がどれくらい強さを維持できるかどうか。
ところでBootstrap v5ではjQueryへの依存がなくなるらしい。 私はアニメーションとBootstrapの依存ライブラリのためにしか使ってないので、そこを提供してくれれば移行は困りません。 ただ意外とそこが面倒。 前者はVelocity.jsが出てきたけど別にサイズが軽い訳ではないし、ライブラリのjQuery離れもどれくらいの速度で進むかな。 Native JavaScript for Bootstrapやv5が安定してから採用するほうがVueを使うより楽だし軽いと思うので待ちですかね。 v5が出るまでは基盤ライブラリに何を使うかは迷い所かも。

Parcelができていた

煩雑なHTML/CSS/JavaScritptを何も設定せず最小化してくれるParcelという素敵なツールが出ていた。 便利なのは理解したけど、最小化やキャッシュ周りで最も注意が必要なのはService Workerで、ここをミスするとバグに気付けなくなるので、ここを自動化するためにもビルドツールは完全に自作した。
ただこれはworkbox-webpack-pluginを知らなかったからであり、このプラグインは上記で述べた事を良い感じにやってくれるので、今だったらこちらを使うかも。 workbox-webpack-pluginがかなり便利なので、次回作る時はWebpackでも良いかなとも思っている。 Parcelはそのへんが安定してきたら候補に上がる。

レイアウトのリフロー対策はよくわからない

とりあえず完成したサイトはPageSpeed Insightsでパソコン版は99点だった。 その後モバイル最適化のためにあえて点数を少し落としたけど、1つ気になったのは過大な DOM サイズの回避というもの。 リッチサイトじゃどうしようもないような。 もしかしてレイアウトのリフローを避けるためには、iframeを使うべきなのだろうか。

ChromeのDevToolsから色々なSEOのチェックができるようになった

DevTools -> Auditから確認してもらえる。 PageSpeed InsightsのようなレスポンスのチェックだけでなくSEO周りもチェックできるようになって嬉しい。 jQueryでWarningが出るという。 その問題を無視すれば、Performanceを以外を100点にするのは今のところ簡単。

WebPが良い感じになってきた

WebPは以前からたいていのブラウザでHTML経由の表示はできていたと思うのですが、2018/01/29でリリースされたFirefox65の正式採用によって、ついに実用的な利用が視野に入ってきたように思います。確認テストもしてみた感じでは、画像の多いサイトでは通信量を1/10以下にできる可能性もありそうですね。

CGIはSSHが使えないとつらい

もしくはリバースプロキシがいかに天国であるか。 もしくはレンタルサーバとVPSの選び方。 結構長い話になるので詳しくはこちらをどうぞ
さらにEC2やGCP、S3なども含めて運用基盤全般も軽く調査し直したけど、 今回は検討の結果、Vultrを利用した。 価格のバランスが良くてネットワーク速度が早かったので選んでみたけど、適宜増設していくつもりです。

マイクロWebフレームワークが増えて選択肢が広がった

昔はRuby on RailsDjangoなどの巨大なフレームワークしかなかったけど、マイクロWebフレームワークの種類が凄く増えた。 Ruby/Pythonでも早いものが増えたので、気軽に実装できるようになった。

静的ファイルを作り過ぎてinodeが枯渇した

静的ファイルのほうが早いものはひたすら静的化していたのですが、容量の小さなVPSで小さなファイルをたくさん作ると、容量より先にinodeが枯渇する事を知りました。 ちなみにext4でinodeが枯渇するとファイルシステムを作り直さないといけない。これはあかん。 ファイルに書き出しまくるとこういう問題もあるんだなあ。 レンタルサーバはVPSよりクリティカルな問題にならないかなこれ。
仕方がないのでKVS実装にサクっと書き直した。 ほぼファイルシステムとしてしか使ってないけど、ファイルシステムより効率は良いのでファイルサイズが1/3になったし、リクエスト数も減らせて高速化した。 レンタルサーバにこだわらなければハマる事はなかった問題だったけど、勉強になった。

init.dスクリプトのテンプレートができていた

いつも超迷う /etc/init.d/service でサービス登録するテンプレートができていて、凄く簡単にサービス登録できた。

決済周りが一番時間が掛かった

コア実装は満足のいくレベルの1万行〜くらいを3週間でパパっと書けたので、速攻でリリースしようと思ったものの、実際にはかなり時間が掛かっている。 調査に1週間、少額決済の実装に1週間、申請に5週間、利用可能までに2週間掛かった。
調査の時間が長いのは久々にWebサービス作ったせい。 決済の実装が思ったより闇が深くて検証に時間が掛かって、審査にも凄く時間が掛かった。 やっぱ申請って疲れるなあ。 最初からすべてOKをもらってから運用開始しようとするのは凄い時間掛かるのでやめたほうが良い。 申請中にまったり機能改善をするのが良さそう。

今回は割と学びの多い開発になった。

0 件のコメント: