Edited at

NuxtとFirebaseでTwitterまとめサイトを作る! (ツイートを表示する前編)


はじめに - "Vue.js / Nuxt.js / Firebase のアプリ開発体験コース"

🎄🎄 🎅 オープンストリーム Advent Calendar 2018 の 19 日目です 🎁🎄🎄

最近、 Vue.jsとFirebaseを使ってサービス作ったー …と流行っていますね!

この記事では、そんなVue.jsを使ってWebアプリを作る Nuxt.js と、 Firebase を用いて ツイートをまとめるアプリ を作ってみたいと思います!

Vue.js / Nuxt.js / Firebaseの入門としてこの記事を位置づけています🔰

環境はこんな感じです!

$ node -v

v11.4.0

$ npm -v
6.4.1

$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.14.2
BuildVersion: 18C54


作ったモノ

Twitterで モーメント の機能があったのはご存じでしょうか? 使ったことないって?


モーメントはツイートを一つのページにまとめられる機能ですが、この前 スマートフォンアプリからのモーメントの作成ができなくなりました。 不便ですね。

この記事で作るのは、そんなモーメントのようにツイートをまとめるアプリを作ります 🗒

前編ではここまで作ります。このようにまとめたツイートをTwitterの埋め込み機能で表示するアプリになります。

HTMLに埋め込みタグ貼り付ければおしまいだろ

image.png

最終的には Vue.js/Nuxt.js/Firebase を習得しながら次を目指していきます😃


  • Twitterのアカウントで認証して自分だけのまとめを作れるようにする

  • スマートフォンでもツイートをまとめられるようにする


Nuxtプロジェクトの作成

create-nuxt-app を使います。 Node.jsの環境は整えましたよね?

プロジェクトの名前からCSSのフレームワーク、SPAにするかどうかまでこのコマンドで設定でき、素早くプロジェクトが始められます。

$ npm install -g npx

$ npx create-nuxt-app moments-sub
> Generating Nuxt.js project in ~/Projects/moments-sub
? Project name moments-sub
? Project description My tweet collection project
? Use a custom server framework express
? Use a custom UI framework bulma
? Choose rendering mode Single Page App
? Use axios module yes
? Use eslint yes
? Use prettier yes
? Author name Masataka Yoshida
? Choose a package manager yarn


プロジェクトの動作確認

作ったプロジェクトが動くか yarn dev で試してみましょう。

$ cd moments-sub

$ yarn dev
~/Projects/moments-sub/pages/index.vue
36:1 error Delete `` prettier/prettier

✖ 1 problem (1 error, 0 warnings)
1 error and 0 warnings potentially fixable with the `--fix` option.

おっと、ファイルに触れていないのにエラーが出ました🤔

ソースコードが整形された形になっていないと このエラーが出るようですが、プロジェクト開始直後から出るのはテンションが下がります。

./node_modules/.bin/eslint --fix pages/index.vue とeslintに --fix オプションを付けて実行するとこのエラーを解決してくれるそうですが、 動作を確認するときに毎回このエラーが出て --fix オプションを付けて直す…なんてやってられません。


整形に関するエラーを自動で修正する

yarn dev を実行したときに --fix オプションでeslintを走らせられるといいのですが、この方法が見つかりません。

そこで、 エディターでプロジェクト内のファイルを変更したときにこのエラーを直してもらうよう 設定しましょう。Atomの場合は次を参考にするとAtomとeslintを連携させることができます。

Atom & Vue.js & ESLint で自動整形環境構築 - Qiita

https://qiita.com/taiju59/items/326bb25814f60ecf9c3c

最後に linter-eslint パッケージの "Fix errors on save" にチェックを入れると、 上記の整形に関するエラーが自動で治ります 😃

image.png

http://localhost:3000 を開いてNuxt.jsの画面が出たら次に進みましょう😃

すこし話がそれましたが、これでNuxtの準備が整いました!


まとめたツイートを表示する画面を作る

では、ツイートを表示してみましょう。

create-nuxt-app で作ったNuxtのプロジェクトを見ると次のような構成になっています。

image.png

このNuxt.jsのプロジェクトに画面を作るには pages ディレクトリにファイルを追加しますが、 pages/index.vue を変更します。

この pages/index.vue がVue.jsの 単一ファイルコンポーネント というものです。 <style> に何も書いていませんが、HTML/JS/CSSを書いたことがあれば <template>, <script>, <style> は何を書いているかイメージしやすいですよね☺️

<template> の下にある <div> は必要です。


pages/index.vue

<template>

<div>
<h1>🐥まとめページ</h1>
<hr>
<ul>
<li> {{ tweets }}</li>
</ul>
</div>
</template>

<script>
export default {
data: function() {
return { tweets: 'ここにツイートが出たらいいなぁ' }
}
}
</script>

<style>
</style>



まとめたツイートをクライアントに送る

まとめたツイートをクライアントに送る部分を作りましょう。 まず、server ディレクトリに apiapi/tweets.js を作ります。これはまとめたツイートのデータを返す部分(API)になります。

次に同じディレクトリに datadata/tweets.json を作ります。これはまとめたツイートのデータになります。

こんな感じになります。

image.png

Twitterのツイートをみると、URLは次の形式になっています。この数値の部分がツイートのIDになるので、これを手作業で抜き出してツイートをまとめましょう。

https://twitter.com/Adobe/status/1074067849872900097

~~~~~ ~~~~~~~~~~~~~~~~~~~
@以降の名前(screen_name) ツイートのID(id, id_str)

