clover.blue

Nuxtで初めるWEBアプリ開発(SSR&SPA)

Data
2019/10/08
Tag

Nuxt使ってサイトをリニューアルしたので色々まとめていきます。
使い方などは公式サイトが充実しているのでほかサイトでも説明があるため
Nuxtについてはサラッと流して困ったポイントをまとめていきます。

clover.blue

Nuxtって何?

Vueを使って、最初の設定周りすっとばして開発が初めれる便利ツールです。

Vue単体でも、webpackとかあまり気にせず作れますが
さらに + でrouterやvuexも最初から揃っているのでそれほど気にせずに作れちゃうところが良いなと思いました。

使ってみて

もう個人的には 静的ページSSPSSR どれで開発するときもNuxtを使えばいいのではと思いました。
公式もかなり充実してるので、困ることがすくないのもよいところです。

はじめる

公式が充実してるので下記から、そのまま順番通りに進めていけば特に詰まることなく初められると思います。

リニューアルにあたっての構成

下記のような構成ではじめました。

npx create-nuxt-app <project-name>

Choose the package manager * Yarn
Choose UI framework * None
Choose custom server framework * Express
Choose Nuxt.js modules * Axios, PWA
Choose linting tools * ESLint, Prettier, Lint staged files
Choose test framework * Jest
Choose rendering mode * Universal (SSR)

Nuxtのディレクトリ構造について

ディレクトリ構造には意味があり下記に詳しく書いてあります。
* ディレクトリ構造 - Nuxt.js

開発を初める

とりあえず起動してみる

yarn dev

http://localhost:3000を開くとdemoが表示されます。

個人的にport3000が、他の開発と被る可能性があるため変えるようにしています。
nuxt.config.jsに下記を追加しました。

server: {
  port: process.env.PORT || 1341
}

process.env.PORTはherokuやGoogle App Engineなどにdeployする際に環境変数として定義されているので指定しています。
今回リニューアルにあたりGoogle App Engineを使っています。

タイトルをページごとに変更したい

下記を参考にして設定しました。
* Nuxt.js で動的タイトル設定
* nuxtでtitleタグを動的に設定する

apiを作りたい

Expressが入っているため、nuxt.config.jsにserverMiddleware記述して
vueのrouterから外して、apiを定義することができるようになります。
下記を参考にしました。

サーバー側もes6で書きたい

babel-nodeで実行しようと思ったのですがGAEではうまく実行できませんでした。
babel-nodeは本番での使用は推奨されていないようなので、一度変換してから実行するようにしました。
https://babeljs.io/docs/en/babel-node

es6でかけるようにpackage.jsonを変更する

dev環境では変換する必要がないため。babel-nodeをそのまま使っています.
本番環境ではbuild:serverを実行することで一度server_distに変換します。
startのserver/index.jsnode server_dist/index.jsに変更し。babelで変換したファイルを使うようにしました。

"dev": "cross-env NODE_ENV=development nodemon --exec babel-node server/index.js --watch server",
"start": "cross-env NODE_ENV=production node server_dist/index.js",
"build:server": "babel server/ -d server_dist",

旧アドレスからリダイレクトさせたい

旧サイトはwww付きだったため。リダイレクトさせる必要がありました。
最初はGAEからリダイレクトさせる方法を考えていたのですが下記方法で実現しました。

https://github.com/nuxt/nuxt.js/issues/1843#issuecomment-360416960

middlewareに下記ファイルを置きwwwRedirect.jsを用意しました。

export default function(data) {
  const isWww = data.req && ~data.req.headers.host.indexOf('www')
  if (isWww) {
    data.redirect('301', `${process.env.HOST}${data.route.fullPath}`)
  }
}

そしてnuxt.configt.jsに書きを追加しました。

router: {
  middleware: ['wwwRedirect']
},

JSON-LDを管理

下記に詳しく書いてくれていますので参考にしました。

nuxt-jsonldというプラグインも作ってくれているので。使わせていただきました。
https://www.npmjs.com/package/nuxt-jsonld

ただ。。あまり検証進められていないのですが。少し重くなる原因になっているのではと感じています。
リンクをするたびに動作が重くなっているように感じているので。時間があれば原因調べたいなと思っています。
濡れ衣だったらすみません。m(_ _)m

こちら、1.4.4のバージョンで確認したところ問題なさそうです!
作者さんありがとうございます!

GTMを使ってみる

