NextJS 初心者向け チュートリアル ポートフォリオサイト作成 Topページ編

React
この記事は約22分で読めます。

皆様、こんにちは
この記事では、下記で紹介しました、最新のWEB技術であるNextJSというフレームワークの勉強を兼ねた制作物作成過程を解説いたします。

作成するのは、初学者の方のチュートリアル向けに、自分のサイト「ポートフォリオ」サイトになります。NextJSを使って何かを作るとしたら、高速なWebページは最も初学者にとって良い題材になります。

今回は、Topページとフッターヘッダーの作成編です。全5回に分けて解説していきますので、よろしくおねがいします。

ポートフォリオ作成 全編

ポートフォリオ作成 環境構築編

では、解説に入る前にNextJSを使った開発のための環境構築をしていきます。これをしなければ、開発に入ることができませんからね。

今回の解説においては、環境は下記になります。
前提として、NodeやTypeScriptがインストールされている必要があります。もし、NodeやTypeScriptがインストールされていない場合は、下記記事を参考にしてください。

環境
  • MacOS X
  • ターミナル:zsh
  • Node
  • npm

最初に、次のコマンドを実行してください。

$ npx create-next-app@latest app --typescript

このコマンドでNextJSを使用したプロジェクトが作成できます。プロジェクト名はこの記事ではappとします。これは任意の名前が設定できますので、皆さんのお好きに決めてください。

今回は型指定を行う事のできるTypeScriptで作成しますので、オプションとして–typescriptをつけます。

次に、Webサイトの見た目を決めるスタイルですが、今回はCSSフレームワークであるTailwindCSSを使用致します。これの詳細は省きますが、簡単に言うとクラス名を正しく設定するだけで、簡単に見た目を整えることができるフレームワークです。

今回はそれをNextJSプロジェクトにインストールして使えるようにいたします。

$ cd app

$ npm install -D tailwindcss postcss autoprefixer

$ npx tailwindcss init -p

上記のコマンドを実行してください。
これはTailwindCSSをインストールするための定形コマンドです。
続いてファイルを編集していきます。

