Nuxt.jsの基礎勉強-firebaseと連携したToDoアプリ1-
はじめに
今回はグーグルが運営しているデータベースであるfirebaseとNuxt.jsのアプリケーションを連携させることを勉強した。 長くなると思うので記事を2つに分けて投稿します。
firebaseの環境設定
firebaseでプロジェクトを作成
- firebaseでアカウント登録をしてCloud Firestore のデータベースをテストモードでプロジェクトを作成する。
- 設定からプロジェクトIDを取得する。
firebaseとvuexfireと@nuxtjs/dotenvをインストール
$ npm install --save firebase $ npm install --save vuexfire $ npm install --save @nuxtjs/dotenv
- 上記をインスコしたら
package.json
を開いてdependencies
に上記全部が記述されていることを確認する。
~/plugins/firebase.js
にfirebaseをimportする
import firebase from 'firebase' const config ={ projectId: process.env.FIREBASE_PROJECT_ID } if(!firebase.apps.length){ firebase.initializeApp(config) } export default firebase
@nuxtjs/dotenvを利用して環境変数を使用する
- @nuxtjs/dotenvを有効化するために
nuxt.config.js
のmodules部分に以下を記述
/* ** Nuxt.js modules */ modules: [ '@nuxtjs/dotenv' ],
~/.env
を作成
FIREBASE_PROJECT_ID = 'Your firebase project id'
~/.gitignore
にて~/.env
を記述
.env
storeの設計
vuexfireの設定
- vuexfire#usageにも記述されているがvuexfireは
~/store/index.js
にてmutationsを作る必要があるので~/store/index.js
に以下を記述
import { vuexfireMutations } from 'vuexfire' export const mutations = { ...vuexfireMutations }
todos.jsにてfirebaseとvuexfireを取得して使う
- pluginからfirebaseをimport
- 同じくvuexfireもimport
- firebaseをdbに格納 (今回はfirestoreを用いたからこの綴りになる)
- 初期化したfirebaseにvuex内のデータであるtodosを格納
- firebaseに渡す値todosを定義
- vuexfireのusageにもある通りにActionを記述
init:
でfirebaseを初期化add:
で入力値がある場合にtodosRefに夫々の値を格納している
import firebase from '~/plugins/firebase' import { firestoreAction } from 'vuexfire' const db = firebase.firestore() const todosRef = db.collection('todos') export const state = () => ({ todos: [] }) export const actions = { init: firestoreAction(({bindFirestoreRef}) => { bindFirestoreRef('todos', todosRef) }), add: firestoreAction((context, name) => { if(name.trim()){ todosRef.add({ name: name, done: false, created: firebase.firestore.FieldValue.serverTimestamp() }) } }), (以下略)
~/page/todos.vue
に入力フォームの作成
textareaのフォームを作成して、submitを用いてデータの送信をサーバーに送る機能を作成。
- template部分の記述
<template> <div class="form"> <form v-on:submit.prevent="add"> <input v-model="name"> <button>Add</button> </form> </div> </template>
- script部分の記述
export default { data: function(){ return { name: '', done: false } }, created: function(){ this.$store.dispatch('todos/init') }, methods: { add(){ this.$store.dispatch('todos/add', this.name) this.name = '' },
終わりに
抜けが無ければ上記まででfirebaseに入力したテキストデータとサーバーのタイムスタンプとfalseの値を投げるプログラムになる。
このコードは写経しながら書いたコードだったが後から読みながら公式ドキュメントを追ったりすることで、書いたコードの意味や作業の確認ができてよかったと思う。
次回はこのプログラムの続きを上げていきます。
Nuxt.jsの基礎勉強-カウンターアプリを作成-
はじめに
今回はカウンターアプリを作ることでvuexの知識を整理をした。
カウンターアプリの実装
storeの作成
- モジュールモードを用いてストアを設計
- stateにはデータの初期状態を記述
- mutationsにデータの操作を記述
- actionsにmutationの読み込み操作を記述
export const state = () =>({ count: 0 }) export const mutations = { countUp: function(state, payload){ state.count += payload }, resetCount: function(state, payload){ state.count = payload } } export const actions = { countUpAction: function(state, payload){ state.commit('countUp', payload) }, resetCountAction: function(state, payload){ state.commit('resetCount', payload) } }
コンポーネントでカウンターアプリを作成
- 今回はアクションを介してミューテーションからストアの操作を行なったので、
dispatch
を使ってデータの送信をActionに送る。
<template> <section class="container"> <p> {{ $store.state.counter.count }} <button @click="$store.dispatch('counter/countUpAction', 1)">+1</button> <button @click="$store.dispatch('counter/resetCountAction', 0)">reset</button> </p> </section> </template>
ページでコンポーネントを表示
<template> <section class="container"> <counter /> <page /> </section> </template> <script> import counter from '~/components/counter.vue' import page from '~/components/page.vue' export default { components: { counter, page } } </script>
終わりに
実際に自ら考えて作ってみることで、storeやcomponentsの記述の仕方を再学習するいい機会になった。
Nuxt.jsの基礎勉強-vuexの使い方について-
はじめに
今回はvuexを用いたデータの扱いについて学習したので纏めておく。
- 前回同様に以下のリポジトリに扱ったソースコードを公開します。 github.com
vuexとは
vue.jsを用いたアプリケーションで扱うデータの状態管理を行うツールのことです。
vuexを用いたデータを呼び出し
~/store/index.js
というファイルを作成し、vuexをimportして扱えるようにする。その後以下のように記述することで扱うことができる。
import Vuex from 'vuex' const createStore = () => { return new Vuex.Store({ state: function(){ return{ message: 'Hello Vuex' } } }) } export default createStore
上記で定義したデータを呼び出すにはコンポーネントにて$store
を呼び出すことで出力することができる。
<template> <section class="container"> <div> <p>{{ $store.state.message }}</p> </div> </section> </template>
ミューテーションを用いたデータ操作
vuexを用いたデータの状態管理ではview側から直接的なデータ操作を行わずにミューテーションを介したデータ操作をする必要がある。
その理由として、データ管理を行う上でview側からの予期しない操作の防止やデータのバグが何処からきているのかを明確にし、アプリケーションのメンテナンス性向上に貢献することがあげられます。
基本的なmutation構文
基本的な記述の仕方は~/store/index.js
内にmutations
を作ってその中に処理を記述します。
return new Vuex.Store({ state: function(){ (略) }, mutations: { updateMessage: function(state){ state.message = 'Update Message' } } })
呼び出しは$store.commit('呼び出すミューテーション')
<p v-on:click="$store.commit('updateMessage')"> {{ $store.state.message }} </p>
mutationの値渡し
~/store/index.js
側では第二引数を設定することで外部から値を受け取ることができる。
mutations: { payloadMessage: function(state, payload){ state.message = payload } }
コンポーネント側では第二引数として渡したい値を記述します。
<p v-on:click="$store.commit('payloadMessage', 'this is payload')"> {{ $store.state.message }} </p>
actionを介したmutationの扱い方
~/store/index.js
側でactionを定義し、action側からミューテーションを呼び出すように記述します。
mutations: { payloadMessage: function(state, payload){ state.message = payload } }, actions: { payloadMessageAction(context, payload){ context.commit('payloadMessage', payload) } }
コンポーネント側ではdispatch関数を用いて、第一引数を呼び出すアクション名にし、第二引数を渡したい値とすることで記述できます。
<p v-on:click="$store.dispatch('payloadMessageAction', 'this is dispatch')"> {{ $store.state.message }} </p>
モジュールモードでの開発について
今までの記述の仕方はクラシックモードといって~/store/index.js
内に一括管理する方法です。しかし、大規模アプリを作成する場合だと一括管理した場合、storeの記述が肥大化し管理が難しくなる可能性があります。
そこで、複数のファイルでstoreの管理を行うモジュールモードの記述をここでは記述していきます。
今までのコードをモジュールモードへ
モジュールモードで管理する場合は~/store/index.js
を作成せずにその他の名前でファイルを作成することで出来ます。
今回は~/store/hello.js
という風にファイルを作成し、以下のように各状態を関数型で定義していくことで、クラシックモードからモジュールモードに書き換えが完了します。
export const state = () => ({ message: 'Hello Vuex' }) export const mutations = { updateMessage: function(state){ state.message = 'Update Message' }, payloadMessage: function(state, payload){ state.message = payload } } export const actions = { payloadMessageAction(context, payload){ context.commit('payloadMessage', payload) } }
呼び出すときは、storeのモジュール名をコンポーネント内に表記することで出力することができます。
<p v-on:click="$store.commit('hello/updateMessage')"> {{ $store.state.hello.message }} </p> <p v-on:click="$store.commit('hello/payloadMessage', 'this is payload')"> {{ $store.state.hello.message }} </p> <p v-on:click="$store.dispatch('hello/payloadMessageAction', 'this is dispatch')"> {{ $store.state.hello.message }} </p>
終わりに
今回は実際にvuexを触ることで、vuexを用いた状態管理の大まかな概要を学ぶことができた。
Nuxt.jsの基礎勉強-ファイル構造の理解を深める-
はじめに
前回Nuxt.jsを勉強した際にはファイル構造や知識の追加だけだったので今回は実際に動かしてみたので行なったことについて纏めていく。
今回勉強した内容は以下のリポジトリにあげております。 github.com
componentsとpageについて
この二つがMVCのVに相当する部分になり、コンポーネントと各ページの出力を担うvueファイルを夫々纏めて管理することができる。
- componenntsの基本構文は以下のように記述する
<template> <div class="Hello"> Hello Nuxt.js </div> </template> <script> export default { } </script>> <style> .Hello { color: brown; } </style>
- 上記を読み込んで使う場合はpage側でコンポーネントをimportして使う
<template> <section> <hello /> </section> </template> <script> import hello from '~/components/hello.vue' export default { components: { hello } } </script>
このように記述することで、ページ内にhelloコンポーネント内の記述がpage側で処理されてHello Nuxt.js
を出力することができる。
デフォルトのページデザインを弄る
layoutsについて
layouts/default.vue
内のコードを弄ることでデフォルトのデザインを変えることができます。
<template> <div> <div class="header"> <h1 class="header">This is First Nuxt.js</h1> </div> <Nuxt /> </div> </template> <style> .header{ color: #fff; background-color: black; } ~略~
上記のように記述することでヘッダーを全てのページのデフォルトとして付け足すことができる。
<Nuxt />
が各ルートで呼ばれるページを出力する場所なので、これを消すと各ページの中身が消えてしまうので注意が必要。
nuxt.config.js
ここではアプリ内に使う外部ツール等の設定やHTMLの<head>
記述を纏めています。公式参照
今回はテスト的にGoogle Fontsを使うようにコードを記述してみます。
- nuxt.config.js
head: { ~中略~ link: [ { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }, { rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Sriracha&display=swap'} ] },
- layouts/default.vue
html { font-family: 'Sriracha', cursive; ~中略~ }
とすることで、デフォルトのフォントが変更される。
アプリのルートについて
ルート割り当てについて
アプリのルートは~/page/
に入っているvueファイルの名前によって自動的に作られ、同名のvueファイルと関連付けがされます。
- 例1)
~/page/index.vue
とすると/
が自動的に作られる - 例2)
~/page/second-page
とするとsecond-page
が割り当てられる
同様に階層を深くしたりしても自動的にその階層をルートとして割り当ててくれる。
ページ遷移について
Nuxt.jsではvue-router
を用いてページ遷移を行うので<router-link>タグを使うことで遷移ボタンを作成できる。
<template> <section> <router-link to="/">Top</router-link> <router-link to="second-page">second-page</router-link> </section> </template>>
assetsについて
ここに画像ファイル等を置くことで管理しやすくしている。
終わりに
今回は以前勉強したディレクトリ構造からより理解を深めるために練習用のプロジェクトを作って使ってみることでNuxt.jsの概要をつかむことができたと思う。
次回はvuexを用いたデータ操作について勉強しようと思う。
環境変数をHerokuに設定した話
はじめに
前回の記事でAPIの変更を行なったRailsアプリがHerokuではerror
を出していたので、それについて問題解決をしてRailsアプリを動く状態にした。
daily-weather-app.herokuapp.com
status=500 errorについて
ローカルではしっかり動いたrailsアプリがHerokuにあげて動作させるとエラーを出したのでサーバーログを見ることに。
$heroku logs --tail
サーバーのログをみながらアプリの方を動かしていたら検索ボタンを押してAPIリクエストをするタイミングでステータス500エラーが出ていることに気づいた。 ここから考えられるエラーの理由は私の中では以下の3パターンです。
データベース関連の問題について
データベース関連の問題については私の場合、アプリ側でデータを追加する操作をしていないためサーバー側に重要なデータがないので、全てリセットして再構築することにしました。
ENVを用いた環境変数がHeroku側でうまく適応できていない
データベース関連については片づいたはずなのにうまく起動しなかったため更にステータス500のみのエラーログについて考えることにしました。
ステータス500エラーというのは、"サーバー側のプログラムが実行できているがアクセスに失敗している状態"の事で、それについて思い当たる節を考えていった結果、環境変数をENVで定義している事でした。
なのでHeroku側にも環境変数を登録してあげれば動くのではないかと考え設定しみました。
- Herokuサイトで該当アプリのプロフィールを見る
- settingのConfig Varsを開くと登録できる
設定すると無事動きました。
参考サイト - Herokuで本番環境の環境変数(config vars)を.envファイルで設定する
終わりに
ENVを使った影響で本番環境が動いていないということに気づくまで結構長い時間詰んでたので、うまく動いてくれて安心しています。
Railsで作った天気アプリのAPIを変更した話
はじめに
今回はRailsで作った天気アプリで使っていたlivedoor さんの天気APIがサービス終了していたので、APIの取得先をopenweathermapさんに変更することにした。
openweathermapの利用登録
- openweathermapさんにてアカウント登録をする
- メールが届くのでリンクを踏んでアカウントの有効化
- メール宛にAPIキーが届きます(確かサイト内の自身プロフィールでも確認できます)
- APIキーが届いたら有効化されるまでにタイムラグがあるので待ちます
データの状態
こちらの記事がわかりやすかったのでここを参考にデータをいじってみた。
5日間天気予報(Call 5 day / 3 hour forecast data)の値一覧
require "net/http" require "uri" require "json" API_KEY = "YOUR_KEY" id = 1856035 uri = URI.parse("http://api.openweathermap.org/data/2.5/forecast?id=#{id}&appid=#{API_KEY}") json = Net::HTTP.get(uri) result = JSON.parse(json) p result["city"]["name"] p Time.at(result["list"][0]["dt"]) p Time.at(result["list"][8]["dt"])
上記コードのログ
"Tokyo" 2020-08-10 18:00:00 +0900 2020-08-11 18:00:00 +0900
RailsアプリでAPI取得を変更
元々あったAPIから得たjsonのデータ構造や名前などの違いを先ほど作ったコードで生のデータをいじりながら欲しいデータを取得できるように記述を変更していく。
seedデータを変更
アプリの使用上データベースに検索に用いるid
を登録しているため、以前の仕様のままのデータベースを新しい仕様のデータベースに変更する。
seed内のコードを書き換えたらテーブルを一新してシード値を埋め込みました。
$rails db:migrate:reset $rails db:migrate $rails db:seed
I18nで日本語表示にする
生データのままだと英語で天気情報が返ってきたので、I18nを用いて得られた生データを日本語表示にして出力する様にした。
背景を変更
生データの使用上背景を変更するプログラムが正常に動作しなかったためapp/view/weather/_template.html.erb
内の記述を変更
gitにあげる前にAPI_KEYを隠す
gitにあげる前にAPI_KEYを隠す必要があったので、dotenv-rails
を使用した。
Gemfileに
gem 'dotenv-rails'
を追加して$bundle install
する。~/.envファイルにAPI_KEYを記述
WEATHER_API_KEY=YOUR_API_KEY
- ~/.gitignoreに.envファイルを弾く様に記述
.env
終わりに
今回はやることが多かったので、その中でも大まかな流れだけを説明しました。
APIに依存するアプリケーションのメンテナンスの大変さを身にしみて感じる機会になった。
Nuxt.jsの基礎勉強~ create-nuxt-appでプロジェクトの作成やファイル構造~
はじめに
今回はVue.jsのステップアップとしてNuxt.jsの勉強を行なったので、それについてまとめていこうと思う。
npmのinstall
npmが入ってなかったのでnpmの環境設定をした。(詳しくは以下の記事に記載しました) - npxコマンドを使うためにNode.jsをインストールした話
create-nuxt-app
を用いたプロジェクトの作成
新規プロジェクトを立ち上げる時の質問
質問 | 意味 |
---|---|
Project name | 今回作るプロジェクト名-基本そのままでいい- |
Programming language: | 扱う言語-JavaScriptを選択- |
Package manager: | 扱うパッケージ-今回はnpmを選択- |
UI framework: | 扱うUI フレームワーク -今回はnone- |
Nuxt.js modules: | 扱うモジュール -今回はaxios- |
Linting tools: | コードチェックするためにEsLintを指定 |
Testing framework: | テストに扱うフレームワークを指定 |
Rendering mode: | レンダリングモードの選択-Vue.jsやNuxt.jsのみで作る予定ならUniversal- |
Deployment target: | デプロイする環境を設定 |
Development tools: | 開発に使うツールを設定 |
ファイル構造
大まかなファイル構造以下の様なっている。特に重要だと思うディレクトリについては別途説明する。
. ├── README.md ├── assets ├── components ├── layouts ├── middleware ├── node_modules ├── nuxt.config.js ├── package-lock.json ├── package.json ├── pages ├── plugins ├── static └── store
assets
components
componentを書いたファイルを管理するディレクトリ
pages
viewを作るファイルを保管する場所で、ここで作ったファイルによってパスが自動に生成される。
例) index.vue
だと /
のページのviewに該当し、hoge.vue
だと./hoge
に該当する
plugins
外部からインストールしたプラグインを管理しておくディレクトリ
store
vuex
を用いてデータ操作を行う場合の操作を記述するソースを管理しておくディレクトリ
終わりに
今回はNuxt.jsのディレクトリ構造について勉強したので、次回からは実際に触っていこうと思う。