開発者ポートフォリオとは、スキルや経験を紹介するもので、作品のサンプルやプロジェクトなどを掲載することができます。これをしっかりと構築することで、仕事や案件を探す際に他の候補者に差をつけることが可能です。しかし、それだけではありません。ポートフォリオは、ネットワーキング、学習の記録、特定のトピックに関するブランディングにおいても重要な意味を持ちます。
今回の記事では、Next.jsを使用して開発者ポートフォリオを構築し、GitHubリポジトリからKinstaのアプリケーションホスティングプラットフォームに直接デプロイする方法をご紹介します。サービスを素早く公開するのに便利な無料の「.kinsta.app」ドメインが利用可能です。
Next.jsを使って今回構築する開発者用ポートフォリオのデモはこちらから確認できます。
このプロジェクトのGitHubリポジトリはこちらにご用意しています。こちらのテンプレートを使って「Use this template」>「Create a new repository」を選択すると、利用を始めるのに必要なコードが新規リポジトリにコピーできます。スタイル、Font Awesome CDNのリンク、画像、基本構造などのコードが含まれます。
前提条件
今回の説明はハンズオン形式です。すでに以下を満たしていると理想です。
- HTML、CSS、JavaScriptの基礎知識
- React(そして可能であればNext.js)についての基礎知識
- Node.jsとnpm(Node Package Manager)またはyarnがPCにインストールされていること
Next.jsの特徴
Next.jsはReactベースのオープンソースJavaScriptライブラリフレームワークです。さまざまなウェブ開発プロジェクトで使用し、サーバーサイドレンダリングと静的アプリケーションの構築を簡素化することができます。Reactの優れた機能を活用し、レンダリング性能を最適化することでプロセスを整え、ユーザー体験の向上まで実現可能です。Next.jsの一般的な使用例には、以下のようなものがあります。
- 静的なウェブサイトの構築:Next.jsを使って、この解説記事で紹介するように、開発者ポートフォリオサイトを素早くデプロイすることができます。メンテナンスが最小限で済む静的ウェブサイトの構築に向いています。
- 動的なウェブサイトの構築:Next.jsで、ユーザーとのインタラクションやサーバーサイドのデータ取得に基づいてコンテンツを変更する、動的なウェブサイトを作成することができます。
- ECサイトの構築:Next.jsは、SEOやパフォーマンス向上を考慮しサーバーサイドレンダリングを必要とするECサイトの構築に適しています。
- プログレッシブウェブアプリケーション(PWA)の構築:Next.jsは、ネイティブアプリのように機能し、ユーザーのデバイスにインストールできるウェブアプリケーションであるPWAの構築をサポートしています。
Next.jsの開発環境を構築する方法
Next.jsの開発環境を構築するには、まずNode.jsをPCにインストールします。npx
コマンドを使用して、npmパッケージをシステム上にグローバルにインストールすることなく実行するためのものです。これが済んだら、次のコマンドを実行してNext.jsのプロジェクトを作成します。
npx create-next-app@latest my-portfolio
プロンプトが表示され、追加の依存関係を確認するよう求められます。その後、npm run dev
を実行して、アプリをlocalhost:3000で利用できるようにします。
npx
コマンドでNext.jsプロジェクトを作成すると、自動的に次のようなメインディレクトリを持つフォルダ構造が雛形として採用されます。
- pages:このフォルダには、アプリケーションのページが含まれており、ファイル名に基づいて自動的にルーティングされます。例えば、pages/index.jsはホームページ、pages/about.jsはサイト紹介ページになります。
- public:このフォルダには、画像、フォント、その他のアセットなど、直接配信することのできる静的ファイルが格納されます。
- components:このフォルダは任意で、アプリケーション全体で使用できる再利用可能なUIコンポーネントを保存するためのものです。
- styles:このフォルダも任意で、アプリケーション全体に適用できるグローバルスタイルが格納されます。
その他のディレクトリやファイルも、特定の構成や機能に応じて生成されますが、とりあえず上記が基本的なNext.jsプロジェクトの中核になります。
今回の説明では、構築したものはすべてインデックスページ(1ページのウェブサイト)に表示され、ヒーロー(Hero)、サイト紹介(About)、プロジェクト(Projects)など、さまざまなセクション分けを行いそこにコンポーネントを組み込んでいきます。
Next.jsでレスポンシブな開発者ポートフォリオを構築する方法
ポートフォリオは、通常、次のような要素で構成されます。
- ナビゲーションバー
- ヒーロー
- サイト紹介/About
- スキル
- プロジェクトや作品
- お問い合わせ
- フッター
ポートフォリオに複数のページがある場合、ナビゲーションバーとフッターは、すべてのページに表示する必要がありますが、これはNext.jsでのレイアウト定義により実装できます。
Next.jsでレイアウトを定義する
Next.jsでは、レイアウトという概念で、サイトの各ページに表示するコンポーネントの構造を定義することができます。レイアウトには通常、すべてのサイトページで表示されるヘッダー、ナビゲーションメニュー、フッターなどの要素があります。
まず、Next.jsプロジェクトのsrc(ソース)ディレクトリに、componentsフォルダを作成します。次に、レイアウトで使用するNavbarコンポーネントとFooterコンポーネントを作成します。
Navbar.jsxのNavbarコンポーネントは以下の通りです。
// components/Navbar.jsx
import Link from "next/link";
const Navbar = () => {
return (
<div className="nav-container">
<div className="logo">
<Link href="/">
ジョーのポートフォリオ
</Link>
</div>
<a href="" className="cta-btn">履歴書</a>
</div>
)
}
export default Navbar;
そして、Footer.jsxのFooterコンポーネントはこのようになります。
// components/Footer.jsx
const Footer = () => {
return (
<>
<hr/>
<div className="footer-container">
<p>
© {new Date().getFullYear()} ジョエルのポートフォリオ
</p>
<div className="social_icons">
<a
href="https://twitter.com/olawanle_joel"
aria-label="Twitter"
target="_blank"
rel="noopener noreferrer"
>
<i className="fa-brands fa-twitter"></i>
</a>
<a
href="https://github.com/olawanlejoel"
aria-label="GitHub"
target="_blank"
rel="noopener noreferrer"
>
<i className="fa-brands fa-github"></i>
</a>
<a
href="https://www.linkedin.com/in/olawanlejoel/"
aria-label="LinkedIn"
target="_blank"
rel="noopener noreferrer"
>
<i className="fa-brands fa-linkedin"></i>
</a>
</div>
</div>
</>
)
}
export default Footer;
注)Font Awesomeのアイコンを使用するには、プロジェクトにFont Awesomeをインストールするか、そのCDNを使用する必要があります。CDNリンクは、_document.jsファイルに次のように記述します。
// pages/_document.js
import { Html, Head, Main, NextScript } from 'next/document';
export default function Document() {
return (
<Html lang="en">
<Head>
<meta charSet="utf-8" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css"
integrity="sha512-MV7K8+y+gLIBoVD59lQIYicR65iaqukzvf/nwasF0nqhPay5w/9lJmVM2hMDcnK1OnMGCdVK+iQrJ7lzPJQd1w=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
注)CDN経由でFont Awesomeの別のバージョンにリンクする場合には、そのリリースにあわせたintegrity
ハッシュを記述する必要があります。
レイアウトに必要なコンポーネントを作成できたので、今度はLayoutコンポーネント自体を作成します。このLayoutコンポーネントで、各ページをラッピングして表示することになります。
Layoutコンポーネント内でchildrenを受け付けることができます。
// components/Layout.jsx
import Navbar from './navbar';
import Footer from './footer';
const Layout = ({ children }) => {
return (
<>
<Navbar />
<main>{children}</main>
<Footer />
</>
)
}
export default Layout;
ここまでで、Navbar、Footer、そして、childrenを組み込むかたちでLayoutコンポーネントを作成しました。これで、各ページのコンテンツをLayoutでラッピングする作業に進むことができます。この設定は、_app.jsファイルで行います。
// pages/_app.js
import '@/styles/globals.css';
import Layout from '../components/layout';
export default function App({ Component, pageProps }) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
);
}
これで、ポートフォリオのレイアウトが作成できました。このポートフォリオでは、Next.jsと、ウェブサイトをKinstaでデプロイする方法に重点を置いています。そのため、styles/globals.cssファイルのスタイルはそのままコピーしてご利用ください。開発者モードでポートフォリオサイトを起動すると、アプリのレイアウトが以下のように表示されるはずです。
さて、次はポートフォリオサイトにコンテンツを追加していきます。
ポートフォリオ各セクションの構築
開発者ポートフォリオの各セクションに個別のコンポーネントを作成できるようになりました。コンポーネントはすべてNext.jsプロジェクトのインデックスページにインポートされ、npm run dev
でプロジェクトを起動したときに表示されます。
Heroコンポーネント
Heroコンポーネントは、Navbarの下にある最初のセクションで、その主な目的は、サイト訪問者の注意を引き、ウェブサイトやアプリケーションの役割を簡単に伝えることです。
// components/Hero.jsx
import Image from "next/image";
const Hero = () => {
return (
<div className="hero-container">
<Image src='/images/profile.jpeg' className="profile-img" width={300} height={300} alt="Joe's personal headshot" />
<div className="hero-text">
<h1>こんにちは、ジョーです👋</h1>
<p>
ナイジェリアのラゴスを拠点とするソフトウェア開発者です。卓越したウェブサイトやアプリケーション、またその間にあるあらゆるものの構築(時にはデザイン)を専門としています。
</p>
<div className="social-icons">
<a
href="https://twitter.com/olawanle_joel"
aria-label="Twitter"
target="_blank"
rel="noopener noreferrer"
>
<i className="fa-brands fa-twitter"></i>
</a>
<a
href="https://github.com/olawanlejoel"
aria-label="GitHub"
target="_blank"
rel="noopener noreferrer"
>
<i className="fa-brands fa-github"></i>
</a>
<a
href="https://www.linkedin.com/in/olawanlejoel/"
aria-label="LinkedIn"
target="_blank"
rel="noopener noreferrer"
>
<i className="fa-brands fa-linkedin"></i>
</a>
</div>
</div>
</div>
)
}
export default Hero;
上記のコードでは、画像の追加に、HTMLのimg
タグの代わりにNext.js Imageコンポーネントを使用しています。これは、画像の自動最適化やリサイズなどを可能にするための配慮です。
また、Aboutコンポーネントには、開発者の簡単な自己紹介と、Font AwesomeによるSNSアイコン(SNSアカウントにリンクする)を追加しています。
Heroコンポーネントはこのような見た目になります。
Heroコンポーネントにさらにコンテンツを追加したり、styles/globals.cssファイルのスタイルを微調整したりして、好みの見た目に仕上げることができます。
Aboutコンポーネント
Aboutコンポーネントは、ポートフォリオサイトを訪れた人に、サイトの意味やあなたについて、もう少しだけ詳しく説明するためのものです。分量が多くなる場合には、たとえば自己紹介ページを別に作成して、このセクションに「もっと詳しく」などのボタンを配置することもできます。
// components/About.jsx
import Image from "next/image";
const About = () => {
return (
<div className="about-container">
<h2>自己紹介</h2>
<div className="flex-about">
<div className="about-text">
<p>
開発者として、複雑な問題に対して簡潔かつ効果的なソリューションを生み出すことに常に情熱を注いできました。HTML、CSS、JavaScriptなどのウェブ技術を中心に、ソフトウェア開発の基礎をしっかりと身につけています。アプリケーションのフロントエンドとバックエンドの両方に携わり、パフォーマンスを最適化し、ユーザーエクスペリエンスを改善し、高い水準のコードを確保する方法を常に模索しています。
</p>
<p>これまでのキャリアを通じて、シンプルな静的ウェブサイトから複雑なエンタープライズレベルのアプリケーションまで、幅広いプロジェクトに携わってきました。React、Angular、Vue.js、Node.js、Laravelなど、さまざまな開発ツールやフレームワークの使用経験があります。常に新しい技術を学び、研究することに貪欲で、自らのスキルや知識を磨く機会を絶えず求めています。</p>
</div>
<div className="about-img">
<Image src='/images/about.jpeg' className="profile-img" width={300} height={500}/>
</div>
</div>
</div>
)
}
export default About;
上記のコードには、私の開発の経験についての簡単な説明と画像を配しています。このAboutセクションの見た目はこのようになります。
当然、スタイルに手を加えたり、画像を増やしたり、調整の可能性はあなた次第です。
Skillsコンポーネント
スキル紹介のコンポーネントには、開発に使用している技術や、過去に仕事で利用したことのある言語などを掲載することができます。
外部ファイルで配列を作成し、コンポーネントにインポートすることで、同様のコードを重複させることなくループさせることができるため、メンテナンスが容易になります。
// components/Skills.jsx
const Skills = () => {
return (
<div className="skills-container">
<h2>スキル</h2>
<div className="grid-skills">
<div className="skill-card html">
<i className="fa-brands fa-html5 html-icon"></i>
<p>HTML</p>
</div>
<div className="skill-card css">
<i className="fa-brands fa-css3-alt css-icon"></i>
<p>CSS</p>
</div>
<div className="skill-card js">
<i className="fa-brands fa-js-square js-icon"></i>
<p>JavaScript</p>
</div>
<div className="skill-card react">
<i className="fa-brands fa-react react-icon"></i>
<p>React</p>
</div>
<div className="skill-card node">
<i className="fa-brands fa-node-js node-icon"></i>
<p>Node</p>
</div>
<div className="skill-card python">
<i className="fa-brands fa-python python-icon"></i>
<p>Python</p>
</div>
</div>
</div>
)
}
export default Skills;
上記のコードでは、各スキルごとにカードが作成され、各カードにはfont-awesomeのアイコンと技術名が保持されます。さらにスタイルを追加したり、コードを微調整して、見た目をもっと魅力的に調整することもできるでしょう。
Projectsコンポーネント
プロジェクトは、開発者ポートフォリオの中で重要なセクションのひとつです。開発者のスキルと能力を具体的に証明するものであり、知識を実務に応用する能力を証明できます。
各プロジェクトには、プロジェクトの簡単な説明、ソースコードのリンク(ここではGitHubのリンクを使用しています)、その他言及しておきたい情報を記載しています。
各プロジェクトの詳細を保持する配列を作成し、それをコンポーネントにインポートすることで、ハードコーディングによる記述を避けることができます。
プロジェクトデータの配列を格納するdata.jsファイルを作成します。このファイルは、componentsフォルダまたはpages/apiフォルダに保存することができます。今回のデモでは、componentsフォルダに格納することにします。この配列は、各プロジェクトごとにオブジェクトを保持するもので、そのオブジェクトにはプロジェクト名、説明、GitHubリンクが記述されます。
// components/data.js
export const projectData = [
{
id: 1,
title: 'ToDoリストアプリ',
description:
'JavaScriptで作ったシンプルなTodoリストアプリです。すべてのデータがlocalstorageに保存されます。予定をリストアップしチェックしながら実行するのに一役買います。',
gitHubLink: 'https://github.com/olawanlejoel/Todo-List-App',
},
{
id: 2,
title: '読書記録アプリ',
description:
'JavaScriptで構築した、シンプルな本棚アプリです。今読んでいる本や読み終わった本の一覧を管理することができます。',
gitHubLink: 'https://github.com/olawanlejoel/Book-Library',
},
{
id: 3,
title: '名言生成サービス',
description:
'さまざまな著者によって記述された約1600の名言から言葉を生成するツールです。名言は自動でクリップボードにコピーされます。',
gitHubLink: 'https://github.com/olawanlejoel/random-quote-generator',
},
{
id: 4,
title: 'パスワード生成サービス',
description:
'ランダムなパスワードの生成に重宝します。パスワードの内容を選択でき、生成したパスワードはクリップボードにコピーできます。',
gitHubLink: 'https://github.com/olawanlejoel/Password-Generator',
},
{
id: 5,
title: 'Twitter UIクローン',
description:
'TailwindCSSとVue Jsで構築した、シンプルなTwitter UIクローンです。 Twitter UI のホームページのみを対象にしたものです。TailwindCSSの基本的な概念を理解するのにうってつけです。',
gitHubLink: 'https://github.com/olawanlejoel/TwitterUI-clone',
},
];
これで、簡単にループしてこのデータを利用するプロジェクトコンポーネントを作成することができます。JavaScriptの反復メソッドは何でも使えますが、今回は、データ配列をProjectsコンポーネントにインポートした後、JavaScriptのmap()
配列メソッドを使用してループ処理することにします。
// components/Projects.jsx
import { projectData } from './data.js';
const Projects = () => {
return (
<div className="projects-container">
<h2>プロジェクト紹介</h2>
<div className="projects-grid">
{projectData && projectData.map((project) => (
<div className="project-card" key={project.id}>
<div className="project-header">
<i className="fa-regular fa-folder-open folder-icon"></i>
<div className="small-icons">
<a href={project.gitHubLink}><i className="fa-brands fa-github"></i></a>
</div>
</div>
<h3>{project.title}</h3>
<p>{project.description}</p>
</div>
))
}
</div>
</div>
)
}
export default Projects;
上記のコードでは、配列をループしてすべてのプロジェクトをProjectsコンポーネントに出力することで、何度も同じコードを記述するのを回避し、プロジェクト記録の管理や追加を容易にしています。
Contactコンポーネント
ポートフォリオサイトですので、興味を持ってくれた人が連絡を取れるように、お問い合わせの手段を用意しておきたいものです。たとえばメールの送信が考えられます。Contactコンポーネントでこれを処理しましょう。
// components/Contact.jsx
const Contact = () => {
return (
<div className="contact-container">
<h2>お気軽にお問い合わせください</h2>
<p>お仕事のお誘い、ご質問、イベントでの講演依頼など、お気軽にお声がけください。できるだけ早くお返事差し上げます。</p>
<a href="mailto:[email protected]" className='cta-btn'>お問い合わせ</a>
</div>
)
}
export default Contact;
a
タグに実際のメールアドレスを記述してください。ボタンをクリックすることで、あなた宛のメール作成画面が、利用者のアプリケーションで立ち上がります。
これで、ポートフォリオアプリケーションのすべてのコンポーネントを作成することができました。次に、これらをインデックスページに取り込みます。pages/index.jsファイル(デフォルトで作成されます)に移動し、そのコードを次のように置き換えます。
// pages/index.js
import Hero from '@/components/Hero';
import About from '@/components/About';
import Skills from '@/components/Skills';
import Projects from '@/components/Projects';
import Contact from '@/components/Contact';
import Head from 'next/head';
const Home = () => {
return (
<>
<Head>
<title>ジョエルのポートフォリオ</title>
<meta name="description" content="ジョエルのポートフォリオ" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
<div>
<Hero />
<About />
<Skills />
<Projects />
<Contact />
</div>
</>
);
};
export default Home;
これでアプリケーションを実行すると、完全なポートフォリオウェブサイトが作成されます。最後に、アプリケーションをデプロイする前に、依存関係をインストールしましょう。Next.jsを使うメリットは、ファイルベースのルーティングや画像の最適化など、多くの機能が搭載されていることです。
画像の最適化は、Next.jsのImage
コンポーネントで処理されます。Imageコンポーネントを使用するアプリケーションを本番環境にデプロイする前に、sharpのインストールを強くお勧めします。ターミナルを開き、プロジェクトのディレクトリに移動したら、次のコマンドを実行してください。
npm i sharp
これでアプリケーションをデプロイすれば、Next.jsの最適化を用いて動作するようになります。
KinstaにNext.jsアプリケーションをデプロイする方法
素敵なポートフォリオが完成したら、今度はそれを公開しましょう。GitHubとKinstaのアプリケーションホスティングプラットフォームを使ってそれを実現する方法をご紹介します。
コードをGitHubにプッシュ
GitHubにコードをプッシュする方法はいろいろありますが、今回はGitを使ってみます。Gitは、コードの変更を管理し、プロジェクトで共同作業を行い、バージョン履歴を管理するのに非常に便利で、ソフトウェア開発の分野で広く使用されています。
以下の手順でGitHubにコードをアップロードすることができます。
まず、新しいリポジトリ(コードを保存するローカルフォルダのようなもの)を作成します。下の画像のように、GitHubのアカウントにログインして、画面右上の「+」ボタンをクリックし、ドロップダウンメニューから「New repository」を選択します。
次に、リポジトリに名前を付け、説明を追加し(任意)、リポジトリを公開または非公開にするかを選択します。そして、「Create repository」をクリックします。これで、GitHubリポジトリにコードをプッシュできるようになりました。
Gitでコードをプッシュするのに必要なのは、リポジトリURLだけです。このURLは、リポジトリのメインページ、 「Clone」または「Download」ボタンの下、あるいはリポジトリを作成した後に表示される画面で確認することができます。
ターミナルまたはコマンドプロンプトを開き、プロジェクトを格納するディレクトリに移動します。そして、次のコマンドを使用して、ローカルのGitリポジトリを初期化します。
git init
次に、以下のコマンドを使用して、コードをローカルのGitリポジトリに追加します。
git add .
上記のコマンドは、現在のディレクトリとそのサブディレクトリにあるすべてのファイルを新しいGitリポジトリに追加するものです。そして、次のコマンドで変更をコミットできます。
git commit -m "my first commit"
注)「my first commit」の部分は適宜、変更内容を説明するものに書き替えてください。
最後に、以下のコマンドでコードをGitHubにプッシュします。
git remote add origin [repository URL]
git push -u origin master
注)[repository URL]を実際のGitHubリポジトリのURLに置き換えてください。
ここまでの手順を完了すると、コードがGitHubにプッシュされ、リポジトリのURLからアクセスできるようになります。これで、リポジトリをKinstaにデプロイする準備が整います。
Kinstaにポートフォリオをデプロイ
Kinstaへのデプロイはわずか数分で完了します。コントロールパネル「My Kinsta」にログイン、またはアカウントの新規登録を行います。
次に、以下の簡単な手順でGitHub上でのKinsta認証を行います。
- 左サイドバーの「アプリケーション」をクリック
- 「サービスの追加」をクリック
- Next.jsアプリケーションをKinstaにデプロイしたいので、ドロップダウンメニューから「アプリケーション」をクリック
ポップアップが表示されるので、そこからデプロイするリポジトリを選択することができます。
リポジトリに複数のブランチがある場合は、デプロイするブランチを選択してください。また、このアプリケーションに名前をつけることができます。25箇所の中からデータセンターを選択します。Kinstaにより自動でstartコマンドが検出されます。
これでアプリケーションのデプロイが始まります。数分もあれば、デプロイされたアプリケーションのリンクが確認できるようになります。この例では「https://kinsta-developer-portfolio-ir8w8.kinsta.app/」となっています。
注)自動デプロイが有効になっているので、コードベースに変更を加えてGitHubにプッシュするたびに、Kinstaのシステムにより自動でアプリケーションが再デプロイされます。
まとめ
ウェブプロジェクトにNext.jsを使用するメリットはいくつもあります。まず、プリフェッチやコード分割などの機能により、ページの読み込み時間を短縮し、すぐにパフォーマンスを最適化することができます。次に、React開発者が慣れ親しんだ操作性を誇り、スタイル付きコンポーネントや最新のReactの機能など、注目の要素を広くサポートしています。
Kinstaは、従来のサーバーベースのホスティングや最新のサーバーレスプラットフォームなど、Next.jsのさまざまなデプロイメントをサポートしています。フレームワークのパフォーマンス最適化などの強みをフル活用しながら、好みに合わせて楽々デプロイすることができます。
今回の記事では、Next.jsを使ってレスポンシブなポートフォリオサイトを構築し、それをKinstaにデプロイする方法を手順を追ってご紹介しました。
Kinstaのアプリケーションホスティングは無料からお試し可能です。また、月額7ドルからのお求めやすいホビープランもご利用いただけます。
新しく開発したポートフォリオサイトに、好みの機能をどんどん追加してみてください。詳しい情報を別途ページに追加する、MDXでブログを統合する、アニメーションを実装するなどなど、可能性は無限大です。どんなプロジェクトやサイトができあがったか、以下のコメント欄でお聞かせください。
コメントを残す