2019/08/01
※ この記事は、実務経験の乏しいWEB開発未経験者〜新人WEBエンジニアに向けて書かれています。
※ ソースコードレベルの話はほぼ出てきません。
※ 個人開発のWEBサービスの公開までに必要な手順例として、4日間でやったことを紹介しています。
ワンクリックで位置を共有できるWEBサービス。その名も「いまここ」。
https://imakoko.tokyo
https://twitter.com/imakoko17
ごくちいさいサーバーレスSPAです。
着手から公開までを約4日間(人日換算)で行いました。
↑ワンクリックで生成されるURLを共有するだけで全員の位置を1つの地図上にリアルタイムに反映できます。
まずは提供したい価値を言語化して明確化するところから始めます。
※ 以下技術的な話でないですが背景として。興味がなければ読み飛ばしてくださいませ。
事業に取り組む前に、「ビジネスモデル」や「市場における立ち位置」或いは「価値の流れ(Value-Chain)」を明確にするために、価値とお金の流れを図に落とし込んでみましょう。
この過程が「本当にこのモデルは有効なのか」「このビジネスドメインの優位性は何か」「顧客は本当にこの価値を求めているのか(或いは求めるべきなのか)」を深める第一歩となります。
今回はお金が「全く」絡まないので、シンプルにシステムイメージ図になりました。図の作成はdraw.ioだけあればいいです。実務でもどうぞ。
https://www.draw.io/
【採用理由】(開発が)はやい・(開発コストが)安い・うまい(書いてて心地よい)。
Nuxt.jsも実務経験あるのですが、個人的にあまり好きでないので今回は不採用。
【補足】 Firebaseってつまりなに?
最近ではすっかり有名になりましたが、数年前までは名前も聞いたことないよーって人も多かったと思います。
(今現在でも、製品での採用事例はそこまでは多くなく、いまいまでみても挑戦的な選択肢だと思います)
来歴としては、もともと米国のスタートアップが作っていたのをGoogleが買収して今に至っています。
(最近はあんまり聞かない用語な気もしますが)「mBaas」という部類に入るクラウドサービスです。mは「Mobile」のmですが、firebaseはWEB開発でも利用できます。
https://mbaas.nifcloud.com/about.htm
すごくざっくり説明すると、GCPをフロントエンドから直接叩けるようにした感じのもので、普段Servletとかで古き良きWEBサービスを書いている人が急に触ると常識が通じなさすぎて脳震盪を起こすかもしれません。
(個人開発での)作業レベルでいうと、サーバーサイドの環境構築および機能実装が不要になり、もっというとホスティング環境の構築も不要です。
極論すると、node.jsでフロント書いて、firebase deploy
でWEBサービスの開発が終わります。
もう、毎度毎度書いている「認証フロー」や「ゲッターセッターの羅列」や「コネクションプールの管理」や「select文発行するだけのメソッド」や「$.ajaxでの煩雑なデータのやり取り」や「ファイルアップロード処理」などを見ずに済みます。
有料アカウントさえとっておけばサーバー負荷でダウンするとか基本考える必要がなく、夜は安らかに眠れます。
https://news.livedoor.com/article/detail/15105748/
...という開発のパラダイムシフトが起こっている場所がFirebaseなのです。
プロダクションで採用するのは色々あるのでちゃんとPOC回すとかしないと破綻のリスクもあると思いますが、価値先行型の個人開発であれば、十二分に採用の価値のあるプラットフォームだと思います。
--- 補足ここまで ---
まず、頭の中で大まかなシステム設計をし、必要そうなライブラリ・API類を調査します。
あとで頓挫したり、手戻りが発生しないように、あらかじめ各APIの公式ドキュメントでやりたいことが実現可能か確認しておくとよいでしょう。
今回コアとなるのは「地図API」と「データのリアルタイム反映」です。
候補に上がったのはGoogle Maps APIとYahooの地図APIです。
調べてみるとGoogleの方はいつのまにかGCPに統合され、お金もかかってきそうなので、今回はYahooのAPIを採用しました。
https://developers.google.com/maps/documentation/javascript/tutorial?hl=ja
https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/js/
こちらはFirebase(realtimeDB/firestore)の得意分野ですから、普通に組んでいれば実現できます。Firebaseなしだと手でAjaxかWebsocketでゴリゴリやる必要があるので結構大変です。
HTML5のGeolocationAPIを使います。
スマートフォン含めて多くのブラウザで利用できるようなので問題なさそうです。
https://developer.mozilla.org/ja/docs/Web/API/Geolocation/Using_geolocation
エンジニアにとっての鬼門だったりしますが、画面デザインを考えてみます。
今回はごく小さいサービスなので使いませんでしたが、普段はAdobeXDを用いて画面デザインを固めます。
https://www.adobe.com/jp/products/xd/details.html
後で<span style="font-size:12px !important">
とかカオスなことにならないようにデザインのガイドラインを用意して具象値を変数化しておくとよいでしょう。↓変数化の例。
https://bulma.io/documentation/customize/variables/
今回はスマホで使ってもらうことを前提としているので、そのことを念頭においてデザインします。
ロゴもWEB上で作れたりします。
(細かいデザインは後回しで兎も角MVP!という方はロゴの色をメインカラーにつかっておくのが便利です。)
https://www.777logos.com/
画像やアイコンはフリーで提供しているサイトがあります。クレジットは忘れずにいれておきましょう。
https://unsplash.com/
https://fontawesome.com/
https://icons8.com/icons
CSSフレームワークとしてはオキニのbulmaを採用しました。
https://bulma.io/
bootstrapがオワコン化して久しく、生CSSも育っていてCSSフレームワーク界はコモディティ化してますので、何を使っても、或いは使わなくても、あまり大差は無いので好みで決めましょう。
一方、フレームワークを利用すると、簡単なデザインであればSassの変数値を独自の値に差し替えていけばCSSの基盤が完成するので、あとはドキュメントのサンプルコードをペタペタするとそれっぽい見た目が出来上がります。
今回は兎も角楽をしたいのでbulmaを採用しました。
なにはともあれリポジトリを作るところからです。
私はMicrosoftによる買収のタイミングで(何となく)gitlabに移ったのでそちらにリモートレポジトリを立てます。
CIとか頑張ってもいいですが、大抵の個人開発レベルでは頑張るほどではないです。
https://www.gitlab.jp/comparison/gitlab-vs-jenkins.html
Vueプロジェクトを起こします。
用意されたコマンドを叩いてあげるとテンプレートが生成されます。
https://cli.vuejs.org/guide/creating-a-project.html#vue-create
適宜利用するライブラリをnpm install
したり設定ファイル作ったりします。
Vue関連のライブラリ導入の際にはsrc/main.js
をいじることが多いので各ライブラリのドキュメントを参照しましょう。
ESLint・Prettierあたりはとりあえず入れておく派です(エディタ連携の設定もしておきましょう)。
コード整形のコスト減少・品質向上の分開発速度が上がると思います。開発現場でもしばしば使われます。https://qiita.com/soarflat/items/06377f3b96964964a65d
Firebaseの初期化手順は慣れるまで少し手こずります。
詳細手順はQiita上の良記事や公式ドキュメントに譲りますが、概要は以下です。
firebase login
(ユーザー認証)firebase init
(firebaseで利用する機能を選択します)尚、firebase init
の際に聞かれるhostingの公開ディレクトリをdist
にしておくとよいでしょう。(npm run build
でdist
ができます)
個人的に、モジュールファイルの構成(共通化の構造)をある程度決めてクラス等ざっくり組んでから中身のコードを書き始めます。
今回はVue-cliでテンプレができているので適当にfirebaseアクセス用のクラスとかを適宜どこかに作っておきます。
ここから本格的にコーディングに入ります。各人のスタイルによると思いますが、私は一連の画面実装から始めます。
DB設計・詳細設計等も書きながら考えます。(実務ではさすがにちゃんと設計組んでから書き始めますが..)
VueやReactにおいては「コンポーネント設計」もこの作業に含まれます。
UI要素としてのコンポーネント設計はもちろんのこと、利用するAPIやfirestore特有のDB設計など、「どのコンポーネントにどの責務を持たせてどのように値を連携するのが綺麗か・効率的か」も考えながら実装することになります。
また、今回はスマホで使ってもらうことが前提のため、レスポンシブに書いていきます。
ひと昔前に比べればずっと楽にはなりましたが、いまだにブラウザごとの差分とか全く考えないと思わぬ画面崩れとかがあるので可能な限り実機検証等もしておきましょう。
(今回はPCとスマホで両立するミニマムなデザインにしたのでブレークポイントごとの設定とかは特にしていません。)
firestore(データベース)関連のコードを実装し、いよいよ画面の動きとDBの動きを繋げます。
firestoreとVueやReactとの相性はよく、基本的には「変数間のマッピング」(ORマッパ的なイメージ)を行うというイメージです。あとは正しく動けばデータがあっちこっちにリアクティブに反映されていきます。
LAMP環境とかで作業されている方はこれが初めて動いた際には感動すると思います。
C言語は出た当時「自動プログラミング!」とか言われていたそうですが、正にそんなイメージです。値のマッピングを書いておくと「勝手に」あっちこっちに反映されます。
強いエンジニアの方はテストから書き始めたり色々方法論があります。今回は小さいですし、個人開発ですし、でテストコードは特に書いていません。
ただし、WEBフレームワークDjangoでは次のようなことばがささやかれます
"Code without tests is broken by design."
今回はシンプルにSinglePageApplicationを生成するのでnpm run build
を叩くだけでOKです。
良い感じにビルドされたdist/
が出来上がります。
firebase-hostingの初期化が済んでいればfirebase deploy --only hosting
とすると勝手にデプロイしてくれます。
私はこんな簡単なコマンドもすぐ忘れちゃうので↓をdeploy.sh
に書いておいています。
npm run build && firebase deploy --only hosting
【追記】 package.json
に以下のように記述しておくと良いとアドバイスいただきました!
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"deploy": "npm run build && firebase deploy --only hosting" // ← 追加
}
ドメインを取得しましょう。
お名前.comとかでぽちぽちするとドメインを取得できます。
https://www.onamae.com/
ドメイン鯖側にレコードを追加し、firebase-consoleのホスティングタブの「ドメインを接続」ボタンを押してドメインを接続します。
初めてやる時微妙にハマりがちなので、インターネット上の記事を漁りましょう。
https://firebase.google.com/docs/hosting/custom-domain?hl=ja
大まかな流れはドメインを取得したサイトのDNS設定のページを開き
1. 「テキストレコード」を設定して認証
2. firebase-console上に表示されるAレコードをDNS設定に書き込む
だけですので焦らずにやれば大丈夫です。
(DNSレコードの反映には数分かかるのでのんびりやりましょう)
慣れるまでちょっと面倒ですが、インフラの人でも無い限りなかなかDNSなんて触らないでしょうから、勉強の機会にはなりますね!
表示速度も重要です。
表示速度を解析してくれるGoogleのChrome拡張やWEBサービスがあります。
https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk?hl=ja
https://developers.google.com/speed/pagespeed/insights/
闇雲に(特にSPAで)高得点をもらおうとすると泥沼に陥るので、妥協点を探しながら、解析結果を参考に高速化を目指しましょう。
画像・WEBフォント周りは何も考えないで突っ込んでいるとボトルネックになりがちです。
画像の圧縮、読み込むweightの制限・読み込みの遅延化は定跡ですので色々調べてみましょう。
見逃しがちですが、firebaseのhostingでは、firebase.jsonという設定ファイルを触ることでレスポンスのHTTPヘッダをいじることができます。
ここで設定できる「Cache-Control」(ファイルをキャッシュする期間の定義)はこのスコアに大きく寄与するので確認しておきましょう。
https://firebase.google.com/docs/hosting/url-redirects-rewrites?hl=ja#section-headers
「検索エンジン最適化」の対策を施します。
私は門外漢なのでよくわからないです。本を(一緒に)読みましょう。
Google Search Consoleなるツールがあるみたいです。
https://search.google.com/search-console/about?hl=ja
https://support.google.com/webmasters/answer/6258314?utm_source=wnc_376106&utm_medium=gamma&utm_campaign=wnc_376106&utm_content=msg_743502&hl=ja
https://support.google.com/webmasters/answer/9128669?utm_source=wnc_20079900&utm_medium=gamma&utm_campaign=wnc_20079900&utm_content=msg_110183365&hl=ja
サービスにどれくらいの人が流入しているか確認するためにGoogle Analyticsも導入しておきましょう。
https://developers.google.com/analytics/?hl=ja
SPAの場合、ページ遷移しないので、ルーティングにバインドして逐一ビーコンを打たないとSPA内でのページ遷移の情報が取得できません。
vue-analyticsというライブラリを導入するとビーコンの送信を自動化してくれるので便利です。
https://github.com/MatteoGabriele/vue-analytics
ユーザーがページのどの部分をみているのか。どこをクリックしているのか。
を可視化してくれるヒートマップサービスを導入してみます。
今回はメールアドレスで登録後、表示されるHTMLタグをHEADタグ内に挿入するだけでヒートマップを取得できるuserheatというサービスを導入してみました。
https://userheat.com/
一定のPVが溜まってきたら、ヒートマップを分析してページのUIを改善していきましょう。
自身の開発スタイルに合わせて、お手軽に使えるタスク管理ツールを見つけておくとよいでしょう。
個人的にはTrelloが好きです。
https://trello.com/ja
私も法律関係に強くないので細々としたことはわからないですが、兎にも角にも利用規約は用意しておきましょう。
収益性が無く、サービスの性質上、外部への影響の少ない小さなWEBサービスであれば利用規約のテンプレートを作成・管理してくれている法人様があるのでそちらをカスタマイズしていけばひとまず大丈夫でしょう。
https://kiyaku.jp/index.html
お金が発生したり、出会い系が絡む場合は法律事務所に相談したほうがいいかと思います。最悪しょっ引かれます。
また、当サービスでは取得していませんが、個人情報を取得する場合には、プライバシーポリシーの設計も必要になります。
お気に入りのドキュメントサービスをみつけて、マークダウン等で簡易なドキュメントを作成しておくと良いでしょう。
システムコンセプトから設計方針、APIの調査内容や、画像・アイコンの参照元など逐次明文化しておくと忘れた時に役に立ちます。
この記事も開発時に書いたドキュメントから記憶が復元されています。
Firestoreは原則としてWEBから直接アクセスされるものであるため、最低限のセキュリティ担保のため、ある程度手を打っておく必要があります。
最も一般的な手法としては、firebaseにある「ユーザー認証によってデータごとのアクセス可能者の設定を行う」機能を利用することです。
今回のサービスでは特定の個人を認証・区別する必要がないため、firebaseの認証機能のうちの一つ「匿名認証」という機能が利用されています。
また、firestoreへの直接の読み込み・書き込みを禁止し、firebase-functions(AWS Lambda的なやつです)を経由してアクセスすることでリスクを低減させる手法もあります。
データの定期集計などのバッチ処理はfirebase-functionsにfirestore内のデータを巡回するコードを書き、これを外部からcron的に叩きに行く手法がお手軽です。
ただし、functionsはどこからでも叩けてしまうため、手でAPIキー認証的なものを実装する必要があるでしょう。
WEBサービスのフロントからサーバーサイドの重い処理を呼び出す際には「タスクキューを用いた非同期処理」という方法をよく用います。
Firestoreを利用したタスクキューの実現方法としては、特定のコレクションの変更を監視(onSnapshotというコレクションの常時監視関数があります)し、タスク追加時にワーカープロセス(要するに処理関数)を起動する、という流れになります。
調べたら公式のライブラリがありましたのでこちらを利用するとよいでしょう。(node.js等サーバーが必要です)
https://github.com/FirebaseExtended/firebase-queue
趣味範囲での個人開発サービスのほぼ10割はまともに使われないままクローズする運命にあるのでちょっと冗長な気がしますが、個人開発者の気分を味わうためにTwitterアカウントを作成しましょう。
Twitterのプロフィールに「個人開発者です」とか書いている時が多くの人々にとって最も優越的な時間のうちの1つでしょう。
https://twitter.com/imakoko17 (誰か呑みに連れてってクダサイ)
いかがでしたでしょうか。プログラミング初学者の方に「なんか色々やることあるけど、これらのステップを踏めば一応のサービスの形になるんだなー」というイメージを掴んでいけたのなら冥利つきます。
年収3**万の底辺エンジニア(闇)の作業ログ的な記事ですので、間違っている点や情報をミスリードさせてしまう部分、開発手順の漏れなどあるかと存じます。
適宜ご指摘いただけると、皆様の知識でコンテンツの質が上がり、延いては日本のIT業界に間接的に貢献できることになるかと思います。よろしくお願いいたします🙇♂️