GAミント至上主義

Web Monomaniacal Developer.

Nuxt.jsいらない説

Vue使うなら最初からNuxt.js使えよ、という条件反射みたいな風潮にちょっと反論してみる。

※2020/7/6 追記

NuxtJSが必要な状況になって使ったときの感想などはこちら
uyamazak.hatenablog.com

※2018/9/4 追記

1にviewsフォルダ等について追記

またこの記事はNuxtにしようかなと思っていたところでVue CLI3を使って感動し、今も使っていないのでその持論でもあります。

Vue-CLI3に関するVue開発者Evan Youの記事の和訳がきました
jp.vuejs.org

※2019/2/19 追記

SSRのところにOGPについて追記

※追記ここまで

概論

まずVue CLI 3で始めた方がいい。

最初から大人数で大きなアプリを作るつもりだったり、SSRが必要だったらNuxtでいいかも。


私がNuxtを使わない理由3つ

1. Vue CLI3でよく使う公式ライブラリはインストールできるようになった

最近アップデートされたVue CLI3では、プロジェクト作成時にVue Router、Vuex、テスト、lint関連、TypeScriptサポートなどが選べ、選んだ機能に最低限必要な設定ファイルや初期テンプレートが生成されるようになりました。
viewsというディレクトリもができ、routerで使用するページ用vueファイルはそこ、そのほかはcomponentsに入れるというゆるいルールが感じられます。初期状態ではviewsにHome.vue、componentsにHelloWorld.vueが入っている。
でもviewsに入れたからといってNuxtのように自動でルーティングされるわけではなくrouter.jsでの設定が必要。

ホットリロードの開発サーバーも付いているのでほとんどの場合これで十分ではないだろうか。

SSRはついてないので自分でやるかNuxtを使った方がよさそう。
Vue.js Server-Side Rendering Guide | Vue SSR Guide

2. 「The Progressive JavaScript Framework」に反している

jp.vuejs.org

融通が効く
ライブラリと完全な機能を備えたフレームワークの間で拡張できる徐々に採用可能なエコシステム

だからこそNuxtが生まれた理由でもあると思うけど。
Vueは必要に応じてパーツを追加、拡張していこう、みたいな考えを貫いており、コア機能をシンプルに保っています。
その哲学は機能追加の議論などでも貫かれており、かっけーとよく思ってます。

例として最近みたVueにconst的なデータを持たせたいみたいな議論
Constant component data · Issue #6004 · vuejs/vue · GitHub

Vueを始めるときも、最初はCDNからの読み込みで触って、大きくなってきたらシングルファイルコンポーネントで書きたくなってvue-cli使って、みたいに大きくなっていったので、非常にいい思想だと思っています。

その過程でああ、だからVuexがいるんだ、router使うとこんな便利なんだ、みたいな途中の学習や納得が積み重なりVueへの理解が深まります。

一方Nuxt.jsはRailsみたいにいきなりどかっとサーバー環境まるごと全部入り環境な感じなので、Nuxtで一通り用意されてる構造や規約を理解して、それに従って作っていく感じになります。

3. Vue公式ではない

NuxtはVueを使ってるけど別プロジェクトです。
それだけのことですが、NuxtはVueの変更に対し後追いになってしまったり継続が大変そうだなぁと思う。

直接関係ないけど面白いのがGitHubでコントリビューター一覧上位を見ると、全然空気が違う。

Vueは中国系とアニメアイコンが目立つのに対し
Contributors to vuejs/vue · GitHub

Nuxtはヨーロッパ系な感じ。
Contributors to nuxt/nuxt.js · GitHub

それでもNuxtを採用する理由

  • VueでSSRを手っ取り早くやりたい(特にページごとのOGP出しわけは現在のところSSRが必須)
  • Vueのコンセプトどうでもいいから一通り全部用意してもらいたい
  • みんな使ってるから使う

で、現時点の私はコードに関わる開発はデザイナーと私で2人で、企画、設計、ユーザーテスト等その他運営もろもろを2人やっている小さな新規サービス(yagish履歴書)であり、Serach Consoleも問題なくてSSRの必要性もないため、Vue-CLI3で十分、Nuxt.jsいらないとなっています。

本番環境と開発環境でファビコンの色を変えるとすごい分かりやすい話

環境ごとにファビコンの色を変える小技。
前々職にいたデザイナーさんがやってたのを見てから、使わせてもらってます。

yagishの場合こんな感じ。タブを見ると一瞬で分かる。
f:id:uyamazak:20180814141916p:plain

明らかにヤバい紫のヤギ大根が開発(社内サーバー)
まだできてなさそうな緑のヤギ大根がステージング(Firebase)
白いヤギ大根が本番(Firebase)

ただそれだけのことなんだけど、実際使ってみると「これがデザインの力か」と実感できるはず。
これ開発?本番?と悩む時間が無くなる。
見て一発で分かる、考えたり読まなくていいって大事。

