Nuxt.js + Vuetify.jsで、回文を作成して共有できるサービス「回文メーカー」を作りました。
特徴
回文メーカーでは、入力内容に応じて回文を作成することができます。
また、作成した回文をTwitterに共有することもできます。
レスポンシブデザイン
PCやスマートフォンなど、あらゆるデバイスで違和感のないレスポンシブデザインです。
PWA対応
PWA対応なので、iPhoneやAndroidではアプリとしても使えます。
Nuxt.js + Vuetify.jsという選択
今回は、Nuxt.jsとVuetify.jsという二つのフレームワークを使用しました。
Nuxt.jsという選択
Nuxt.jsは、ウェブサイトのインターフェースを構築するためのJavaScriptフレームワークであるVue.jsに、いくつかのライブラリを組み込んだフレームワークです。
Vue.js自体も魅力的なフレームワークですが、Nuxt.jsにはより強力な機能が備わっています。
回文メーカーはページが一つしかない小規模なアプリケーションですが、Nuxt.jsの恩恵をおおいに受けています。
Vuetify.jsという選択
Vuetify.jsは、マテリアルデザインに準拠したVue.js用のUIフレームワークです。
Vue.js用のUIフレームワークは他にもたくさんありますが、僕はタグ名がイケてる(<v-btn>
のようにv-
が接頭辞になっている)のでVuetify.jsが気に入っています。
Vuetify.jsはウェブ上に日本語の情報があまりなかったのですが、最近は導入事例や紹介記事も増えてきて人気の高まりを感じています。1
やったこと
ドメインを取得
munieru.jpドメインのホスティングでもお世話になっているスタードメインで、kaibunmaker.com
ドメインを取得しました。
これにより、将来的にホスティングサイトを切り替えた場合も同じドメインで運用し続けることが可能です。
早くもGitHub Pagesのデプロイフローにつらみを感じているので、早々にNetlifyに移行するかもしれません。
その後、Netlifyに移行しました。
Twitterのアカウントを取得
念のため、Twitterの@kaibunmakerアカウントを取得しました。
なりすまし防止の観点で一応押さえているだけなので、特にツイートはしていません。
アプリケーションの環境構築
アプリケーションを実装するための基盤となる環境作りです。
アプリケーションの雛形を生成
はじめに、create-nuxt-appを用いてアプリケーションの雛形を生成しました。2
$ npx create-nuxt-app kaibunmaker
プロジェクトの設定は以下の通りです。
- Project name:
kaibunmaker
- Project description:
Palindrome maker
- Use a custom server framework:
none
- Use a custom UI framework:
vuetify
- Choose rendering mode:
Single Page App
- Use axios module:
no
- Use eslint:
yes
- Use prettier:
no
- Author name:
Munieru
- Choose a package manager:
npm
次に、不要なページやコンポーネントを削除しました。3
この時点で、layouts/default.vue
とpages/index.vue
は以下のような状態です。
<template>
<v-app>
<v-content>
<v-container>
<nuxt />
</v-container>
</v-content>
</v-app>
</template>
<template>
<v-layout>
<v-flex>
<span>Hello World</span>
</v-flex>
</v-layout>
</template>
こうすることで、その後ページを作っていく際にコミットの差分が綺麗になります(本当は<span>Hello World</span>
すらないほうがいいです)。
参考:Nuxt.jsのプロジェクトにVuetify.jsを導入する方法 - Qiita
JavaScript Standard Styleを導入
僕はJavaScript Standard Styleが好きなので、JavaScript Standard Styleを導入しました。4
参考:Nuxt.jsのプロジェクトにESLint + JavaScript Standard Styleを導入する方法 - Qiita
Sassを導入
素のCSSでスタイルを書くのはつらいので、CSSのメタ言語であるSassを導入しました。5
使用する言語ぐらいは、create-nuxt-appのオプションで選べるようにしてほしいところです。
参考:Nuxt.jsのプロジェクトにSassを導入する方法 - Qiita
stylelintを導入
CSSやSassの構文をチェックするために、stylelintを導入しました。6
こちらも、ESLintやPrettierと同様にcreate-nuxt-appのオプションで選べるようにしてほしいところです。
参考:Nuxt.jsのプロジェクトにstylelintを導入する方法 - Qiita
nuxt-i18nを導入
アプリケーションで使用するテキストをソースコードから分離するために、nuxt-i18nを導入しました。7
nuxt-i18nはその名の通りi18nのためのライブラリですが、一つの言語にしか対応しない場合も有用です。
たとえば言語ファイルにアプリ名を定義しておけば、後からアプリ名を変更したい場合にソースコードのあちこちにあるアプリ名を書き換えなくとも、言語ファイルを更新するだけで済みます。
フォントを追加
タイトルロゴは明朝体(Noto Serif)、それ以外はゴシック体(Noto Sans)を使用しています。
游書体にしようか悩みましたが、マテリアルデザインとの親和性を考えてNotoにしました。
Font Awesomeは、ツイートボタンでTwitterのアイコンを使用するためだけに追加しています。
アプリケーションを実装
リリース日まで時間もなかったので、最悪途中の状態でリリースできるように重要度の高いものから実装していきました。
回文を作成する機能を実装
最初は回文を共有する機能を抜きにして、回文を作成する機能のみを実装しました。
フォームの値を元に回文を生成する処理は、以下のような関数によって実現しています。
import reverseString from '~/modules/reverseString'
export default function (text, repeat) {
const reversedText = reverseString(text)
return repeat ? `${text}${reversedText}` : `${text.substring(0, text.length - 1)}${reversedText}`
}
「最後の文字を繰り返す」がオフの場合は、ダブらないように最後の文字を削っています。
回文を共有する機能を実装
回文メーカーは静的サイトであり、データベースを持っていません(「DBレスアーキテクチャ」とか言っておきます)。
作成した回文を共有するための仕組みとして、URLのパラメーターにstatus=とまと
のように回文を含めることで、フォームに値が入力された状態で表示するようにしています。
URLのパラメーターを元にフォームの値を生成する処理は、Nuxt.jsのasyncData
メソッド内と、vue-routerのbeforeRouteUpdate
メソッド内で行なっています。
export default {
// (省略)
async asyncData ({ query }) {
return createFormData(query.status)
},
beforeRouteUpdate (to, from, next) {
const { text, repeat } = createFormData(to.query.status)
this.text = text
this.repeat = repeat
next()
}
}
こうすることで、初回アクセス時とページ遷移時の両方でフォームの値を更新することができます。
レスポンシブデザインの最適化
ブロック要素や画像はVuetify.jsのコンポーネントを使用すればいい感じにレスポンシブにしてくれるのですが、テキストについてはその限りではありません。
タイトルロゴのフォントサイズを以下のように指定することで、ビューポートの横幅に応じて文字サイズが適切に変化するようにしました。
$relative-max-width: 600px;
$relative-font-size: 14vw;
$absolute-font-size: 84px;
.app-title {
font-family: "Noto Serif JP", serif;
font-size: $absolute-font-size;
a {
color: inherit;
text-decoration: inherit;
}
}
@media (max-width: $relative-max-width) {
.app-title {
font-size: $relative-font-size;
}
}
14vw
というのは「ビューポートの横幅の14%」という意味で、横幅が600px
未満の場合は1文字をビューポートの横幅の14%で表示し、横幅が600px
以上の場合は84px
で表示するようにしています。
アイコンを作成
最近流行りのSketchで、アプリケーションのアイコンを作成しました。
色とフォントを実際のアプリケーションに合わせつつ、円形にトリミングしても文字部分が欠けないようにサイズを調整しました。
OGP対応
TwitterやFacebookなどのサイト上でリッチな表示をするために、OGPに対応しました。11
OGPタグではURLを絶対URLで記述する必要があるため、アプリケーション独自のconfig.json
ファイルでデプロイ先のオリジンやベースディレクトリを指定するようにしています。
{
"BASE_DIR": "/",
"TWITTER_ID": "@munieru_jp",
"OG_IMAGE_PATH": "favicon-256x256.png",
"ORIGIN": "http://localhost:3000/"
}
こうすることで、以下のように環境に応じてベースURLを変えることができます(環境変数を使用していないのは、毎回指定するのが面倒だからです)。
環境 | ベースURL |
---|---|
ローカル | http://localhost:3000/ |
GitHub Pages | https://munierujp.github.io/kaibunmaker/ |
独自ドメイン | https://kaibunmaker.com/ |
PWA対応
せっっかくなので、PWAにも対応しました。12
Nuxt.jsでPWAに対応するには、公式のPWAモジュールを使うのが便利です。
注意点としては、デフォルトではアプリケーション名や作者名などのメタ情報はpackage.json
に記載されているものが使われるので、変更したい場合はnuxt.config.js
ファイルに項目を追加する必要があります。
// (省略)
module.exports = {
// (省略)
manifest: {
name: APP_NAME,
short_name: APP_NAME,
description: APP_DESCRIPTION,
lang: DEFAULT_LOCALE
},
meta: {
author: TWITTER_ID
}
}
Googleアナリティクスを導入
アクセス解析をするために、Googleアナリティクスを導入しました。13
Nuxt.jsでGoogleアナリティクスを使用するには、公式のGoogleアナリティクスモジュールを使うのが便利です。
参考:Google アナリティクスの統合 - Nuxt.js
所感
締め切り駆動開発はつらい
今回、リリース日を回文の日である12月21日に決めてしまったので、プライベート開発にも関わらず締め切りが明確に定められているのがきつかったです。
偶然にも12月18日に仕事でサービスリリースのための深夜作業があったので、その前後はあまり開発に時間を費やすことができず、リリース前日はネットカフェで終電ギリギリまでデバッグ作業をしていました。
Nuxt.jsはいいぞ
たいていのことはモジュールを使用すれば実現できるので、本質的な部分の開発に注力することができます。
僕自身もnuxt-onsenui-moduleというモジュールを作って公開しているので、次はOnsen UIを使って何かを作ってみたいですね。
ソースコード
回文メーカーのソースコードは、GitHubで公開しています。
関連記事
-
Vueでもっと幸せになりたいあなたへ。VueのUIコンポーネントライブラリVuetifyのススメ - KAYAC engineers' blog ↩
-
Create project by create-nuxt-app · munierujp/kaibunmaker@3ac3935 ↩
-
Use JavaScript Standard Style by munierujp · Pull Request #2 · munierujp/kaibunmaker ↩
-
Use Sass by munierujp · Pull Request #5 · munierujp/kaibunmaker ↩
-
Use stylelint by munierujp · Pull Request #6 · munierujp/kaibunmaker ↩
-
Use nuxt-i18n by munierujp · Pull Request #8 · munierujp/kaibunmaker ↩
-
Add Noto Sans JP font by munierujp · Pull Request #12 · munierujp/kaibunmaker ↩
-
Add Noto Serif JP font by munierujp · Pull Request #13 · munierujp/kaibunmaker ↩
-
Add Font Awesome 5 by munierujp · Pull Request #14 · munierujp/kaibunmaker ↩
-
Add OGP/Twitter Cards by munierujp · Pull Request #16 · munierujp/kaibunmaker ↩
-
Apply PWA by munierujp · Pull Request #19 · munierujp/kaibunmaker ↩
-
Add Google Analytics by munierujp · Pull Request #18 · munierujp/kaibunmaker ↩