Nuxt, netlify, Firebase を使ったWebサービス開発と個人開発における技術選定のポイント

![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/6ff1d383-4cea-9f3a-b832-4f7d6830a830.png)

技術構成はこんな感じで作りました。
Nuxtというよりかは個人開発における技術選定のポイントを主体に解説した記事です。
これから個人開発をやろうとしている人の参考になれば幸いです。

## どんなWebサービス？
Google Calendar の表示/非表示を一括で切り替えるWebサービス。
※ゲームとかでよくある装備マイセットのGoogleカレンダー版です。

G Suite を導入している企業だとカレンダー画面が会議室や他のユーザーの予定で溢れてしまいます。
TV会議ができる会議室のセットや同じチームメンバーのカレンダーセットをつくり、セットごとの予定をカレンダーのTOP画面で目視で確認できるようになります！

<img src="https://qiita-image-store.s3.amazonaws.com/0/35595/44231117-cd32-abfb-ef93-6c31ba33db1e.png" width="500px">

### 触ってみたい
https://gcalmanager.com
※無料です

<img src="https://qiita-image-store.s3.amazonaws.com/0/35595/b59239c8-3281-db98-05d1-e68c64b47c20.png" width="500px">

## 作るのにどれぐらいかかった？
11/10開始 〜 12/2終了。30〜40時間ぐらい？
初めて触る技術が多くて、規模の割にだいぶ時間がかかってしまった。

<img src="https://qiita-image-store.s3.amazonaws.com/0/35595/63c664fd-762c-ba31-3537-9b5d627f857d.png" width="400px">


## 技術構成 :tools: 
全体図はこのような感じです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/6ff1d383-4cea-9f3a-b832-4f7d6830a830.png)

## 画面構築 :paintbrush:
Nuxtをベースとして、ボタンなどのUIコンポーネントは Element UI を使いました。
また、Storybookをコンポーネント開発の補助ツールとして使用。
次のような記事も書いたので良かったのでどうぞ。
[Nuxt, ElementUI, Storybook 構成のVueプロジェクトの始め方 - Qiita](https://qiita.com/howdy39/items/38cf2c2a4d356c8d0f6c)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/990bc10e-a9e0-1225-84a8-862b83ed2f14.png)

## デプロイ :arrow_heading_up: 
GitHubのプライベートリポジトリで開発をして、masterブランチにpushするとnetlifyに自動でデプロイするようにしました。
別途CIサービスを使わなくていいので手軽に始める場合はこの構成が**圧倒的にラク**です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/2943863b-d8c6-92cf-cb47-ebe2e68f4050.png)

## ドメイン・SSL :name_badge: 
ドメインはGoogle Domainsから購入しています。
また、Google Domainsは**G Suiteのメールアドレスが瞬殺で作れます。**
サービスの窓口などのメールアドレスを用意する場合も考慮してGoogle Domainsに寄せておくのをおすすめします。
[Google Domains と G Suiteを使って独自ドメインのメールアドレスを作成する - Qiita](https://qiita.com/howdy39/items/c482438d8de121eaa78e)

また、SSL対応はnelifyに用意されているLet's Encryptを使用します。これも本当にラクです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/4e6216e3-5bac-5c35-690e-91a95e65b834.png)


## Googleカレンダーの操作 :calendar: 
Googleカレンダーの操作はGoogle API JavaScript Client を利用しブラウザから直接APIを叩くようにしています。
通常、この手の外部APIはアプリケーションサーバーを用意してそこからAPIを叩くのが一般的ですが、アプリケーションサーバーを用意したくなかったのでこの形にしました。
※デメリットとしてはライブラリを動的に読み込むので初期表示が遅くなるところですね。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/ad5352c8-aece-e40e-e3e4-70b5966df01a.png)

## データの保存先 :package:
データの保存先は（使ってみたかったので）Firestoreを利用しました。

Calendar API を使うときに取得できるid_tokenをFirebase Authenticationを流す感じにするとカレンダーAPIの方と同時に認証できます。
※このパターンでFirebase Authenticationを使うのは大分レアケースな気がするのでサンプルコード置いときます。

