Help us understand the problem. What is going on with this article?

アドベントカレンダーを作れるアプリを作ってみた【Vue.js×Firebase】

この記事は株式会社クロノスの「~2020年春~勝手にやりますアドベントカレンダー」の1日目の企画記事です。
(株式会社クロノスのFacebookはこちらから)

「~2020年春~勝手にやりますアドベントカレンダー」インデックスはこちら(随時更新)

ということで本題

トップバッターを担当します、maroKanataniです。
上述の通り、会社でアドベントカレンダーやろうって話になったので
流れに乗ってアドベントカレンダーを作れるアプリを作ってみました。
技術の話も含めて公開までの手順等をまとめておきます。

アプリは以下のリンクから使えます。
アドベントカレンダーツクール

ソースコードはこちら

(不具合等ありましたら、コメント等でこっそり教えてください:bow_tone1:

ちなみに今回やるアドベントカレンダーをこのアプリで作ると以下のような形になります。
~2020年春~勝手にやりますアドベントカレンダー

できること

アドベントカレンダーの作成

カレンダーのタイトル、対象月、何日まで投稿するか、休日も投稿するかどうかを設定できます。
設定を変えるとカレンダーのプレビューが同時に更新されます。
スクリーンショット 2020-02-28 22.05.11.png

登録を進めると最終的に以下のようなダイアログが出てきます。
テキストボックス内のリンクを共有することで他者とカレンダーの情報を共有することができます。
閲覧専用のページと参加登録等の編集が可能なページの2種類があります。
(今回はなるべく外部から編集されたくなかったのでこのような形にしました。)

スクリーンショット 2020-02-28 22.23.11.png

カレンダーの閲覧、参加登録

共有できるURLには閲覧専用と編集可能なものの2つがあり、
編集可能URLからのみ、参加登録や編集が可能となっています。

閲覧専用ページ
スクリーンショット 2020-03-01 13.48.11.png
編集可能ページ
スクリーンショット 2020-03-01 13.48.30.png

モチベーション

社内のアウトプットがもっと活発になってほしい。 という切なる願いが一番のモチベーションです。
弊社もQiitaやSlackの社内チャンネルでのアウトプットは今でもあるにはあるのですが
大体いつも同じ人が投稿していたりして、活発なように見えるけど実はそんなにやん・・・と感じることが多く(個人の感想です)、もっと色んな人を巻き込んだ取り組みができないかなーと思っていました。
そんなところに今回アドベントカレンダーをやろうという話が来たので、全力で乗っかりにかかった次第です。
自分一人だけでアウトプット続けるのは大変ですし、 アドベントカレンダーはいい意味でのプレッシャーを抱えつつ続けられる良いツールだと思っているので、12月以外でもできるようになればいいなーという気持ちもあり、今回このアプリの作成に取り組んでみました。

使用技術

スクリーンショット 2020-02-29 17.04.04.png

  • Vue.js
  • Vuex
  • Buefy
  • Firebase(Hosting, Firestore)

(ちなみに私自身、どの技術も初学でしたので至らない部分は多々あるかと思います。何かあればご指摘いただけると幸いです。)

環境構築~デプロイまで

手空きの時間にちょっとづつ作ったのでだいたい2週間くらいかかってしまいました。
一日平均2~3時間といったところでしょうか。

以下手順になります。(長いのでいらない方は最後までスキップ推奨)
※npmコマンドを多用するので、Node.jsをインストールしておく必要があります。

Vue.js

vue-cliのインストール

今回はプロジェクトを作成するのにvue-cliを使用しました。
以下のコマンドでインストールできます。(yarnでも可能です)

npm install -g @vue/cli

プロジェクトの作成

プロジェクトの作成は以下のコマンドで行います。

vue create [プロジェクト名]

コマンドを叩くと色々聞かれますが、今回は基本的に全部デフォルトで作成しました。

ローカルで起動

出来上がったプロジェクトのディレクトリ内で以下のコマンドを実行すると開発用サーバーが立ち上がります。

npm run serve

スクリーンショット 2020-02-29 17.37.02.png

デフォルトだとlocalhost:8080で起動します。
ブラウザからアクセスしてみましょう。
以下のような画面が出ればおっけーです。

スクリーンショット 2020-02-29 17.38.14.png

ひたすら実装

プロジェクトができたので、あとはひたすら実装です。
ますはFirebaseと連携する部分以外を画面設計しながら実装しました。
コンポーネントの設計やディレクトリ構成は以下の記事を参考にさせていただきました。

2020年にWebフロントエンドを勉強する人が作るべきたったひとつのアプリ
Vue.js ディレクトリ構成 色々試してみた

あと、今回はUIライブラリにBuefy、ルーティングにVue Router、状態管理にVuexを使用しているので、main.js、index.htmlに以下のように修正しています。

各ライブラリインストール

npm install buefy
npm install vue-router
npm install vuex --save
main.js
import Vue from 'vue'
import App from './App.vue'
import Buefy from 'buefy'      // Buefy用
import 'buefy/dist/buefy.css'  // Buefy用
import store from '@/store'    // Vuex用
import router from '@/router'  // Vue Router用

// Buefy用
Vue.use(Buefy, {
  defaultIconPack: 'fa',
})

Vue.config.productionTip = false

new Vue({
  router,    // Vue Router用
  store,     // Vuex用
  render: h => h(App),
}).$mount('#app')
index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <!-- Buefyで使用するアイコンをインポートする -->
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css">
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

Firebase

Firebaseを使用するにはGoogleアカウントが必要になるので、ない場合は作成しましょう。
今回は全て無料で使えるSparkプランで作ってます。
(無料でこんなに使えるなんてGoogleさん太っ腹ですよね)

プロジェクトの作成

Firebase Consoleの以下の画面からプロジェクトを追加しましょう。
今回はプロジェクト名以外は全てデフォルトで作成しています。
スクリーンショット 2020-02-29 17.56.09.png

DB作成

プロジェクトのページのサイドバーからDatabaseをクリックするとDatabaseを管理する画面へ遷移します。
初回はロケーションの設定と、テストモードか本番モードを設定するよう言われるので、今回はロケーションはasia-northeast1、テストモードに設定しました。(あとで本番モードに変更しました。)

設定後はデータの作成が行えます。今回はカレンダーの情報を格納するcalendarsというコレクションと予定を格納するschedulesというコレクションを作成しました。
(ちなみにRDBしか実務で触ったことがなかった自分からすると、 コレクション=テーブル、ドキュメント=レコードのような位置づけのように感じました)

スクリーンショット 2020-02-29 18.13.51.png

Vueのプロジェクトに組み込む

認証情報の取得

DBは用意できたのでVueからアクセスできるようにしましょう。
Firebaseのプロジェクトのページから「+アプリを追加」を選択します。
今回はWebアプリなのでWebを選択します。
スクリーンショット 2020-02-29 18.28.36.png

アプリのニックネームを入力し、今回はHostingも利用するのでチェックボックスにチェックを入れて登録。
(②以降はあとでやるので一旦スキップ)

スクリーンショット 2020-02-29 18.33.55.png

プロジェクトのページに戻ると「+アプリを追加」の左に先程設定した内容があるのでクリック
画面の下部のFirebase SDK snippet > 構成でAPI Key等の情報が見られるのでコピーする。

Vueアプリケーションに設定する

Firebaseのライブラリをインストールする

npm install firebase --save

今回はsrc直下にfirebaseというディレクトリを作成し、そこに先程作成した認証情報を配置します。
以下2つのファイルを配置します。

firebaseConfig.js
// さっきコピーした内容を貼る
export default { 
    apiKey: '', 
    authDomain: '', 
    databaseURL: '', 
    projectId: '', 
    storageBucket: '', 
    messagingSenderId: '' 
}
firebaseInit.js
import firebase from 'firebase'
import 'firebase/firestore'
import firebaseConfig from './firebaseConfig'
const firebaseApp = firebase.initializeApp(firebaseConfig)
export default firebaseApp.firestore()

こうすることで以下のように使用できます。

sample
import db from '@/firebase/firebaseInit'
import firebase from 'firebase'

const calendarRef = db.collection(collectionId) // コレクションID
                      .doc(documentId)          // ドキュメントID

calendarRef.get().then(doc => {
    console.log(doc.data())    // JSONが出力される
})

firebase cli導入

デプロイ用にfirebase cliをインストールします

npm install -g firebase-tools

デプロイ

まずはFirebaseのコマンド実行するために認証を行います。

firebase login

次にVueのプロジェクトのディレクトリで以下のコマンドを実行します。

firebase init

今回はFirestoreとHostingを使用するのでその2つをチェックします。
スクリーンショット 2020-02-29 19.13.27.png

以降は基本的にはデフォルトで、以下のpublic/index.htmlを書き換えるような設定はNoを選択しましょう。
スクリーンショット 2020-02-29 19.17.54.png

次にfirebase.jsonを修正します。
デプロイの対象をdist配下のファイルに変更します。

firebase.json
{
  "hosting": {
    "public": "dist",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  }
}

次にデプロイ用にVueのプロジェクトをビルドします。
dist配下に新しくファイルが作成されるはずです。

npm run build

最後に以下のコマンドでアプリをデプロイします。

firebase deploy

コンソールに表示されたURLに無事アクセスできたら成功です。

苦労した点

画面コンポーネントの設計に関する部分が一番苦労しました。
特にVuexの使い所です。コンポーネントを分割するのはいいんですが、何でもかんでもstoreに頼ってしまうと、データの流れがわかりにくくカオスな状態になる(特に更新系)ので、どのコンポーネントまではstoreを参照して、他は基本的にはpropsで渡す、みたいなルール決めを上手くやらないといけないなーという感想を持ちました。(規模が大きくなったときとか特に難しそう)
今回はとりあえずpages配下のコンポーネントのみstoreとやり取りする形を目指しました。

最後に

簡単なものではあるものの、アプリの作成から公開まで一人でできたのは良い経験になったと思います。
Firebaseを使うと結果的にアプリ側の作成に集中できる時間が増えるので、こういった個人開発には特に向いているツールだと感じました。
今回作成したアプリも自分が認識しているだけでも課題は山程あるので、可能な範囲で引き続き改修していけたらなと思ってます。開発楽しい。技術楽しい。

参考

2020年にWebフロントエンドを勉強する人が作るべきたったひとつのアプリ
Vue.js ディレクトリ構成 色々試してみた
光の速さでデプロイ ~ Vue + Firebase hosting ことはじめ ~
Vue.js + FirebaseでTodoアプリを作る

maroKanatani
カメレオンエンジニア目指してます。 爆速で成長していきたい。 同じ技術ばっかりやるんじゃなくて色々やりたい。 たまに技術者の教育とかもやってる。
https://www.kronos.jp/
kronos-jp
AI開発・WEB開発・システム開発・Android開発・iOS開発・IT研修・トレーニング・新入社員研修などを行う企業です。
https://www.kronos.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away