LOADING

saco blog logo

Webコーダー日記

Nuxt勉強【はじめてつくるNuxtサイト(三好アキさん著書) – 第3章 開発編その2】

webコーダーのsaco @sacocco_sacoya です。
前回に引き続きはじめてつくるNuxtサイト(三好アキさん著書)で学んだことを記事にします。
※ もし記述内容として誤りやアドバイスなどがありましたら、Xお問合せフォームにてお知らせいただけるととても喜びます!

教材内の目次では第3章の「開発編 その2」の記録です!

内容はポートフォリオのTOPページを作成する、というものです。

生じた疑問点やエラー、教材と結果が違う箇所など、私が触ってみた結果も交えて記述していきたいと思います。

↓前回の記事はこちら

Indexページを編集

第2章の初めに作成した、pagesフォルダ内にあるindex.vuecontact.vueを使用していきます。
第2章で記述したコードはすべて削除してからすすめます。

まずはpagesフォルダ内にあるindex.vueを開き、以下のコードを追加しました。

<template>
    <div>
        <div class="hero">
            <nuxt-img src="/images/index-hero.jpg" alt="hero" format="webp" />
            <div>
                <h1>I'm Abe Hiroki!</h1>
                <h3>Javascript Developer</h3>
            </div>
        </div>
        <div>
            <div>
                <div>
                    <h2>Javascript Nerd</h2>
                    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Alias cum cumque inventore debitis,
                        suscipit, iusto laborum veniam repudiandae nisi incidunt aliquam odio? Dolores, ex at consectetur
                        harum officia neque nostrum.</p>
                </div>
                <nuxt-img src="/images/profile.jpg" alt="profile" format="webp" />
            </div>
            <div>
                <h2>Skills</h2>
            </div>
            <div>
                <div><img src="/images/javascript.svg" alt="javascript"><span>JavaScript / 10 years</span></div>
                <div><img src="/images/react.svg" alt="react"><span>React / 4 years</span></div>
                <div><img src="/images/vue.svg" alt="vue"><span>Vue / 4 years</span></div>
                <div><img src="/images/nuxt.svg" alt="nuxt"><span>Nuxt / 3 years</span></div>
            </div>
            <div>
                <NuxtLink to="/contact">Make It Happen!</NuxtLink>
            </div>
        </div>
    </div>
</template>

ブラウザで確認すると、まだ画像などのサイズ調整がされていませんが、トップページindex.vueの土台(スケルトン)が完成です。

コンタクトページを編集

contact.vueを開き、以下のコードを追記しました。

<template>
    <div>
        <div>
            <h1>Contact</h1>
            <p>お気軽にご連絡ください</p>
            <form method="POST">
                <label htmlFor="name">お名前</label>
                <input type="text" name="name" id="name" required>
                <label htmlFor="email">メールアドレス</label>
                <input type="text" name="email" id="email" required>
                <label htmlFor="textarea">ご用件</label>
                <textarea name="message" rows="10" id="textarea" required></textarea>
                <button type="submit">送信</button>
            </form>
        </div>
    </div>
</template>

ブラウザを開くと、以下のような状態です。
Contactページの土台も完成しました。

layoutの作成

各ページの骨組みが完成したので、共通パーツであるヘッダーとフッターを作成していきます。

componentsフォルダ

ルートディレクトリにcomponentsフォルダを作成し、その中にheader.vuefooter.vueを作成しました。

header.vue

header.vueに以下のコードを記述しました。

<template>
    <header>
        <div>
            <div>
                <NuxtLink to="/">
                    <nuxt-img src="/images/logo.png" alt="logo" format="webp" />
                </NuxtLink>
                <ul>
                    <li>
                        <NuxtLink to="/blog">Blog</NuxtLink>
                    </li>
                    <li>
                        <NuxtLink to="/contact">Contact</NuxtLink>
                    </li>
                </ul>
            </div>
        </div>
    </header>
</template>

footer.vue

footer.vueには以下のコードを記述しました。

<template>
    <footer>
        <div>
            <a href="https://www.google.com/"><img src="/images/github.svg" alt="logo"></a>
            <a href="https://www.google.com/"><img src="/images/linkedin.svg" alt="logo"></a>
            <a href="https://www.google.com/"><img src="/images/twitter.svg" alt="logo"></a>
            <a href="https://www.google.com/"><img src="/images/facebook.svg" alt="logo"></a>
            <hr />

            <NuxtLink to="/contact">Contact</NuxtLink>
            <NuxtLink to="/blog">Blog</NuxtLink>
            <p>©{{ new Date().getFullYear() }} Abe Hiroki</p>
        </div>
    </footer>
</template>

以上でコンポーネントファイルのheader.vueとfooter.vueが完成です。

コンポーネントファイルについて

Vueではコンポーネント(部品化)というコンセプトが採用されており、作成したコンポーネントをパーツとして必要なページで読み込んで使用することができます。

テストとして、contact.vueファイルにヘッダーとフッターのコンポーネントを読み込みました。

<template>
    <Header />//<div>から記述変更
    <div>
        <h1>Contact</h1>
        <p>お気軽にご連絡ください</p>
        <form method="POST">
            <label htmlFor="name">お名前</label>
            <input type="text" name="name" id="name" required>
            <label htmlFor="email">メールアドレス</label>
            <input type="text" name="email" id="email" required>
            <label htmlFor="textarea">ご用件</label>
            <textarea name="message" rows="10" id="textarea" required></textarea>
            <button type="submit">送信</button>
        </form>
    </div>
    <Footer />//</div>から記述変更
</template>

!注意点