module.exports = {
  content: [
    "./pages/**/*.{js,ts,jsx,tsx}",
    "./components/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

tailwindcssをNextJSにおいて使えるようにするため、tailwind.config.jsというファイルがapp内にあるはずです。そのファイルの内容を上記のようにしてください。

@tailwind base;
@tailwind components;
@tailwind utilities;

最後に、./app/styles/globals.cssのファイルを上記のように修正してください。これで、実際にクラス名を決定することで、TailwindCSSが動きます。

続いて、このプロジェクトで使用するライブラリをインストールして行きます。今回はdeviconとmaterial UIを利用します。

$ npm install --save devicon
$ npm install @mui/material @emotion/react @emotion/styled @mui/icons-material

これで、環境構築は終了です。

ポートフォリオ作成 ヘッダーの作成

では、最初にWEBページの部品を作っていきます。ヘッダーを作っていきましょう。
ヘッダーにはサイト名とナビゲーションバーを含みます。

では、最初に./app/pages/ディレクトリ内にcomponentsディレクトリを作成してください。

$ tree

├── components
│   ├── modules
│   └── organisms
├── index.tsx

//

さらに、componentsディレクトリ内にさらにorganismsディレクトリを作成してください。ファイル構造としては上記のようになります。

organismsディレクトリ内に、ファイルを作成していきます。ファイルを作成したら次のようにファイルを編集してください。

import React from "react";
import Link from "next/link";
import { webTitle } from "../../api/variable";

const Navbar:React.VFC = () =>{
    return(
        <div className="py-2">
            <ul className="flex flex-col items-center justify-center sm:flex-row md:justify-end sm:mt-2 sm:h-12">
                <li className="text-white px-6 py-2 w-1/2 text-center sm:w-1/4 md:1/5 lg:w-1/6">
                    <Link      
                        href={"/components/organisms/top"}
                        as="/"
                    >
                        <a className="p-3 align-middle block sm:text-xl md:text-2xl hover:opacity-50 hover:bg-gray-400">Top</a>
                    </Link>
                </li>
                <li className="text-white px-6 py-2 w-1/2 text-center sm:w-1/4 md:1/5 lg:w-1/6">
                    <Link
                        href={"/components/organisms/about"}
                    >
                        <a className="p-3 align-middle block sm:text-xl md:text-2xl hover:opacity-50 hover:bg-gray-400">About</a>
                    </Link>
                </li>
                <li className="text-white px-6 py-2 w-1/2 text-center sm:w-1/4 md:1/5 lg:w-1/6">
                    <Link 
                        href={"/components/organisms/skills"} 
                    >
                        <a className="p-3 align-middle block sm:text-xl md:text-2xl hover:opacity-50 hover:bg-gray-400">Skills</a>
                    </Link>
                </li>
                <li className="text-white px-6 py-2 w-1/2 text-center sm:w-1/4 md:1/5 lg:w-1/6">
                    <Link 
                        href={"/components/organisms/works"}
                        >
                        <a className="p-3 align-middle block sm:text-xl md:text-2xl hover:opacity-50 hover:bg-gray-400">Works</a>
                    </Link>
                </li>
                <li className="text-white px-6 py-2 w-1/2 text-center sm:w-1/4 md:1/5 lg:w-1/6">
                    <Link 
                        href={"/components/organisms/hobbys"}
                    >
                        <a className="p-3 align-middle block sm:text-xl md:text-2xl hover:opacity-50 hover:bg-gray-400">Hobbys</a>
                    </Link>
                </li>
            </ul>
        </div>
    )
};

const Header:React.VFC = () => {
    return (
        <>
        <header className="bg-gray-700 h-1/6 py-3 sm:pt-4 sm:pb-4">
            <h1 className="text-4xl font-bold text-white text-center sm:text-left sm:my-2 sm:mx-4">
                {webTitle}
            </h1>
            <Navbar/>
        </header>
        </>
    );
}

export default Header;

このファイルには、ヘッダーとなる部分のコードになります。ReactやNextは書き方が互いに似ており、JSX・TSXという書き方です。文法としては、JavaScriptとHTMLが融合したようなものです。
HTMLとJavaScriptを少し理解しておく必要があります。

また、JSXのclassを指定する方法はHTMLと少し違い、 classNameというタグを使用します。このタグ内に、TailwindCSSで決められたクラス名を入れることで、スタイルが適用されます。

次に、./app/pages/api/ ディレクトリにファイルを作成してください。

import {workTypes,skillTypes,importImage,hobbysTypes,hobbysdescType,worktechTypes,topImage,skillCardCol, urls} from './type';
export const webTitle: string = "Jiro's Portrait Site";

export const url: urls= {
    urlBlog:"https://www.s-gakuenblog.com/",
    urlGit:"https://github.com/POD-azlamarhyu",
    urlTwitter:"https://twitter.com/Inc_capitalist",
};

export const copyright: string = "shell varng 2022";

export const topImages:topImage[] = [
    {   
        id:0,
        image:require("../../public/topimage1.png").default,
    },
    {   
        id:1,
        image:require("../../public/topimage2.png").default,
    },
    {   
        id:2,
        image:require("../../public/topimage3.png").default,
    },
    {   
        id:3,
        image:require("../../public/topimage4.png").default,
    }
];

このファイルは今後も編集をいたしますが、それはその都度、解説していきます。現段階では、これのみで大丈夫です。

ポートフォリオ作成 フッター

続いてフッターを作ります。

先程作成した header.tsx ファイルと同じディレクトリ内に footer.tsx を作ってください。

import React from "react";
import CopyrightIcon from '@mui/icons-material/Copyright';
import LibraryBooksIcon from '@mui/icons-material/LibraryBooks';
import GitHubIcon from '@mui/icons-material/GitHub';
import TwitterIcon from '@mui/icons-material/Twitter';
import {url} from '../../api/variable';

import { copyright } from "../../api/variable";



const Footer:React.VFC = () => {

    const openUrl = (n:number) =>{
        if(n === 0){
            window.open(url.urlGit,"_blank");
        }else if(n===1){
            window.open(url.urlTwitter,"_blank");
        }else{
            window.open(url.urlBlog,"_blank");
        }
    }

    return(
        <>
            <footer className="flex justify-center bg-gray-700 text-white">
                <div className="mx-6 my-2">
                    <CopyrightIcon fontSize="large"/>{copyright}
                </div>
                <div className="mx-6 my-2 ">
                    <GitHubIcon 
                        className="mx-3 cursor-pointer"
                        fontSize="large"
                        onClick={() => openUrl(0)}
                    />to github
                </div>
                <div className="mx-6 my-2 ">
                    <TwitterIcon
                        className="mx-3 cursor-pointer"
                        fontSize="large"
                        onClick={() => openUrl(1)}
                    />to twitter
                </div>
                <div className="mx-6 my-2">
                    <LibraryBooksIcon
                        className="mx-3 cursor-pointer"
                        fontSize="large"
                        onClick={() => openUrl(2)}
                    />to blogsite
                </div>
            </footer>
        </>
    );
}

export default Footer;

こちらが、サイトの最も下に表示されるフッターとなります。フッターにはSNSアカウントやGithubへのリンクで飛べるようになっております。

ポートフォリオ作成 Topページ

では、今回のメインであるTopページを作成していきます。
organisms/ ディレクトリ内に top.tsx ファイルを作成します。その top.tsx ファイルを次のように編集します。


import Image from "next/image";
import React from "react";
import Header from './header';
import Footer from './footer';
import {topImages} from '../../api/variable';
import { topImage } from "../../api/type";



const Top:React.VFC = () => {

    return(
        <>
            <Header />
            {
                topImages.map((content:topImage) => {
                    return (
                        <div className="m-0 p-0 bg-gray-700" key={content.id}>
                            <div className="m-0 p-0">
                                <img src={content.image.src}/>
                            </div>
                        </div>
                    );
                })
            }
            <Footer />
        </>
    );
}

export default Top;

Topページは主に画像を用いて作成していきます。
画像については、皆様のお好きな画像を4枚ほどご用意ください。用意できましたら、画像は ./public/ディレクトリ内に配置してください。

画像を配置しましたら、variable.ts ファイルに読み込む画像についての配列を作成しています。topImages 変数がそれになります。今回は複数の画像をmapメソッドで連続して出力します。変数の配列をいじれば、表示する画像の数を減らしたり増やすことが可能です。

//(再掲)
export const webTitle: string = "Jiro's Portrait Site";

export const url: urls= {
    urlBlog:"https://www.s-gakuenblog.com/",
    urlGit:"https://github.com/POD-azlamarhyu",
    urlTwitter:"https://twitter.com/Inc_capitalist",
};

export const copyright: string = "shell varng 2022";

export const topImages:topImage[] = [
    {   
        id:0,
        image:require("../../public/topimage1.png").default,
    },
    {   
        id:1,
        image:require("../../public/topimage2.png").default,
    },
    {   
        id:2,
        image:require("../../public/topimage3.png").default,
    },
    {   
        id:3,
        image:require("../../public/topimage4.png").default,
    }
];

このページに、先ほど作成したヘッダー・フッターを読み込むことでコンポーネントを再利用することが可能です。

今回はTypeScriptで作成していますので、型指定をしていきます。型指定をするため、その型を宣言するための専用のファイルを作ります。
./app/pages/api/type.ts を作成してください。場所はpages/api ディレクトリ内に作成してください。

export type importImage = {
    src : string
    height: number
    width: number
    blurDataURL: string
};

export type topImage = {
    id: number;
    image: any;
}

export type urls = {
    urlBlog:string;
    urlGit:string;
    urlTwitter:string;
}

TypeScriptはほとんどJavaScriptと文法的には代わりはありません。TypeScriptは型の指定のみが変わったところです。

TypeScriptについての詳しい解説は下記記事をご参照ください。

最後に、作成したウェブページを表示できるようにします。
プロジェクト作成時に自動で生成される ./app/pages/index.tsx ファイルを編集します。

import Head from 'next/head';
import React from 'react';
import Top from './components/organisms/top';


const Home = () => {
  return (
    <>
      <Head>
        <title>portrate</title>
        <meta charSet='utf-8' />
        <meta name='viewport' content='minimum-scale=1,initial-scale=1,width=device-width'/>
      </Head>
      <Top />
    </>
  )
}

export default Home;

このファイルは実際にWebページとして表示される部分の大本となります。
プロジェクトを作成すると、様々なファイルが生成されます。初期状態で実際に編集するファイルはこれとCSSファイルくらいで、あとは構う必要はないファイルです。

ポートフォリオサイト 実行

ここまでできましたら、実際にサイトを動かしてみましょう。

$ npm run dev

上記のコマンドを実行してください。
上記のコマンドを実行しましたら、次のURLにアクセスしてください。

http://localhost:3000

みなさんがNextJSで開発する時、使用するポート番号は初期状態で3000です。設定によってこの番号を変更することが可能です。

アクセスすると、ページが表示されるはずです。

まとめ

では、今回のまとめに入ります。
今回は、NextJSのチュートリアルとして、初学者の方向けにポートフォリオ作成、そのうちの環境構築とTopページ作成の解説をいたしました。

次回は、Aboutページについての解説をする予定です。

今回はここまでとなります。
お疲れさまでした。

タイトルとURLをコピーしました