```js
// Google API JavaScript Client でid_tokenを取得
const googleUser = gapi.auth2.getAuthInstance().currentUser.get();
const idToken = googleUser.getAuthResponse().id_token;

// id_tokenを利用してFirebaseを認証
const googleAuthProvider = new firebase.auth.GoogleAuthProvider();
const credential = googleAuthProvider.credential(idToken);
const fbUser = await firebase.auth().signInAndRetrieveDataWithCredential(credential);
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/94f95e9c-01a2-d9f2-d025-82134f27932d.png)


## アクセス解析:chart_with_upwards_trend: と エラーログ収集 :warning: 
アクセス解析にGoogle Analyticsつかうのは鉄板ですね。
イベントトラッキングも入れておき、この機能はどれぐらい使われいるかなどをしっかり計測しておきましょう。
トラッキング情報を用いて全然使われていない機能を消してしまう、などの参考情報にします。

エラーログの収集はsentryのvue用のやつを組み込みました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/38e41b0c-3302-c6bf-7b95-4e14f829ab7c.png)


## 技術選定のポイント :point_left: 
### 1. お金 :moneybag:
Google Domains のドメイン代 と Github のプライベートリポジトリ代だけになるようにしています。
※ 独自ドメインではなく、ソースを公開しても良いなら完全無料になる

サービスが全然使われなくても、維持費がかからないのでお財布に優しい :v:


### 2. サーバーを自分で用意しない :computer:
個人開発で、OSやミドルウェアのバージョンアップを仕事しながらやっていくのはつらいです。
（サービスが使われなかったらなおさら）

各種サービスのリリースノートを追うだけのほうが知識もつくので一石二鳥:v:


### 3. 負荷を気にしない構成にする :muscle:
"サーバーを自分で用意しない" に繋がりますが、
利用者が増えたから、サーバー台数を増やす？
そんな運用を個人開発でやるのはつらいです。

外部サービスをうまく使って自動でスケーリングする仕組みを使うと負荷を気にしなくてラク:v:


### 4. アカパス認証はしない :secret: 
パスワード使い回しされてると漏れたときが怖いです。
仮に情報漏えいしたときのことも考慮したほうがいいでしょう。
そのためパスワードを使った認証ではなく、ブラウザとGoogle間で認証・認可を行うようにすると精神的にラク:v:


### 5. アクセストークンを保持しない :key: 
Googleカレンダーへの認可は求めていますが、前述のGoogle API JavaScript Clientを使って直接ブラウザからAPIを実行しています。
そのためブラウザ上にしかアクセストークンを保持していません。
そうすることで、**サービス提供者である私も利用ユーザーのカレンダーを見ることができない**ようにしています:v:


## Nuxtを使って良かった点 :sparkles:
* ドキュメントが日本語で読める :flag_jp:
* ディレクトリが決まっているので迷うことが少ない
* Vuex や Vue Router などが組み込み済
* webpack の設定が不要（結局Storybookで必要になったが）
* プラグインが豊富 （↓は今回使ったプラグイン）
  * @nuxtjs/sentry
  * @nuxtjs/google-analytics
  * @nuxtjs/pwa
* 情報が豊富  
 Qiitaのnuxt.jsタグの記事が **447** 2018/12/8時点

## Nuxtイマイチだった点:thinking:
思いつかなかった…（SSRをやっていないのでハマりどころが特になかった、というのもありそう）

強いて言うなら TypeScript でやりたいと思ったときに情報が少なそう。（今回はTSを使わなかったが、次はTSでやろうとしている）
※ typescript-template あるけど更新されてない。
https://github.com/nuxt-community/typescript-template


## まとめ
### 個人開発では運用コストを減らそう！ :arrow_down:
広義の運用コストにはメンタルも入れておくと良いかなと思います。

* お金 :moneybag: 
  * 使われない状態で月額数千とかかるような構成はちょっと…
* 時間 :timer: 
  * OSやミドルウェアのアップデートとかやりたくない…
* メンタル :heart: 
  * 情報漏えい（大事な情報を持たない）や負荷を気にする など

### Nuxtはいいぞ！
いいフレームワークです、これからも使っていきます:muscle:


## 余談
### 100点を目指さない、60~70点ぐらいでいいじゃない
個人開発は世に出すことが一番大事だと思います。
もちろん、セキュリティ等は大事なとこですが、パフォーマンスや見た目で100点目指していつまでたっても終わらないのは本末転倒です。

ラクできるところは外部のサービスやライブラリを使ってラクをしましょう。
それらは100点を目指す場合には適さないことも多いでしょう。
でもそこは「まぁ動いてるしいっか」ぐらいのゆるい気持ちで :ok_hand: