マークアップエンジニアがNuxt.js案件で必須な知識【5選】

こんにちは、現在フリーのマークアップエンジニアとして活動しているしょーごと申します。
最近はYouTubeなどでも発信しています。

普段は**WordPress構築や静的サイトコーディングをメイン**としているのですが、
最近機会に恵まれまして、`Nuxt.jsのマークアップ部分（ロジック以外）`を担当しております。

結果的に大苦戦してベテランの方に大迷惑をかけてしまったので、
`マークアップエンジニアやデザイナーがNuxt.jsのマークアップ部分をアサインされた場合に必要な知識`をまとめました。

**Nuxt.jsはweb制作業界にも少しづつ浸透してきている**ので、マークアップエンジニアやデザイナーさんもいずれ触る期間があるかもしれない点で、同業の方々に参考にして頂けたらと思います。

`俺の屍を超えていけ`

## Nuxtってなんなの？

Vue.js単体では開発に不足している機能が多いです。なので従来はプラグインやライブラリを導入していましたが、Nuxtは色んな機能が最初から盛り込まれているフレームワークになります。
**Vue.js+ライブラリの集まり**みたいなものです。

## Nuxt.jsのマークアップ部分とは？

Nuxt,jsはご存知の通り、`単一ファイルコンポーネント`と呼ばれています。

HTML,CSS,JSが一つのファイルにまとまっています。

`以下コードは超適当なので、scriptにロジックがかいてあるんだとだけ認識頂けたら🙏`

```vue:default.vue

<template>
  <div>
    <div class="posts overflow-scroll mb-24">
      <post v-for="(post,index) in posts" :key="index" :post="post" />
    </div>
      <el-upload v-if="!imageUrl" action :show-file-list="false" :http-request="uploadFile">
        <el-button size="small" type="primary">Click to upload</el-button>
      </el-upload>
      <el-input type="textarea" :rows="8" placeholder="Please input" class="mt-8" v-model="text"></el-input>
  </div>
</template>
<script>
import Post from "~/components/Post.vue";
import { db, firebase } from "~/plugins/firebase";
export default {
  components: {
    Post,
  },

  data() {
    return {
      posts: [],
      imageUrl: null,
      text: null,
    };
  },
  methods: {
    async post() {
      await db.collection("posts").add({
        text: this.text,
        image: this.imageUrl,
        createdAt: new Date().getTime(),
      });
      this.text = null;
      this.imageUrl = null;
      window.alert("保存されました");
    },
  },
  mounted() {
    db.collection("posts").onSnapshot((snapshot) => {
      snapshot.docChanges().forEach((change) => {
        const doc = change.doc;
        if (change.type === "added") {
          this.posts.unshift({ id: doc.id, ...doc.data() });
        }
      });
    });
  },
};
</script>
<style lang="scss" scoped>
input {
  box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16);
}
.posts {
  text-align: center;
}

```

ここの**script以外が作業範囲**になります。
つまり、`チーム開発が前提です。`

厳密に言えば、

>
1.HTML部分のコーディング
2.Scoped CSS、グローバルCSSの記述と設計(Sassが標準)
3.コンポーネント分け（ここだけscript部分）
4.状態管理でのclass出し分け（v-forやv-bind,propsあたり）
5.CSSフレームワークの利用と共存（Tailwindやbulma、Element-uiやBuefyなど）

このあたりが業務範囲になります。
その他はプログラマーさんに担当していただきます。

>
プログラマー→フロントエンド、フルスタックエンジニア
マークアップエンジニア→コーダー、デザイナー

では、これらをふまえてNuxt.jsのマークアップ部分を担当する上で何を知っておくといいのか解説します。

## ①Nuxtのコンポーネント、レイアウト、ページルーティング

