SMARTCAMP Engineer Blog

スマートキャンプ株式会社(SMARTCAMP Co., Ltd.)のエンジニアブログです。業務で取り入れた新しい技術や試行錯誤を知見として共有していきます。

VercelとHerokuで手を抜きながらはじめる個人開発

こんにちは、BOXILの開発をしている徳田(@haze_it_ac) です。
今回は業務と少し離れた話をしてみます。

はじめに

みなさんは仕事以外でもWebアプリケーションを作っていますか?
作りまくっている人も、仕事以外ではコードを書かない人も居るかと思います。
私は気になったライブラリを見つけたり、こういう実装ってできないかな?と思った際に、簡単なWebアプリケーションを作って試しています。

この記事ではその中で、ゴールデンウィーク中に "簡単に作れて、運用が楽な SPA/SSR + API Server 構成の小さなWebサービス" を考えて試した際の構成と、作成手順を紹介します。

サンプル

f:id:hazeblog:20200520234937p:plain
画面

https://blog-sample-fe.now.sh/

見た目が雑で申し訳ないのですが、サンプルとして

  • 会員登録
  • ログイン
  • 会員ページ
  • ログアウト

機能を実装したものです。

構成

f:id:hazeblog:20200519233120p:plain
全体の構成

フロントエンドはNext.jsを、バックエンドはRuby on Railsを使いました。
デプロイ先はそれぞれVercel, Herokuを選択。

GitHubリポジトリのstaging, productionブランチの変更をフックに、staging環境やProduction環境にdeployされます。(サンプルのリポジトリ上ではProduction Deployのみを行っています)
ローカルではRuby on Rails, DB等をdocker上で、Next.jsはMacOS上で動かして開発します。

VercelとHeroku

Vercel

vercel.com

VercelはZEIT社が提供する、フロントエンド向けのホスティングサービスです。
All-in-one を謳っており、Global CDNが付いていたり、Serverless Functionsを作れたり、Preview機能が付いていたり、LighthouseやGoogle CloudとのIntegration機能があったりと、本当に様々な機能が存在します。
Zero Config というだけありセットアップがかなり簡単で、特にZEIT社がメインで開発しているNext.jsとセットで使用するとめちゃくちゃ簡単にSPA/SSR/SSGのWebフロントエンドを作ることができます。

Heroku

heroku.com

HerokuはSalesforce社が提供する、 "インフラ管理が不要な" PaaSです。
長く続く人気のあるサービスなのでご存知の方も多いと思いますが、正式にNode.js, Ruby, Java, Python等に対応しており、様々なアプリケーションをデプロイすることができます。

大きな特徴は、CNCFにも追加されたBuildpacksという仕組みで、Linux上で走ることのできるアプリケーションであれば何でも動かせることです。この仕組みを利用し、DB、ジョブスケジューラ、監視Agent、webサーバなどを簡単に提供することができます。

選定理由とメリット

どちらもインフラレイヤを考えることなく、アプリケーション開発に集中するためのプラットフォームです。
インフラレイヤで何かを試したい(kubernetesで遊びたいとか)のであれば選択肢からは外れますが、私はアプリケーションレイヤのことを考えていることが多く、これらを選びました。

また、どちらもGitHubへのpush, 特定branchの変更をフックに自動でデプロイができる仕組みが標準で用意されており、デプロイ時のワークフローもあまり考えなくて済むことも大きな理由です。

アーキテクチャ以外の話

DB

JawsDB MySQL | Heroku Dev Center

Heroku上のDBはJawsDB MySQLを使っています。
Herokuの環境変数にDBのアクセス情報を設定するのを忘れないようにしましょう。

認証方式

jwt.io

認証はJWTを用いて行いました。tokenはCookieに保存しています。
ruby-jwtで簡単に実装できます。

[application_controller.rb]

  # JWT
  def jwt_encode(user_id)
    expores_in = 1.week.from_now.to_i
    preload = { user_id: user_id, exp: expores_in }
    JWT.encode(preload, ENV['SECRET_KEY'], 'HS256')
  end

  private

  def jwt_decode(token)
    decoded_token = JWT.decode(token, ENV['SECRET_KEY'], true, { algorithm: 'HS256' })
  end

https://github.com/haze-it/blog-sample-be/blob/master/app/controllers/application_controller.rb#L30-L41

エラーが出た時のトラブルシューティング、tipsなど

ログ

Herokuは heroku logs --tails --app [アプリケーション名] でログを見ることができます。
(GUIの画面でも多少見れますが、数十行しか見れないのでCLIをおすすめします)

Vercel CLI Reference - Vercel

Vercel上のログも vercel logs ... で見れるようです。

Herokuからの返事が遅いとき

無料プランでのHerokuはしばらくリクエストが来ない状態が続くとワーカーを落とすようで、次にリクエストが来た際に立ち上げ直して処理をするといったことをします。
そのため最初の一回目のアクセスだけレスポンスが遅くなります。
有料プラン(Hobby以上)にすると、24時間立ち上がり続けるようになるため、ちゃんとサービスを運営する場合は少しお金を掛けたほうが良さそうです。

devcenter.heroku.com

また、Herokuのサーバは24時間ごとに一度再起動を行い、リリース等をしています。
複数台構成にすればかぶらないようになるそう。ミッションクリティカルなシステムを構築する際は注意したほうが良さそうです。

vercel.com

Vercelに関しては、チーム開発をする場合や追加の機能を使いたい場合、SLAが欲しいといった場合は有料になりますが、個人で使うぶんは無料です。


以上が作ったものの紹介とtipsになります。
今回紹介したサンプルのソースコードは以下のリポジトリに置いています。

github.com

github.com

次にやること

一般的なWebアプリケーションではほぼほぼ必要となる非同期処理、メール送信、他APIとの連携機能などを作ることで、一通りのアプリケーション開発の素振りをしようと思っています。
AWSのSQSやLambda, SESを使って楽に実装していけたらなと考えています。

真面目に外に公開できる程度のちゃんとしたアプリケーションもそろそろ作らないとな...とも...思っています...やっていきます...🙃
(エラー対応、監視、セキュリティ対策(CORS,XSS対策)などもやらないといけないですね...

紹介した構成だと、アクセスが跳ねたらDBがボトルネックになって死にそうなのでそこもどうにかしたいですね。

最後に

いかがでしたか?
たまに普段と違う技術を使ってみると気分転換になったり、仕事だと得られない経験が得られることもあります。
ぜひ皆さんも試して遊んでみてください!

宣伝

hrmos.co

スマートキャンプでは仕事でも、仕事以外でもプログラミングを楽しむエンジニアを募集しています。