まとめたツイートを次の形で先ほどの server/data/tweets.json に保存します。


server/data/tweets.json

{

"tweets": [
"1073763832869179392",
"1073909919839997952",
"1074076529838120960"
]
}


次に、このまとめたデータを返すAPIを作ります。 server/api/tweets.js を次の内容にします。

ここでまとめたツイートのJSONを読み込んでクライアントに送ります。


server/api/tweets.js

const express = require('express')

const router = express.Router()
var path = require('path')
var fs = require('fs')

router.get('/tweets', (req, res, next) => {
const tweetsPath = path.join(__dirname, '../data/tweets.json')
var tweetsFile = JSON.parse(fs.readFileSync(tweetsPath, 'UTF-8'))

res.header('Content-Type', 'application/json; charset=utf-8')
res.send(tweetsFile)
})

module.exports = router


APIを作ってもNuxt側は把握できないため、 server/index.js を編集して先ほどのAPIを登録します。

ファイルの中に2行を入れますが、既にコードが書かれているのと、それぞれ挿入する場所が決まっているので注意して入れます。



  1. const apiRouter = require('./api/tweets') : APIのJSを読み込みます。 require 内には index.js から見たAPIのJSまでの場所を 拡張子無しで 指定します。


  2. app.use('/api', apiRouter) : APIを登録します。 /api はクライアントから見た場所になります。


server/index.js

const express = require('express')

const consola = require('consola')
const { Nuxt, Builder } = require('nuxt')
const app = express()
const host = process.env.HOST || '127.0.0.1'
const port = process.env.PORT || 3000

const apiRouter = require('./api/tweets') // <- ここに挿入

app.set('port', port)

// Import and Set Nuxt.js options
let config = require('../nuxt.config.js')
config.dev = !(process.env.NODE_ENV === 'production')

async function start() {
app.use('/api', apiRouter) // <- ここに挿入

// Init Nuxt.js
const nuxt = new Nuxt(config)

...


APIができたら画面に出してみましょう!再び pages/index.vue を編集します。

先ほどのIDのリストが tweets になって <template> 内に入るため、リストの中身でループしています。 :key は必要です。


pages/index.vue

<template>

<div>
<h1>🐥まとめページ</h1>
<hr>
<ul
v-for="tw in tweets" :key="tw">
<li> {{ tw }}</li>
</ul>
</div>
</template>

<script>
export default {
data: function() {
return { tweets: ['ここにツイートが出たらいいなぁ'] }
},
mounted: function() {
this.$axios
.$get('/api/tweets')
.then(response => {
this.tweets = response.tweets
})
.catch(error => {
console.log(error)
})
}
}
</script>


編集後は http://localhost:3000 に接続するとツイートのIDが並ぶはずです😀

image.png


画面に送られたツイートを表示する

まだIDしか表示されていませんが……これで


  • Nuxt.jsでAPIを作って

  • そのAPIに通信して

  • まとめたツイートの情報を取得できました


このIDをツイートとして表示するのですが、便利なプラグインを使ってみましょう。

ここでは、Vueのプラグインである vue-tweet-embed を使います。

yarnを使ってプラグインを導入するので、 yarn devhttp://localhost:3000 に接続できる状態であれば Ctrl+c / Cmd+c で終了しましょう。

次に、このコマンドで vue-tweet-embed をインストールします。

$ yarn add vue-tweet-embed

インストールが終わったら pages/index.vue を編集します。

コンポーネントを追加するので、 <script> 内の importcomponents を忘れないようにしましょう。

使用方法は <Tweet :id="'692527862369357824'"></Tweet> と文字列を入れるようになっていますが、変数をセットするときは <Tweet :id="tw"/> と書くことができます。


pages/index.vue

<template>

<div>
<h1>🐥まとめページ</h1>
<hr>
<div
v-for="tw in tweets" :key="tw">
<Tweet :id="tw"/>
</div>
</div>
</template>

<script>
import Tweet from 'vue-tweet-embed/tweet'

export default {
components: {
Tweet: Tweet
},
data: function() {
return { tweets: ['ここにツイートが出たらいいなぁ'] }
},
mounted: function() {
this.$axios
.$get('/api/tweets')
.then(response => {
this.tweets = response.tweets
})
.catch(error => {
console.log(error)
})
}
}
</script>


yarn dev を実行してブラウザで確認すると、ツイートのIDが埋め込みツイートに変化しました😆

これでまとめたツイートが表示できましたね!

image.png

このままでは自分でツイートを追加したり、新しいまとめページを作るときにファイルを作って、そのファイルを指定して……とファイルが必要になってきます。


  • スマートフォンからまとめページをいじりたいですよね?

  • データベースを用意してツイートやページを追加できるようにしたいですよね?

  • Twitterのアカウントで認証したいですよね?

🔥ここでFirebaseを使います🔥


前編おわり

…………とFirebaseの導入を書きたいところですが、Firebaseの部分を書くと その部分だけで10,000文字を超えてものすごく長くなってしまうので 後編に分けます 🙇‍♂️

だっていろいろハマったんだもん

(あれ……とりあえず19日の分は書けたよね……?明日でいいよね……?🛌💤)

明日は @maemori さんです!

この記事を書いているときに、ツイートをまとめる Togetter があったのをすっかり忘れてました。


参考

Nuxt.js でバックもフロントもこれ一本 - Qiita

https://qiita.com/kawaMk4/items/298f95f751540b96d39b