co6ei note

Nuxt.jsでのHello Worldと構造のチェック

記事をTwitterで共有

ここの通りに進める。

nuxtjs.org

と思ったが動画とソースコードが置いてあるだけのかなり簡素な作りなので、少し遠回りして、理解を深めながらHello Worldしようと思う。

まず、create nuxt-appによって作られたままのフォルダ群を見ていく。以下のページを参考にする。

nuxtjs.org

このページにすべて書いてあるので基本的にはそちらを読むとして、Hello Worldからフツーの静的なWebサイトを制作するのに必要そうなところを重点的に見ていく。

正確には、middlewarepluginsstorenuxt.config.jsはとばします。

バーっとフォルダを開いていくと、大体のフォルダがREADME.mdしか持っておらず、このマークダウンには当該フォルダの説明が英語で記載されている。やさしい。

この中で、README.mdしか入ってないフォルダが上記であげたディレクトリたち。今は一旦気にしない。

まず、Pagesを確認する。

Pages

Vueも真面目に勉強したことが無いゆえ知識がまばらなのだが、Vueでは<template>の記述のある.vueファイルはコンポーネントとして使用できるようになる。

単一ファイルコンポーネントというやつ。

単一ファイルコンポーネント - Vue.js

ただ、Nuxtの場合は、ほとんどのファイルがで囲まれることになる。それがコンポーネントでなくても。まさに、その例がこのPagesに含まれるファイルなのではないだろうか。

jsxの一番上に1つの親要素を用意しなければいけないようにで囲むのかと思ったが、の中で更に全体を囲む親要素は必要なよう。

また、このPagesディレクトリに入っている.vueファイルは自動的に読み込まれ、ルーティングを上手い具合にやってくれるそう。ありがたい。

(話は変わるけど、ファイルちょっといじっただけでESLintがめっちゃ怒ってきて困る)

※ESLint

かなり怒ってきて色々とシンドいので先にこいつをどうにかする。

環境によって状況が変わってきそうなので、リンターは取り敢えずいいから先に進みたい、という人はESLintを解除してしまっても良いと思う。

.eslintrc.jsに新しく記述を追加する。会社のプロジェクトで使用しているやつを借りた。

module.exports = {
  root: true,
  env: {
    browser: true,
    node: true
  },
  parserOptions: {
    parser: 'babel-eslint'
  },
  env: {
    serviceworker: true
  },
  extends: [
    'prettier',
    'prettier/vue',
    'plugin:prettier/recommended',
    '@nuxtjs',
    'plugin:nuxt/recommended'
  ],
  plugins: ['prettier'],
  // add your custom rules here
  rules: {
    'dot-notation': 0,
    'no-unused-vars': 0,
    'arrow-parens': 0,
    'space-before-function-paren': 0,
    'vue/singleline-html-element-content-newline': 0,
    'no-console': 'off',
    'vue/html-self-closing': [
      'error',
      {
        html: {
          void: 'always'
        }
      }
    ]
  }
}

詳しく見ると時間がかかりそうなので内容についてはとばす。

ここまで行っても現段階で出てるエラーとしては、<a>についているtarget="_blank"だと思う。このエラーに対しては、<a>に対しrel="noreferrer noopener"と記述を追加してあげることで、修正することが出来る……らしいのだがまだエラーが出る。

どうもESLintではなくPrettierがエラーを吐いているらしい。消耗してきた。

紆余曲折あり、以下の記事を参考に環境を整えてどうにか無意味なエラーのない世界が訪れた。

ただ、この記事通りでもちょっとハマって、VS Codeの環境設定でFormat On Saveのチェックを外したら上手くいった。

もうprettierで消耗したくない人へのvueでのeslint設定 - Qiita

しかし、つぎはrel="noreferrer noopener"の記述をなくしてもtarget="_blank"のエラーが出なくなってしまった......もう何がなんやら。ESLintとPrettierについては一度腰を据えて考えてみたほうが良さそう。

ココ結構な離脱ポイントな気がするし、最初はcreate nuxt-appのときESLintとPrettierのチェック外したほうが良いのかもしれない。

かなり話がそれたがやっと本題に戻れる。

components

pagesのindex.vueで使用されているのコードはcomponentの中にある。

言うまでもないが、コンポーネントとして作られたファイルは他のファイルに読み込んで、ある特定の役割を果たす。再利用されるパーツをコンポーネントに分けることでコードの可読性や保守性が高くなるのだ。

ドキュメントに少し気になる記述がある。

components ディレクトリには Vue.js のコンポーネントファイルを入れます。これらのコンポーネントでは asyncData や fetch を使うことはできません。

これらも併せて目を通しておく。(あれ、使えてない?)

nuxtjs.org

Nuxt.jsのasyncDataとfetchは何が違うのか - Qiita

layouts

上記のページ内にあるように、デフォルトレイアウトとしてdefault.vueを追加すると、レイアウトが指定されていないすべてのページに適応されるようだ。

現段階のdefault.vueにはリセットCSSやその他のスタイルまで書かれているが、この管理法は良くなさそう。リセットCSSなどは他ファイルに分けてどこかで統一して読み込ませたい。

しかし、layoutはどういう場面で使うのだろう。ワンカラム、ツーカラム、などのサイトの大枠を変えるような時に使用する?layoutを使わなくても実現できそうなので、まだ使い所が掴めない。

ドキュメントによると、エラーページはpageではなくlayoutで作るらしい。

ちなみに、layoutには<nuxt />コンポーネントが必須。ここでpageの中身などが読み込まれていく。

以下の画像を見るとそれぞれがどのように包まれているかイメージしやすい。

nuxt-views-schema

Hello World!

ここまで分かれば、何てこともなくHello World出来るはず。

というか、page内のindex.vueを少しいじるだけですぐに出来るので、かなりここまで遠回りしたとも言える。

まず、index.vueの中身をゴッソリ削る。

<template>
  <div class="container">
    <Logo />
  </div>
</template>

<script>
import Logo from '~/components/Logo.vue'

export default {
  components: {
    Logo
  }
}
</script>

<style>
.container {
  width: 100%;
  height: 100vh;
  max-width: 800px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
}
</style>

ふつうにHello Worldと表示させるだけではつまらないので、少し動きを加える

5 sec from Hello World!のように、1秒経過ごとに数値を入れ替えてみよう。

こんな感じ。

<template>
  <div class="container">
    <Logo />
    <h1>{{ `${timer} min` }} from Hello World!</h1>
  </div>
</template>

<script>
import Logo from '~/components/Logo.vue'

export default {
  components: {
    Logo: Logo
  },
  data() {
    return {
      timer: 0,
    }
  },
  created() {
    setInterval(() => {
      this.oneMinCounter()
    }, 1000)
  },
  methods: {
    oneMinCounter() {
      return this.timer ++
    }
  }
}
</script>

// <style>省略

result

data()とかcreated()とかmethods:とか色々使ってはいるけど、イマイチ使い所がまだ分からないので、次はライフサイクルについて見ていく。

Vue.js と Nuxt.js のライフサイクル早引きメモ - Qiita