JAMstack で初めてのホームページ制作の手順を紹介します(トップページデザイン構築) | 東京都墨田区のHP・デザイン・イラスト制作会社 TenCy株式会社
    • HOME
    • お知らせ
    • JAMstack で初めてのホームページ制作の手順を紹介します(トップページデザイン構築)
  • 2022.7.3 2022.10.26

    JAMstack で初めてのホームページ制作の手順を紹介します(トップページデザイン構築)

    前回の記事に引き続き、JAMstack 構成でのサイト構築を試行錯誤してみたいと思います。前回の記事はこちら。

    JAMstack で初めてのホームページ制作に挑戦!

    試行錯誤する環境は、前回に引き続きこちらです。

    • microCMS + netlify + Nuxt.js
    • Windows11 + VS Code + github

    主に参考にしたmicroCMSの記事をまとめておきます。いずれもmicroCMS社のブログ記事です。

    前回の記事で、JAMstack 構成で記事の作成~ビルド・デプロイ~配信までの一通りの流れが実現できました。今回は、サイトのそのものをmicroCMS と Nuxt を使いながら作りこんでいきます。

    JAMstack でWebメディアサイト(ブログ形式)を作ってみる

    前回の試行錯誤で、トップページにおいてmicroCMSに登録された記事一覧の取得と、個別記事ページへのルーティングまで実施できました。引き続き、今回の記事ではトップページの作りこみを進めていきたいと思います。

    ヘッダーメニューのコンポーネント化

    今回作るサイトは、Webメディアになります。microCMSの無料プランの範囲で試行錯誤するため、前提として利用できるAPI数は3個であり、記事/カテゴリ/タグ、の3種を登録しています。ヘッダーメニューでは、各カテゴリページへの遷移やお問い合わせページへの遷移等を作りたいと思います。

    今回作りたいヘッダメニューのイメージはこちら。WordPressで作っていたころの名残りです。

    良くあるヘッダーですね

    ヘッダメニューに搭載する機能として、まずはドロップダウンメニューを載せましょう。スマホレイアウトのハンバーガーメニュー等もいずれは必要となりますが、まずはPC版で実施していきたいと思います。

    なお、こちらのコードはオープンソースとして公開頂いているmicroCMSのブログのコードを多分に参考にさせていただいています。大変感謝。Jamstackを学ぶ上での良い教材をありがとうございます。

    「microCMSブログをオープンソース化しました」 https://blog.microcms.io/open-source-the-blog/

    まずは、HTML側のコードから。ロゴ部分とメニュー部分を合わせて一つのコンポーネントにしています。

    <template>
      <div>
        <header class="header">
          <h1 class="logo">
            <a href="https://trylog.biz">
              <img class="logoImg" src="https://trylog.biz/wp-content/uploads/2021/11/%E3%83%AD%E3%82%B3%E3%82%99-1.png"
                width="422" height="80" alt="trylog" />
            </a>
          </h1>
          <div class="menu" :class="{ isOpen: open }">
            <ul class="lists">
              <li v-for="(menu, index) in desktopHeaderMenu" :key="index" class="list" @mouseover="handleOpenMenu(index)"
                @mouseleave="handleCloseMenu(index)">
    
                <NuxtLink :to="menu.path" :class="menu.isDropDown ? 'dropDown' : ''"> {{menu.name}} </NuxtLink>
                <transition name="fade">
                  <ul v-if="menu.contents.length > 0" v-show="openDropDownMenu[index]" class="dropDownMenu">
                    <li v-for="(content, contentIndex) in menu.contents" :key="contentIndex" class="dropDownMenuList">
                      <a :href="content.path" v-text="content.name" />
                    </li>
                  </ul>
                </transition>
              </li>
            </ul>
          </div>
        </header>
        <div class="empty"></div>
      </div>
    </template>

    マウスカーソルのhoverでドロップダウン形式のサブメニューを表示する仕組みにするため、サブメニューの設定があるかどうかで <transition>タグ以下の有無が変わります。サブメニューの設定有無は、menu.contents.length > 0 で判別しており、v-if ディレクティブで表示変更が対応しています。

    これに対するJavaScriptの部分は、以下の通りです。カテゴリ記事一覧をリンク先にしているので、リンク先URLとmicroCMS側の自動生成ページのリンクを合わせておく必要があります。

    export default {
      data() {
        return {
          open: false,
          openDropDownMenu: [],
          desktopHeaderMenu: [
            {
              name: '挑戦の軌跡',
              path: '/category/logs/page/1',
              isDropDown: false,
              contents: [],
            },
            {
              name: '特集',
              path: '',
              isDropDown: true,
              contents: [
                {
                  name: '対談記事',
                  path: '/category/talk/page/1',
                },
                {
                  name: 'PR記事',
                  path: '/category/promotion/page/1',
                },
              ],
            },
            {
              name: '経営Tips',
              path: '/category/tips/page/1',
              isDropDown: false,
              contents: [],
            },
            {
              name: '経営ニュース',
              path: '/category/news/page/1',
              isDropDown: false,
              contents: [],
            },
            {
              name: 'お問い合わせ',
              path: '/contact',
              isDropDown: false,
              contents: [],
            },
          ],
        }
      },
      created() {
        this.openDropDownMenu = Array(this.desktopHeaderMenu.length).fill(false)
      },
      methods: {
        setOpen(value) {
          this.open = value
        },
        toggleOpen() {
          this.open = !this.open
        },
        handleOpenMenu(index) {
          this.openDropDownMenu.splice(index, 1, true)
        },
        handleCloseMenu(index) {
          this.openDropDownMenu.splice(index, 1, false)
        },
      },
    }

    JSONオブジェクト「desktopHeaderMenu」でデスクトップ画面表示時のメニュー構造を定義しています。スマホやタブレットの時は、ハンバーガーメニューを表示してオーバーレイ方式でメニューを表示することを想定していますので、改めて別途定義していくことが必要です。

    今回の例では、デスクトップ用のヘッダメニューまで、としておきたいと思います。

    サイドメニューのコンポーネント化

    続いて、サイドメニューを作っていきましょう。サイドメニューは様々な情報を表示することが想定されますが、3APIという制限の中では表示できるものもそこまで多くありません。まずは、カテゴリ一覧とタグ一覧を表示したいと思います。

    カテゴリ一覧のコンポーネント化

    components フォルダ内に、Categories.vue を追加します。Categories.vue では、親コンポーネント側からカテゴリ一覧データを受け取ります。カテゴリ一覧やタグ一覧を表示するのみであれば子コンポーネント側でAPIコールする設計も考えられますが、記事一覧を表示するために親コンポーネント側でカテゴリ一覧やタグ一覧APIを利用するため、データを受け取るのみの設計としておきます。

    <template>
      <div class="wrapper">
        <h1 class="pageTitle">カテゴリー</h1>
        <ul>
          <li v-for="category in categories" :key="category.id" class="list">
            <nuxt-link :to="`/category/${category.id}/page/1`" class="link">{{
              category.name
            }}</nuxt-link>
          </li>
        </ul>
      </div>
    </template>
    
    <script>
    export default {
      props: {
        categories: {
          type: Array,
          required: true,
        },
      },
    };
    </script>

    タグ一覧のコンポーネント化

    カテゴリと同様に、components フォルダ内にTags.vue を追加します。Tags.vue では、親コンポーネント側からタグ一覧データを受け取ります。将来的にはタグクラウドのような見た目にカスタマイズしたいところですが、まずはカテゴリ一覧と同じように取得と表示ができるところまで、確認します。

    <template>
      <div class="wrapper">
        <h1 class="pageTitle">タグ</h1>
        <ul class="list">
          <li v-for="tag in tags" :key="tag.id" class="listItem">
            <nuxt-link :to="`/tag/${tag.id}/page/1`" class="link">{{
              tag.name
            }}</nuxt-link>
          </li>
        </ul>
      </div>
    </template>
    
    <script>
    export default {
      props: {
        tags: {
          type: Array,
          required: true,
        },
      },
    };
    </script>

    前回の記事の中で、フロントページを定義する /pages/index.vue に、サイドメニューを定義するasideタグを用意しておいたので、そこにカテゴリcomponentとタグcomponent を追加していきましょう。

    <aside class="aside">
      <Categories :categories="categories" />
      <Tags :tags="tags" />
    </aside>

    サイドメニュー領域にカテゴリ一覧とタグ一覧が表示されればOKです。

    また、カテゴリ一覧とタグ一覧の一覧ページに対するルーティング処理を忘れずに追加しましょう。これがないと、カテゴリ一覧をクリックしても404になってしまいます。

    export default {
      router: {
        extendRoutes(routes, resolve) {
          routes.push({
            path: '/page/:id',
            component: resolve(__dirname, 'pages/index.vue'),
            name: 'pages',
          });
          routes.push({
            path: '/category/:categoryId/page/:id',
            component: resolve(__dirname, 'pages/index.vue'),
            name: 'categories',
          });
          routes.push({
            path: '/tag/:tagId/page/:id',
            component: resolve(__dirname, 'pages/index.vue'),
            name: 'tags',
          });
        },
      },
    }

    フッターのコンポーネント化

    フッターメニューに関しては、microCMSブログのコードをリンク先やサイトマップ構造を合わせるだけで充分ではないかと思います。さほど難しくなく、Footer.vueコンポーネントを追加して利用するだけで実施できるのではないでしょうか。記述は割愛したいと思いますが、簡単に導入可能です。

    サイトマップは割愛して、運営会社のリンクだけ追加。

    次回以降では、Webメディアを作っていくにあたって躓いた個々の課題・問題について記事として取り上げたいと思います。


    弊社ではホームページの制作について、ご要望に応じた最適な制作方式・運用管理方式をご提案いたします。お困りごとがありましたら、お気軽にお問い合わせください。

    OTHER NEWS

    一覧にもどる