はじめに - "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
2019/12/18現在の create-nuxt-app
(でプロジェクトが作成できるNode.jsの環境)には対応しません
まずは当時のNode.js 11.4.0でプロジェクトを作成しようとするとESLintが設定できなくなっています。
warning nuxt > @nuxt/webpack > @nuxt/babel-preset-app > core-js@2.6.11: core-js@<3 is no longer maintained and not recommended for usage due to the number of issues. Please, upgrade your dependencies to the actual version of core
-js@3.
error eslint@6.7.2: The engine "node" is incompatible with this module. Expected version "^8.10.0 || ^10.13.0 || >=11.10.1". Got "11.4.0"
error Found incompatible module.
次に、 create-nuxt-app
のESLintが動作できるバージョン(11.10.1)で試したところ、ツイートの埋め込みコンポーネント(tonickkozlov/vue-tweet-embed)が動作しなくなります。
import Tweet from 'vue-tweet-embed/tweet'
と呼び出す方法ではビルドができず yarn dev
ができません。
<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
},
$ yarn dev
...This dependency was not found:
- vue-tweet-embed/tweet in ./node_modules/babel-loader/lib??ref--2-0!./node_modules/vue-loader/lib??vue-loader-options!./pages/index.vue?vue&type=script&lang=js&
importするモジュールを変えた方法 では、ページを開いたときに "Unknown custom element: - did you register the component correctly?"と表示されます。
...
<script>
import Tweet from 'vue-tweet-embed'
export default {
components: {
Tweet
},
詳しい検証を進めたいところですがまだできていません🙇♂️
「NuxtとFirebaseを組み合わせてなにか作りたい」という趣旨の場合はこちらの記事をご確認ください。
Nuxt.js + Vuex + Firebase(Authentication, Cloud Firestore)でTwitterユーザー向けの伝言板を作る - Qiita
https://qiita.com/ysd_marrrr/items/cf7871e7803d7b4919f1
作ったモノ
Twitterで モーメント の機能があったのはご存じでしょうか? 使ったことないって?
モーメントはツイートを一つのページにまとめられる機能ですが、この前 スマートフォンアプリからのモーメントの作成ができなくなりました。 不便ですね。
この記事で作るのは、そんなモーメントのようにツイートをまとめるアプリを作ります 🗒
前編ではここまで作ります。このようにまとめたツイートをTwitterの埋め込み機能で表示するアプリになります。
HTMLに埋め込みタグ貼り付ければおしまいだろ
最終的には 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" にチェックを入れると、 上記の整形に関するエラーが自動で治ります 😃
http://localhost:3000
を開いてNuxt.jsの画面が出たら次に進みましょう😃
すこし話がそれましたが、これでNuxtの準備が整いました!
まとめたツイートを表示する画面を作る
では、ツイートを表示してみましょう。
create-nuxt-app
で作ったNuxtのプロジェクトを見ると次のような構成になっています。
このNuxt.jsのプロジェクトに画面を作るには pages
ディレクトリにファイルを追加しますが、 pages/index.vue
を変更します。
この pages/index.vue
がVue.jsの 単一ファイルコンポーネント というものです。 <style>
に何も書いていませんが、HTML/JS/CSSを書いたことがあれば <template>
, <script>
, <style>
は何を書いているかイメージしやすいですよね☺️
<template>
の下にある <div>
は必要です。
<template>
<div>
<h1>🐥まとめページ</h1>
<hr>
<ul>
<li> {{ tweets }}</li>
</ul>
</div>
</template>
<script>
export default {
data: function() {
return { tweets: 'ここにツイートが出たらいいなぁ' }
}
}
</script>
<style>
</style>
まとめたツイートをクライアントに送る
まとめたツイートをクライアントに送る部分を作りましょう。 まず、server
ディレクトリに api
と api/tweets.js
を作ります。これはまとめたツイートのデータを返す部分(API)になります。
次に同じディレクトリに data
と data/tweets.json
を作ります。これはまとめたツイートのデータになります。
こんな感じになります。
Twitterのツイートをみると、URLは次の形式になっています。この数値の部分がツイートのIDになるので、これを手作業で抜き出してツイートをまとめましょう。
https://twitter.com/Adobe/status/1074067849872900097
~~~~~ ~~~~~~~~~~~~~~~~~~~
@以降の名前(screen_name) ツイートのID(id, id_str)
まとめたツイートを次の形で先ほどの server/data/tweets.json
に保存します。
{
"tweets": [
"1073763832869179392",
"1073909919839997952",
"1074076529838120960"
]
}
次に、このまとめたデータを返すAPIを作ります。 server/api/tweets.js
を次の内容にします。
ここでまとめたツイートのJSONを読み込んでクライアントに送ります。
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行を入れますが、既にコードが書かれているのと、それぞれ挿入する場所が決まっているので注意して入れます。
-
const apiRouter = require('./api/tweets')
: APIのJSを読み込みます。require
内にはindex.js
から見たAPIのJSまでの場所を 拡張子無しで 指定します。 -
app.use('/api', apiRouter)
: APIを登録します。/api
はクライアントから見た場所になります。
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
は必要です。
<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が並ぶはずです😀
画面に送られたツイートを表示する
まだIDしか表示されていませんが……これで
- Nuxt.jsでAPIを作って
- そのAPIに通信して
- まとめたツイートの情報を取得できました
このIDをツイートとして表示するのですが、便利なプラグインを使ってみましょう。
ここでは、Vueのプラグインである vue-tweet-embed を使います。
yarnを使ってプラグインを導入するので、 yarn dev
で http://localhost:3000
に接続できる状態であれば Ctrl+c
/ Cmd+c
で終了しましょう。
次に、このコマンドで vue-tweet-embed をインストールします。
$ yarn add vue-tweet-embed
インストールが終わったら pages/index.vue
を編集します。
コンポーネントを追加するので、 <script>
内の import
と components
を忘れないようにしましょう。
使用方法は <Tweet :id="'692527862369357824'"></Tweet>
と文字列を入れるようになっていますが、変数をセットするときは <Tweet :id="tw"/>
と書くことができます。
<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が埋め込みツイートに変化しました😆
これでまとめたツイートが表示できましたね!
このままでは自分でツイートを追加したり、新しいまとめページを作るときにファイルを作って、そのファイルを指定して……とファイルが必要になってきます。
- スマートフォンからまとめページをいじりたいですよね?
- データベースを用意してツイートやページを追加できるようにしたいですよね?
- Twitterのアカウントで認証したいですよね?
🔥ここでFirebaseを使います🔥
前編おわり
…………とFirebaseの導入を書きたいところですが、Firebaseの部分を書くと その部分だけで10,000文字を超えてものすごく長くなってしまうので 後編に分けます 🙇♂️
だっていろいろハマったんだもん
(あれ……とりあえず19日の分は書けたよね……?明日でいいよね……?🛌💤)
明日は @maemori さんです!
この記事を書いているときに、ツイートをまとめる Togetter があったのをすっかり忘れてました。
参考
Nuxt.js でバックもフロントもこれ一本 - Qiita
https://qiita.com/kawaMk4/items/298f95f751540b96d39b