やはりここが一番重要になるかと思います。
以下公式の画像になります。
![スクリーンショット 2020-08-19 17.21.42.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472701/696befaa-081f-27f3-4c68-2efb0d9d1f8b.jpeg)
>[公式サイト：ビューについて](https://ja.nuxtjs.org/guide/views/)

Nuxtでは一般的にビューの表示は

1.レイアウト（全ページ読み込まれる）
2.ページ
3.コンポーネント

の3つに別れます。

### レイアウトの役割

レイアウトは各ページでの共通要素を書きます。
大抵はheaderとfooterコンポーネントを呼びこむぐらいだと思います。

```vue:default.vue

<template>
  <div>
    <app-header />
    <nuxt />
    <app-footer />
  </div>
</template>
```

`<nuxt />`という部分に、各ページの内容が入ってきます。
### ページの役割

そのページ専用の内容を書いていきます、
直接HTMLを書いたり、コンポーネントを呼び込んで構築していきます。
**レイアウトでheaderとfooterは呼び込み済みなので、それ以外の部分になります。**

またNuxtではルーティングがすでに設定してあるため。例えばusersページを作る際には、

![スクリーンショット 2020-08-19 17.56.32.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472701/9eab9682-3c8c-c28c-3476-1a83c275c36f.jpeg)

これでlocalhost:3000/usersでその配下のindex.vueを表示させることができます。

pagesディレクトリ以下がそのままページのディレクトリ構成を示しています。


### コンポーネントの役割

`header,footer,sidebar,navigationなどダントツでファイル数が多くなります。`
基本的に共通化できそうな塊はだいたいコンポーネント化していきます。
`レイアウトやページで読み込んで表示させていきます。`
大きめのコンポーネントの場合、コンポーネントの中でコンポーネントを読み込むなどの状況もよくあります。


私のブログを例にしてみます。
>
赤枠：レイアウト
緑枠：ページ
青枠：コンポーネント

![screencapture-shogo-log-2020-08-19-17_28_21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472701/79f81ade-4778-e2f8-1705-b0fdc85592ff.png)

![screencapture-shogo-log-2020-08-19-17_28_21 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472701/70a2cfe7-80a6-802f-7d2d-68df4fa254ac.png)


>[弊ブログ：しょーごログより](https://shogo-log.com/)

コンポーネントの読み込みは**importとexport defaultをセットで**使います。

`userコンポーネントを読み込む場合`

```vue:index.vue

<template>
  <div class="users">
    <user />
    <user />
  </div>
</template>

<script>
import User from "~/components/User.vue";
export default {
  components: {
    User,
  },
};
</script>
```
コンポーネント間でのメソッドや状態の受け渡しなどもあるので、プログラマーと相談しつつコンポーネント分けの粒度を決めるといいかなと思います。

## ②Scoped CSSとグローバルCSS設計

### Scoped CSSについて

Scoped CSSは、`scoped`を記入するだけで使えます。その単一ファイル内にしかCSSのスコープが及ばないため、グローバル汚染がなくよく
`「CSS is too fragileからの脱却だ！」`的に叫ばれますが、しかしやはり銀の弾丸はなく、h2やsectipnなどのセレクタに直接指定すると普通に子コンポーネントを汚染します。
![スクリーンショット 2020-08-19 21.46.07.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472701/1e330fcf-11dd-e9b4-7ed4-68c81db288a4.jpeg)
![スクリーンショット 2020-08-19 21.47.24.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472701/37f8cea3-9edc-5ae7-674a-9ae126070ede.jpeg)
>[参考サイト：ICS Media](https://ics.media/)

`このようにカスタムデータ属性により影響範囲を限定的にしています`

まあ普通にBEMとか使っていれば問題ないです。

### Scoped CSSにおけるクラス設計
詳しくは以下の記事に譲りますが、Scoped CSSでも暴虐無人プレイができるわけではないです。
ただ、普通にBEM的にクラス名を書いていけば、バッティングの可能性は相当低くなるので、

Web制作にNuxt.jsが有用である理由の一つとなっております。

>[Scoped CSSにおけるCSS設計手法](https://ics.media/entry/200515/)

### グローバルCSS

全体に適用したいCSSは`assets`以下にcssファイルを置いて、それを`nuxt.config.js`で読み込むのですが、とりあえず「Scoped CSS」と「グローバルCSS」に分かれているらしいぐらいの認識で大丈夫です。
reset.scssとか_variables.scss,_mixin.scssなど全体で使いそうなものを定義していきます。

## ③状態変化でクラスの出し分け
### v-bind,props

意外にここも知っておいたほうがいいです。
例えばよく**「トップページのみヘッダーのデザインが違う🙀」**ということはよくあります。
しかしレイアウトでheaderコンポーネントを読み込んでいるため、トップページのみ変更するのは難しく感じます。

そこでpropsとv-bindが出てきます。

手順としては
>
1.トップページ専用のレイアウトを準備し、利用
2.topであることをBooleanで管理し、trueのときにheaderにクラス付与

となります。

トップページ専用のレイアウトをtop.vue、trueを渡す先のheaderコンポーネントははheader.vueとし、トップページの表示はindex.vueが行います。

まずはtop.vueで`:is-top="true"`とすることでトップであることをheaderコンポーネントに伝えます。

```vue:top.vue
<template>
  <div>
    <header :is-top="true" />
    <Nuxt />
    <footer />
  </div>
</template>

<script>
import Header from '~/components/header-nav'
import Footer from '~/components/footer-nav'

export default {
  components: {
    Header,
    Footer
  }
}
</script>
```

その後、index.vueではレイアウトとしてtop.vueを使うと宣言します。

```vue:index.vue

layout: 'top',

```

headerコンポーネントでpropsによりtrueを受け取り、v-vindでtrueのときにclassを付与します。

```vue:header.vue
<template>
  <header :class="{ 'top-header' : isTop === true }">
  </header>
</template>
<script>
  props: {
    isTop: {
      type: Boolean
    }
  }
</script>

```

これにより、トップページにのみ`top-header`というクラスが付与できるようになります。

他にも**v-onやv-forについても知っておいたほうがいいです。**
v-onはモーダルの表示、v-forは`<li v-for="(item, index) in items">`などでindexを取り出し**ループ内で動的にクラス名を付与したいとき**に、役立ちます。
ここでは詳しくは割愛します。

## ④npm関連
直接Nuxtとは関係しませんが、npmを普段より利用しているかも重要です。
マークアップ側が自分でパッケージを入れることはほとんどないと思いますが、必須知識です。

### npm install
チーム開発ではよくパーケージが新しくインストールされていたりします。
その際に、`「package.jsonが更新されてる！！ということはnpm iすればいいんだ！！」`と知っていればいいのですが、知らないとエラー画面に飛ばされます笑
### npm run dev
Nuxtのサーバーを起動するnpm scriptsです。
ファイルを保存したら、画面を自動リロードしてコンパイルしてくれます。
### nvm
Node.jsのバージョン管理ツールです。
`開発開始前にnode.jsのバージョンはチームメンバーで合わせておくべきです`
npmで入れるモジュールが、Nodeのバージョンに依存するため、チームメンバーのグローバルNodeのバージョンが違うと、地獄と化します。

## ⑤Git
これもNuxtから離れますが、チーム開発ではかなり重要です。
Nuxtを扱うような案件では十中八九必要でしょう。
`いやテーム開発でGit運用とか常識やろ`と声が聞こえそうですが、1人Gitしか経験なく、マークアップ案件でGithub flowでのチーム開発とかほとんどないので自分は大苦戦しました...
diffが見やすいsourcetreeで大丈夫だと思います。

### 最低限抑えておくべきこと
- github flow（機能やページ毎にfeatureブランチを切って運用するぐらい）
- プル→ステージング→コミット→プッシュ→プルリクの流れがわかる
- コンフリクト対応
- スタッシュを知っておく（割と変更内容を退避させるため）

ぐらいかなと思います。コンフリクトの解消など自分はパニクってしまいレビュアー先輩エンジニアの方によしなにしていただきマージしてもらいましたが、これは迷惑かけたのであまりよくないと思いました。

### Gitでの開発流れ
>
1.最新origin/masterからローカルmasterにpull（この際にpackage.jsonが更新されていたら、npm iしてパッケージを入れておく）
2.masterからfeatureブランチを切り作業開始
3.作業が完了したらコミットしプッシュする
4.プルリクを出し、レビュアーにレビューを受ける、問題なければマージされる、問題あれば修正し再度コミットプッシュする
5.マージされたらmasterにチャックアウトし、必ずプルし最新のmasterにする。
6.そして次のfeatureブランチを切り、作業開始

少人数の開発&トラブルがなければこんな感じだと思います。

## Nuxt.jsでのマークアップ案件は増えるのか

NuxtはfirebaseやヘッドレスCMSと組み合わせてJamstackで利用されているイメージですが、ロジック部分に集中したい人は一定層いると考えています。
その際に、**Nuxtの構造を理解しているマークアップエンジニアにスタイリングを外注できたら楽そう**なので、
需要としてはポツポツ発生していそうだと思います。

Nuxtオンリーでの静的サイト制作については、未知数です。
Web制作で使われるならVueでのアニメーションの知識が必要になるのと、枯れているjQueryの資産が偉大なので、すぐに広まるのは考えにくいです。
しかし`保守性の面でコンポーネントやScoped CSSが大変魅力的`なので、大規模サイト制作で真価を発揮するかなと思っています。

## 事前に学習で使用していた教材

[Vue.js&Nuxt.js超入門](https://www.amazon.co.jp/dp/B07X6F1C2P/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)
[Gitが、おもしろいほどわかる基本の使い方33](https://www.amazon.co.jp/Git%E3%81%8C%E3%80%81%E3%81%8A%E3%82%82%E3%81%97%E3%82%8D%E3%81%84%E3%81%BB%E3%81%A9%E3%82%8F%E3%81%8B%E3%82%8B%E5%9F%BA%E6%9C%AC%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B933-%E6%94%B9%E8%A8%82%E6%96%B0%E7%89%88-%E5%A4%A7%E4%B8%B2-%E8%82%87-ebook/dp/B07T5995HK/ref=sr_1_7?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=git&qid=1597884759&s=digital-text&sr=1-7)