componentsファイルの名前を「component」としてしまっていたことで読み込みエラーが発生しました。
VS Codeでは正しければアイコンが右のように色つきに変わりました。

保存してブラウザを確認すると、headerとfooterが読み込まれていました!

Auto Imports機能

Nuxt3ではAuto Importsという機能がデフォルトで備わっており、componentsというフォルダの中にあるファイルは、importで読み込みを行わなくてもコンポーネントとして利用可能のようです。
(ほか、composables、utilsというフォルダ名でも同様にAuto Importが有効となってるようです。)

共通コンポーネントとして読み込む方法

作成した各コンポーネントはすべてのページで読み込みを行いたいので、layout用のテンプレートを作成していきます。

流れとして、ヘッダーとフッターをまとめたコンポーネントとしてのlayoutファイルを作成し、サイト全体で適用したいスタイルや機能を書き込むapp.vueに追記していきます。

前の項目でcontact.vueに読み込んだヘッダーとフッターのコンポーネントの記述は、もとのdivタグへ戻しました。

layoutsフォルダ作成

ルートディレクトリにlayoutsフォルダを作成し、その中へdefault.vueファイルを作成しました。

layoutsフォルダの中にdefault.vueという名前のファイルを作成することで、このファイルが通常のコンポーネントファイルではなく、layoutに使用される特別なものということを示すことになります。

default.vueの中に以下のコードを記述しました。

<template>
    <div>
        <Header />
        <main>
            <slot />
        </main>
        <Footer />
    </div>
</template>

続いて、app.vueに以下のコードを記述しました。

<template>
    <NuxtLayout>
        <NuxtPage />
    </NuxtLayout>
</template>

<NuxtLayout>とは

<NuxtLayout>はNuxtの専用タグで、layoutフォルダのdefault.vueに書かれたコンポーネントになります。

<slot/>とは

<slot/>はVueの専用タグで、下位コンポーネントを上位コンポーネントに差し込んで表示することができるものです。

全体図を確認

デベロッパーツールで出力されたコードを確認するとdata-v-inspectorとして、どのファイルから読み込まれたものかが明示されていました。

ここが教材とは異なっていました。教材内では通常通り<header>や<main>だけの表記でしたが、バージョンが新しくなったようで、分かりやすい表示になっていると感じました。

以上で全ページの土台が完成いたしました。

デザインを調整する

最後にデザイン調整を行うため、スタイルCSSを当てていく方法について学びます。

(headerやfooterには必要なクラスをここで付与しておきました。)

まずassetsフォルダを作成し、その中にさらにstylesフォルダを作成します。

そして各ページに対応するCSSファイルとサイト全体に適用するためのcommon.cssファイルを作成しました。

singleblog.cssは記事詳細ページ([id].vue)用のcssファイルです。

NuxtでCSSを利用する方法

NuxtでCSSを利用するには、各ページで読み込むこともできますが、nuxt.config.tsで読み込む方法が手軽です。
以下のように追記しました。

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
    devtools: { enabled: true },

    modules: [
        "@nuxt/content",
        "@nuxt/image"
    ],

    //追記ここから
    css: [
        "~/assets/styles/common.css",
        "~/assets/styles/layout.css",
        "~/assets/styles/index.css",
        "~/assets/styles/blog.css",
        "~/assets/styles/contact.css",
        "~/assets/styles/singleblog.css",
    ]
    //追記ここまで
})

CSSをnuxt.config.tsファイルで読み込むメリットを調べて見ました。

  • 一元管理できる

1つのファイルでCSSを管理することで、一貫性のあるデザインを維持しやすくなる

  • パフォーマンス最適化

nuxt.config.tsでCSSの読み込みを設定することで、ビルド時にCSSが適切に最適化され、冗長なコードが削除される(CSSの圧縮、使用されていない無駄なセレクタやスタイルルールの削除など)

以上で読み込みが完了したのでブラウザを確認すると、無事CSSが適用されました!

まとめ・感想

  • ヘッダーなど共通パーツとして使いまわしたい部分はcomponentsフォルダへ配置する
  • Nuxt3にはデフォルトでAuto Import機能が備わっており、componentsという名前のフォルダ内にあるファイルはimport不要で呼び出しすることができる
  • layoutフォルダ内にdefault.vueという名前のファイルを配置すると、layoutファイルとして認識される
  • <nuxtLayout>をapp.vueへ記述することでレイアウトファイルを呼び出すことができる
  • NuxtでCSSファイルを管理するにはassetsディレクトリ内にstylesディレクトリを作成し、その中に各ファイルを配置するのが一般的
  • NuxtでCSSを利用するにはnuxt.config.tsファイルへ記述することでパフォーマンス最適化などのメリットがある

ブログページに引き続き、教材に沿ってTOPページも作成が完了しました。

各役割ごとに固定のフォルダ名で管理していくという決まりがあることで、とても管理がし易い構造になるなと感じました。

Auto Import機能が備わっていることや、CSSをnuxt.config.tsファイルに記述して読み込むことでパフォーマンスが最適化されるなど、Nuxt3に備わった機能の便利さに驚きました。

(Auto Import機能に関して少しお調べすると、色々好き嫌いの意見が分かれる機能であることがわかりました。)

今回も沢山の学びを得ることができました!
次回はVercelというwebサーバーに作成したポートフォリオをUPしていく内容です。

本日は以上です。

PROFILE

saco profile img

SACO

1990年12月生まれ / 岡山県在住

WEBコーダーです。
2019年から独学でweb製作の勉強を開始し、2020年にコーダーに転身しました。
製作の備忘録など記していきます。
ショートカットキー、notionが好きです。

ポートフォリオサイトです

saco portfolio logo