はじめに(言い訳)
クソアプリアドベントカレンダー初参加のかつおです!
昨年は完全に読む側で、投稿されるアプリのセンスや利用技術のレベルの高さ、力の入れ具合にただただ関心していました。みなさん本当に凄い!
まさか憧れのクソアプリアドベントカレンダーに記事を投稿する日が来ようとは想像だにしなかったのですが、今回は募集期間に偶然出会ってしまったので、勇気を出して申し込みをさせていただきました!!
伝統のクソアプリアドベントカレンダー
「クソアプリは俺が制す。」
断固たる決意を胸に秘め、脳内企画に技術を試したりとかしていたのですが、12月の某日、状況が一変します。
「辛いものが好きアドベントカレンダー」たるものが、私が運営しているカライイネのユーザー様の手によって立ち上がったのです!
「これは...クソアプリ作ってる場合じゃねーな。。」
私はカライイネのユーザー様に心臓を捧げた人間です。
辛いものが好きアドベントカレンダーを少しでも盛り上げるべく、カライイネにアドベントカレンダーに合った新機能を作ろう!
(作った機能は大したことないのでクソっちゃクソです)
という流れで今回の開発に至ったのでした。。
つくったもの
もともと運用していた激辛口コミサイトカライイネのマガジン機能です。
CMSとしてFlamelink CMSを使ってみました。
Flamelink CMSとは?
- コンテンツ管理(記事投稿とか)のみをやってくれるSaaS
- 自分で用意したFirebaseプロジェクトと連携してCMSを構築
- 投稿したコンテンツは自分のFirebase上に保存される
- フロントはなし。コンテンツを取得するAPI等が用意されている
- Firebaseにデータ保持されるので、構造が理解できれば普通のデータアクセスも可能
- 無料枠あり。個人開発レベルなら無料枠に全然収まる。
使ってみた感想
good
- CMSが簡単に構築できるのは便利
- 使い慣れたFirebaseにデータが乗っかるので理解しやすい。
bad
- アップデートちゃんとされてるか、今後もされるか不安
- Wardpressと比較して画像の挿入とか面倒
- データ取得のAPIが権限エラーになって使えなかった..
(Functionsから直接Firestoreを参照することで回避)
システム構成
- もともと本体もFirebaseで運用していたのですが、今回のマガジン用には別のFirebaseプロジェクトを作成しました。(計2プロジェクトのサービスに...)
- Flamelinkは記事の編集に利用。記事データはFirestoreとStorageに保存されます。
- SPAからの記事の取得はFunctionsで作成したAPIを利用しました。
- Functionsで記事の取得は普通にFirestoreの参照をしています。
作り方
Flamelinkの設定
以下が詳しすぎるので、参照ください。
今すぐ始められる!FIrebaseをブログのCMSに変える「Flamelink」を使ってみた!
上記の記事通りにやってないと
①DB
Realtime DatabaseとFirestoreの選択が必要なのですが、私は慣れてるFirestoreを選択しました。(PaizaさんはRealtime Database)
②コンテンツの取得方法
「記事コンテンツを取得してみよう!」の章でflamelink.jsのライブラリ(flamelink sdk)を利用して記事データを取得していますが、私は利用していません。。
flamelink sdkを利用しようとしたのですが、Firebaseの権限エラーを解消できず、もういいやって利用をやめました。
ググってみると同様のエラーに対して、RealtimeDatabaseを使えとの指示が...
③flamelink sdkインストール時のエラー対処
(結局やめましたが)flamelink sdkはnpmでインストールして利用したのですが、npm installでエラーとなりました。
ググってみると、node.jsのバージョン10だとエラーになるとの記載が...
node.jsのバージョンを8に変更することで、エラー回避してインストールはできました。
権限エラーになるので、結局利用はやめましたが…
ちなみにnode.jsのバージョン変更にはnodistを利用しました。(Windows環境)
nodist利用の際には、既存のnode.jsを1度アンインストールが必要なので面倒くさかったです。
④functionsをAPI化
flamelinkのプロジェクトとフロントのプロジェクトが分かれているのでfunctions経由でflamelinkのデータを取得しています。
functionsのコードを載せておきます。
index.js
const functions = require('firebase-functions')
const admin = require('firebase-admin')
admin.initializeApp(functions.config().firebase)
const express = require('express')
const app = express()
app.use((req, res, next) => {
// 許可ドメイン設定
res.header('Access-Control-Allow-Origin', 'https://karaiine.jp')
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept')
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
next()
})
app.use('/api/posts', require('./apps/posts.js'))
exports.app = functions.https.onRequest(app)
./apps/posts.js
var router = require("express").Router()
const admin = require('firebase-admin');
var db = admin.firestore()
router.get('/', (request, response) => {
// isOpen=trueで公開記事を、新しい順に取得
db.collection('fl_content').where('isOpen', '==', true).orderBy('date', 'desc').get()
.then((snapshot) => {
let list = []
snapshot.forEach(doc => {
let data = doc.data()
list.push(data)
})
response.json(list)
})
.catch(error => {
console.log(error)
})
})
module.exports = router
さいごに
読んでいただきありがとうございます!
辛いものが好きな方、辛いものが好きアドベントカレンダーもお願いいたします!
辛いものが好きアドベントカレンダー