下記プラグインを使うことで簡単に導入できます。

https://github.com/nuxt-community/modules/tree/master/packages/google-tag-manager

GTM側の設定

ページビューでアナリティクスを設定しようとしたのですがSPA,SSRだとリンクをした際に計測されませんでした。
上記プラグインですとnuxtRouteでイベントを発火してくれているため。
トリガをnuxtRouteにすることで遷移のタイミングで発火することができます。

Postcssを導入する

いままで個別で入れたりprecssを入れたりしていたのですが。
postcss-preset-envを使っていくのが良いかなと思ってます。

Mockを導入する

ネット環境がなくても開発が行えるようにaxios-mock-serverを使ってmockを用意することにしました。
下記に@nuxtjs/axiosとの連携方法も書いてあります。

注意点は、import axiosでnuxt外のaxiosを使わないことです。
そうすると@nuxtjs/axiosを使っていないためmockが反応しませんでした。

import axios from 'axios'

axios.get(`/url`)

下記のようにすることで解決しました。

this.$axios.get(`/url`)

package.jsonにmockで起動できるようにscriptを追記しました。

"dev:mock": "axios-mock-server -b && cross-env NODE_ENV=development MOCK=true nodemon --exec babel-node server/index.js --watch server",

nuxt.config.jsにmock用のプラグインをdev環境だけ追加するように追記しました。
MOCK=trueの場合のみ追加するようにしています。

plugins: [
  '~/plugins/jsonld',
].concat(process.env.MOCK ? '~/plugins/mock' : []),

e2eテストを導入する

cypressを入れてみました。

eslint, prettierでコケちゃう

eslint-plugin-cypressを入れて回避しましょう。

yarn add eslint-plugin-cypress

.eslintrc.js

extends: [
  '@nuxtjs',
  'prettier',
  'prettier/vue',
  'plugin:cypress/recommended', //追加しました。
  'plugin:prettier/recommended',
  'plugin:nuxt/recommended'
],

feedを追加する

@nuxtjs/feedを使うと動的にも出力できてよさそうです。

https://github.com/nuxt-community/feed-module

sitemapを追加する

@nuxtjs/sitemapを使うと動的にも出力できてよさそうです。

https://www.npmjs.com/package/@nuxtjs/sitemap

なぜだかGoogle Search Consoleにsitemap.xmlが反映されない

「サイトマップ 取得できませんでした」と出てしまい、サイトマップがうまく読み込まれませんでした。
フォーマットなど調べてみたのですが、いまのところ原因がわかりませんでした。
進捗があり次第。追記したいと思います。

Adsenseの導入

下記プラグインを使うと、任意の位置に広告を追加することができます。
* https://www.npmjs.com/package/@nuxtjs/google-adsense

nuxt.config.js
{
  modules: [
    // Simple usage
    ['@nuxtjs/google-adsense', {
      id: 'ca-pub-###########'
    }]
 ]
}

任意の位置に下記タグを入れます。

<adsbygoogle
  ad-slot="0000000000"
  ad-format="auto"
  full-width-responsive="true"
/>

0000000000には任意のslotIdを入れましょう。

画像差分比較を実装してみる

componentを変更したときにどこまで影響があるのかが分かりづらくなる時があるためResemble.jsを使って画像の差分比較をしてみました。

下記手順をふむことで複数枚画像が存在した場合に一つ前の画像と差分を比較する仕組みを実装しています。

  1. cypressでscreenshotを実行するとキャプチャをとる
  2. なにかコンポーネントを修正する
  3. もう一度cypressでscreenshotを取る
  4. yarn dissする

詳しく記事にしましたので下記を見てください。
* CypressとResamble.jsを使ったwebサイトの差分比較 - Qiita

下記参考にさせていただきました。
* PuppeteerとResemble.jsを使ったスクショ比較によるピクセル差分テスト - Qiita

youtubeでプレーヤー表示

vue-youtubeを使うと簡単に実装できそう

Nuxt.js 2でYoutubeプレイヤー埋め込み - Qiita

Google code-prettifyを使ったときの不具合

今後対応したいこと

  • push通知の実装
  • ドロワーメニューの実装(良い感じのコンポーネントが見つからなかった…)
  • Google Search Consoleでsitemapが読み込めない問題の解決
  • header下にスクロールしたら引っ込むようにする(これも簡単なのが見つからなかった)プラグインを作ろうかなと思っています
  • WAI-AREA roleを適切にいれる