ちなみにyagishではロゴがSVGでVue側で操作できることを活かしてロゴも変えてます
f:id:uyamazak:20180814142145p:plain

実装方法としてはだいたい環境変数で切り替えるんだけど、ただテンプレートでlinkタグをif文で切り替えるか、フレームワーク等によってはプラグインでhead内のタグを管理してるから面倒だったりする。

ノンデザイナーズ・デザインブック [第4版]

ノンデザイナーズ・デザインブック [第4版]

GKEでIngressを使ってService単位でロードバランシングする

以前の下記記事の続きで
uyamazak.hatenablog.com

本番とステージング環境で、管理コストを削減するために

を使いまわし、
/api/* → 本番用Service
/api-staging/* → ステージング用Service
とパスでサービスを分けたいときはIngressが必要だったのでやってみた。

クラスタでよければ、HTTP(S)ロードバランサーの設定だけでクラスタ単位で向けられるのでできる。

Ingressとは

Nianticのゲーム名ではなく、直訳すると「入ること」とか「入場権」的な意味らしい。
ネットワークの文脈だともっといい訳があるかもしんない。
2016年夏ごろにGKEで構築した時は見た覚えがなく、HTTP(S)ロードバランサーの設定でやっていたので、新しめの機能なんだと思う。
今からGKEで構築してドメインSSLを使うならGoogle推奨のやり方となる。

Setting up HTTP Load Balancing with Ingress  |  Kubernetes Engine Tutorials  |  Google Cloud

GKE上でロードバランサーが動くわけではなく、実装はHTTP(S)ロードバランサーで行われている。

それぞれの環境のDeployment, Serviceを作る

今回の主題ではないのでハマりどころ以外はざっくり

以下kcはkubectlのエイリアス

Deploymentは下記二つ

% kc get deploy
NAME                     DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
varuna-django            1         1         1            1           21h
varuna-django-staging    1         1         1            1           21h

それに対するServiceは下記

% kc get service
NAME                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes               ClusterIP   10.27.240.1     <none>        443/TCP          21h
varuna-django            NodePort    10.27.254.67    <none>        8080:30001/TCP   21h
varuna-django-staging    NodePort    10.27.242.187   <none>        8080:30002/TCP   21h

Ingress用のyamlを書く

公式ドキュメントを参考に振り分けする
ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: varuna-ingress
spec:
  rules:
  - http:
      paths:
      - path: /*
        backend:
          serviceName: varuna-django
          servicePort: 8080
      - path: /api/*
        backend:
          serviceName: varuna-django
          servicePort: 8080
      - path: /api-staging/*
        backend:
          serviceName: varuna-django-staging
          servicePort: 8080

Deploymentでのヘルスチェック用のパスの設定

IngressのDeploymentに対するヘルスチェックはデフォルトで/、ステータス200になっている。
今回のサービスだと/api/hc的なパスにしていたので、readinessの設定が必要。しばらくハマった。
下記ページでも上がっていた。

github.com
edit deploy でreadinessProbeとついでに同じようなlivenessProbeも設定しておく。

readinessProbeとlivenessProbeについて、それぞれ詳しくは公式ドキュメント
Configure Liveness and Readiness Probes - Kubernetes

kc edit deploy varuna-django
# 適当にいろいろ削った
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    run: varuna-django
  name: varuna-django
spec:
  replicas: 1
  selector:
    matchLabels:
      run: varuna-django
  template:
    metadata:
      creationTimestamp: null
      labels:
        run: varuna-django
    spec:
      containers:
      - image: asia.gcr.io/your-project/tag
        livenessProbe:
          failureThreshold: 3
          httpGet:
            path: /api/hc_pdf
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 3
          periodSeconds: 3
          successThreshold: 1
          timeoutSeconds: 3
        name: varuna-django
        ports:
        - containerPort: 8080
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /api/hc
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 3
          periodSeconds: 3
          successThreshold: 1
          timeoutSeconds: 3

その他いろいろ

ロードバランサーのIPを静的にするとか、ロードバランサーSSL証明書(Let's Encrypt)の設定をする

Googleが自動でやってくれるのを待ち望んでいるがまだのようなので自分で作ったスクリプトで設置した
自分で作っておいてなんだけど、なかなか設定がめんどくさい。
GitHub - uyamazak/gcp-ssl-auto-renewer: Auto renew SSL Certificates commands on Google Cloud Platform (GCP).

これでクラスタを複数作らずに、サービス単位に振り分けることができた。
GKEというかKubernetesは発展途上なので、時間が空いたら以前やった手順を使わずに、公式ドキュメントを見直した方がよさそう。

コンテナ・ベース・オーケストレーション Docker/Kubernetesで作るクラウド時代のシステム基盤

コンテナ・ベース・オーケストレーション Docker/Kubernetesで作るクラウド時代のシステム基盤

Kubernetes完全ガイド (impress top gear)

Kubernetes完全ガイド (impress top gear)

Docker/Kubernetes 実践コンテナ開発入門

Docker/Kubernetes 実践コンテナ開発入門