21
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Nuxt.jsAdvent Calendar 2018

Day 24

Nuxt.js + Vuetify.jsで回文を作成して共有できるサービス「回文メーカー」を作った

Last updated at Posted at 2018-12-24

Nuxt.js + Vuetify.jsで、回文を作成して共有できるサービス「回文メーカー」を作りました。

特徴

回文メーカーでは、入力内容に応じて回文を作成することができます。
また、作成した回文をTwitterに共有することもできます。

レスポンシブデザイン

6b3195a1-9c90-b8ba-31f0-c1b1a908099a.gif

PCやスマートフォンなど、あらゆるデバイスで違和感のないレスポンシブデザインです。

PWA対応

PWA対応なので、iPhoneやAndroidではアプリとしても使えます。

Nuxt.js + Vuetify.jsという選択

今回は、Nuxt.jsVuetify.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.vuepages/index.vueは以下のような状態です。

layouts/default.vue
<template>
  <v-app>
    <v-content>
      <v-container>
        <nuxt />
      </v-container>
    </v-content>
  </v-app>
</template>
pages/index.vue
<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のためのライブラリですが、一つの言語にしか対応しない場合も有用です。
たとえば言語ファイルにアプリ名を定義しておけば、後からアプリ名を変更したい場合にソースコードのあちこちにあるアプリ名を書き換えなくとも、言語ファイルを更新するだけで済みます。

フォントを追加

アプリケーションで使用するフォントを追加しました。8910

タイトルロゴは明朝体(Noto Serif)、それ以外はゴシック体(Noto Sans)を使用しています。
游書体にしようか悩みましたが、マテリアルデザインとの親和性を考えてNotoにしました。
Font Awesomeは、ツイートボタンでTwitterのアイコンを使用するためだけに追加しています。

アプリケーションを実装

リリース日まで時間もなかったので、最悪途中の状態でリリースできるように重要度の高いものから実装していきました。

回文を作成する機能を実装

最初は回文を共有する機能を抜きにして、回文を作成する機能のみを実装しました。
フォームの値を元に回文を生成する処理は、以下のような関数によって実現しています。

createPalindrome.js
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で、アプリケーションのアイコンを作成しました。

132608/2e8c16c8-68c4-a58a-8d82-98097e74a339.png

色とフォントを実際のアプリケーションに合わせつつ、円形にトリミングしても文字部分が欠けないようにサイズを調整しました。

OGP対応

TwitterやFacebookなどのサイト上でリッチな表示をするために、OGPに対応しました。11
OGPタグではURLを絶対URLで記述する必要があるため、アプリケーション独自のconfig.jsonファイルでデプロイ先のオリジンやベースディレクトリを指定するようにしています。

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ファイルに項目を追加する必要があります。

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で公開しています。

関連記事

  1. Vueでもっと幸せになりたいあなたへ。VueのUIコンポーネントライブラリVuetifyのススメ - KAYAC engineers' blog

  2. Create project by create-nuxt-app · munierujp/kaibunmaker@3ac3935

  3. Clean pages · munierujp/kaibunmaker@fb8ddc5

  4. Use JavaScript Standard Style by munierujp · Pull Request #2 · munierujp/kaibunmaker

  5. Use Sass by munierujp · Pull Request #5 · munierujp/kaibunmaker

  6. Use stylelint by munierujp · Pull Request #6 · munierujp/kaibunmaker

  7. Use nuxt-i18n by munierujp · Pull Request #8 · munierujp/kaibunmaker

  8. Add Noto Sans JP font by munierujp · Pull Request #12 · munierujp/kaibunmaker

  9. Add Noto Serif JP font by munierujp · Pull Request #13 · munierujp/kaibunmaker

  10. Add Font Awesome 5 by munierujp · Pull Request #14 · munierujp/kaibunmaker

  11. Add OGP/Twitter Cards by munierujp · Pull Request #16 · munierujp/kaibunmaker

  12. Apply PWA by munierujp · Pull Request #19 · munierujp/kaibunmaker

  13. Add Google Analytics by munierujp · Pull Request #18 · munierujp/kaibunmaker

21
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?