Jamstackの世界へようこそ
Webアプリケーションの開発なんてやったことないし、そもそもJamstackって何?という方もいるかもしれません。WordPressからの乗り換えを検討している人もいるでしょう。そんな方々のために、どういった順番でJamstackを学べばいいのか、またどのようなドキュメントを読めばいいのかを解説します。
この記事では、2023年版のJamstack開発ロードマップを提供し、各ステップで学ぶべき要点とテクノロジーを紹介します。Jamstackの世界をより深く理解し、次のステップに進むための方向性を見つけることができるのではないかと思います。今回は書籍は紹介しません。なぜなら、Jamstackの世界は高速で日々変化しているから本の情報が新鮮ではない可能性があるからです。そのため、この記事ではオンラインリソースのみを紹介します。
基礎的な理解
まずは、Jamstackの基礎的な理解から始めましょう。JamstackはJavaScript、API、Markupの頭文字をとったもので、より良いパフォーマンス、高いセキュリティ、スケーラビリティ、そして開発者の体験の向上を目指したモダンなウェブ開発アーキテクチャです。
早速ですが、あなたが使用するメインのテクノロジーを選択します。JavaScriptのフレームワークやライブラリ、静的サイトジェネレータ、ヘッドレスCMSを選ぶことになるでしょう。
JavaScriptのフレームワークを学ぶ
JavaScriptのエコシステムには、React、Vue、Angularといった多くのフレームワークやライブラリがあります。それぞれのフレームワークやライブラリには独自の特性と利点がありますが、Jamstackでよく使用されるのはReactです。
type AppProps = {
message: string;
};
const App = ({ message }: AppProps) => {
return <div>{message}</div>;
};
以下は、JavaScriptとReactを学ぶためのオンラインリソースの一部です。これらのリソースは、入門者から上級者までのレベルに対応しています。
言語 | リソース名 | 説明 |
---|---|---|
JavaScript | MDN Web Docs: JavaScript | Mozillaが提供するリソースで、JavaScriptの基礎から高度なトピックまでカバーしています。 |
JavaScript | JavaScript.info | モダンなJavaScriptのチュートリアルで、基本的なトピックから詳細なトピックまで幅広く扱っています。 |
React | React公式ドキュメンテーション | Reactの公式ドキュメンテーションは、Reactの基本から高度なトピックまで詳しく解説しています。 |
React | Codecademy: Learn React.js | インタラクティブなオンラインコースで、Reactの基本的な概念を学べます。 |
React | Egghead.io: Start Learning React | ビデオベースのチュートリアルで、Reactの基本的な概念から応用までを学ぶことができます。 |
TypeScriptを学ぶ
JavaScriptのスーパーセットであるTypeScriptは、Jamstack開発において重要な役割を果たします。型安全性を提供することで、コードの品質を向上させ、バグの発生を減らすことができます。また、自動補完やリファクタリングなどの開発効率を向上させる機能も提供しています。
type UserProps = {
name: string;
age: number;
};
const User = ({ name, age }: UserProps) => {
return (
<div>
<p>{name}</p>
<p>{age}</p>
</div>
);
};
リソース名 | 説明 |
---|---|
TypeScript公式ドキュメンテーション | TypeScriptの公式ドキュメンテーションは、TypeScriptの基本から高度なトピックまで詳しく解説しています。 |
TypeScript Deep Dive by Basarat | このオンラインブックは、TypeScriptの基本から高度なトピックまで、非常に深く掘り下げています。 |
Understanding TypeScript - 2021 Edition (Udemy) | Udemyのこのコースは、TypeScriptの基本から応用までをカバーしており、理解を深めるための実践的なプロジェクトも含まれています。 |
静的サイトジェネレータの選定
静的サイトジェネレータもまた、Jamstackにおける重要な要素です。Next.jsやGatsbyなどのツールは、マークアップを事前に生成し、ブラウザにロードする時間を短縮するために使用されます。これにより、ユーザーはウェブサイトのパフォーマンスの向上を実感することができます。
import { GetStaticProps } from 'next';
type StaticProps = {
data: string;
};
export const getStaticProps: GetStaticProps<StaticProps> = async () => {
// Fetch data from an API
const data = 'Hello, Jamstack!';
return {
props: {
data,
},
};
};
type PageProps = {
data: string;
};
const Page = ({ data }: PageProps) => {
return <div>{data}</div>;
};
export default Page;
静的サイトジェネレータ | 説明 |
---|---|
Astro docs | 日本語版。Astroは静的サイトジェネレーターの新しい形態であり、部分的なリハイドレーションを可能にすることでパフォーマンスを最適化します。 |
Next.js docs | 英語版。日本語版は中途半端。Next.jsはReactベースのフレームワークで、サーバーサイドレンダリングと静的サイト生成をサポートします。 |
Gatsby docs | 英語版。日本語版なし。GatsbyはReactベースのフレームワークで、データをGraphQLを介して取得し、高性能なサイトを作成することができます。 |
Hugo docs | 英語版。HugoはGo言語で書かれた静的サイトジェネレータで、非常に高速なビルド時間が特徴です。 |
Nuxt.js docs | 日本語版。Nuxt.jsはVue.jsベースのフレームワークで、サーバーサイドレンダリングと静的サイト生成をサポートします。 |
ヘッドレスCMSの選定
コンテンツ管理もまた重要な部分で、ヘッドレスCMSがこの役割を果たします。ContentfulやStrapiなどのヘッドレスCMSを用いることで、コンテンツの作成、更新、削除を柔軟に行うことができます。また、これらのヘッドレスCMSはAPI経由でコンテンツを配信するため、どのフロントエンドフレームワークとも容易に統合することが可能です。
ヘッドレスCMS | 特徴 |
---|---|
Contentful | フルAPIベースのヘッドレスCMSで、高度なカスタマイズが可能。 |
Strapi | オープンソースのヘッドレスCMSで、自由度の高い設定と拡張性が特徴。 |
Netlify CMS | GitHub、GitLab、Bitbucketのリポジトリに直接インテグレートできるヘッドレスCMS。 |
Sanity | 完全にリアルタイムで動作し、柔軟なコンテンツ構造を実現可能なヘッドレスCMS。 |
DatoCMS | 高度にカスタマイズ可能なヘッドレスCMSで、リアルタイム更新とマルチリージョナル配信が可能。 |
UIコンポーネントの開発
UIコンポーネントの開発を効率化するツールは、コンポーネントの独立した開発とテスト、ドキュメンテーションの作成、再利用を可能にするためのものです。これらのツールを使用すると、デザイナーや開発者は各コンポーネントがどのように動作し、どのように見えるかを理解しやすくなり、アプリケーション全体の一貫性と品質を向上させることができます。
リソース名(リンク) | 説明 |
---|---|
Storybook docs | StorybookはUIコンポーネントを独立して開発し、テストするためのオープンソースツールです。 |
Styleguidist docs | React StyleguidistはReactコンポーネントのスタイルガイドを生成するツールです。 |
Bit docs | Bitはコードを共有し、再利用するためのツールです。 |
import React from 'react';
import { Button } from './Button';
export default {
title: 'Example/Button',
component: Button,
};
const Template = (args) => <Button {...args} />;
export const Primary = Template.bind({});
Primary.args = {
primary: true,
label: 'Button',
};
このコードでは、まずButtonコンポーネントをインポートします。次に、Storybookのデフォルトエクスポートを使って、ストーリーのメタデータを定義します。そして、テンプレート関数を作成して、その関数を使って具体的なストーリーを作成します。最後に、各ストーリーのpropsを定義します。
CSS-in-JSの活用
CSS-in-JSは、JavaScript内でCSSスタイルを宣言的に記述し、コンポーネントに直接適用する技術です。コンポーネントのスコープ内でスタイルを管理することで、スタイリングの再利用、テーマの適用、動的なスタイルの変更などを容易に行うことができます。また、サーバーサイドレンダリングやTypeScriptとの互換性も備えています。
リソース名(リンク) | 説明 |
---|---|
Styled-components docs | Styled-componentsは人気のあるCSS-in-JSライブラリで、JavaScriptでCSSを書くためのエレガントな方法を提供します。 |
Emotion docs | Emotionは高性能なCSS-in-JSライブラリで、styled APIとcss prop APIの両方をサポートします。 |
JSS docs | JSSはJavaScriptでCSSを記述するためのライブラリで、CSSの再利用、テーマ、プラグインなどの機能を提供します。 |
EmotionはCSS-in-JSライブラリの一つで、Reactコンポーネントにスタイルを適用するための便利な方法を提供します。Emotionはパフォーマンスに優れ、サーバーサイドレンダリングをサポートし、さらにTypeScriptとの親和性も高いという特徴があります。
Emotionにおいて三項演算子は、動的なスタイリングを行う際に非常に便利です。
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react'
type Props = {
isPrimary: boolean
}
const Component = ({ isPrimary }: Props) => {
return (
<div
css={css`
color: ${isPrimary ? 'hotpink' : 'blue'};
`}
>
Hello, Emotion!
</div>
)
}
このコードでは、isPrimary
というpropsを元に、文字色を動的に変更しています。isPrimary
が真であれば、文字色はhotpinkになり、偽であればblueになります。このように三項演算子を用いることで、propsの値に基づいた動的なスタイリングを実現できます。
Emotionは主に二つのスタイリング方法を提供します。一つは styled
コンポーネントを使用した方法、もう一つは css
propを使用した方法です。 Emotionの styled
コンポーネントは、スタイルを直接コンポーネントに適用することができます。スタイルはテンプレートリテラル内にCSSとして記述します。
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react'
import styled from '@emotion/styled'
const StyledDiv = styled.div`
color: hotpink;
`
const Component = () => {
return <StyledDiv>Hello, Emotion!</StyledDiv>
}
このコードは、色をhotpinkに設定した StyledDiv
というコンポーネントを作成します。そのコンポーネントは、Component
内で使用されています。
css
propを使用したスタイリング
また、Emotionでは css
propを用いてスタイルを適用することも可能です。これは、スタイルをインラインで定義し、それを直接コンポーネントに適用する方法です。
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react'
const Component = () => {
return <div css={css`color: hotpink;`}>Hello, Emotion!</div>
}
このコードは、色をhotpinkに設定したスタイルを、divタグに直接適用しています。
クライアントライブラリ
クライアントライブラリは、クライアント(通常はウェブブラウザ)からサーバーにデータを要求したり、サーバーからデータを受け取ったりするためのツールです。これらのライブラリは通常、HTTPリクエストを簡単に作成できるAPIを提供し、非同期通信を簡単に行えるようにします。これにより、開発者はサーバーとの通信に関する複雑な詳細を気にせずに、アプリケーションの主要な機能に集中できます。
リソース名(リンク) | 説明 |
---|---|
Apollo Client docs | Apollo ClientはGraphQLクエリを発行し、サーバーからのレスポンスを管理するためのJavaScriptライブラリです。 |
axios docs | axiosはPromiseベースのHTTPクライアントで、ブラウザとNode.jsの両方で動作します。 |
fetch API docs | Fetch APIはブラウザの組み込みAPIで、非同期HTTPリクエストを行うためのものです。 |
以下に、Apollo Clientを用いたGraphQLクエリの例を示します。
import { ApolloClient, InMemoryCache, gql } from "@apollo/client";
const client = new ApolloClient({
uri: "https://your-graphql-endpoint.com/graphql",
cache: new InMemoryCache()
});
client
.query({
query: gql`
query GetMyData {
myData {
id
name
}
}
`
})
.then(result => console.log(result));
このコードでは、まずApolloClientのインスタンスを作成し、GraphQLエンドポイントとキャッシュの設定を行います。次に、gql
タグ付きテンプレートリテラルを使ってGraphQLクエリを定義し、client.query
メソッドでクエリを実行します。最後に、クエリの結果をコンソールに出力します。
データベースプラットフォーム
Jamstackと相性が良いデータベースプラットフォーム(例えばPlanetScale)は、信頼性、拡張性、そしてセキュリティを高いレベルで提供します。これらのプラットフォームは、データの取得や保存を強化し、Jamstackアプリケーションに対して必要なデータベース機能を提供します。その結果、開発者はアプリケーションの機能に集中することができ、データベースのメンテナンスやスケーリングに関する心配をする必要がありません。
以下に、PlanetScaleを使用してデータベースからデータを取得する例を示します。
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient({
datasources: {
db: {
url: 'mysql://username:password@endpoint/databasename',
},
},
})
async function main() {
const allUsers = await prisma.user.findMany()
console.log(allUsers)
}
main()
.catch(e => {
throw e
})
.finally(async () => {
await prisma.$disconnect()
})
このコードでは、PrismaClientをインポートし、PlanetScaleのエンドポイントを指定して新しいPrismaインスタンスを作成します。その後、非同期関数を定義して、その中でPrismaのfindManyメソッドを使用してすべてのユーザーを取得します。
次に、PlanetScaleや類似のデータベースプラットフォームを学習するためのリソースを表形式で提供します。
リソース名(リンク) | 説明 |
---|---|
PlanetScale docs | PlanetScaleは、Vitess技術を使用して強力なデータベースプラットフォームを提供します。 |
Firebase Realtime Database docs | Firebase Realtime Databaseは、リアルタイムにデータを同期し、オフライン対応のモバイルアプリケーションを開発するためのNoSQLデータベースです。 |
Supabase docs | Supabaseは、リアルタイムの機能とPostgresの強力な機能を組み合わせたオープンソースのFirebase代替です。 |
ORM
データベースのクエリやマイグレーションを簡単に扱えるライブラリ(たとえばPrisma)は、データベースとの接続と操作を抽象化し、より安全で読みやすいコードを書くためのものです。これらのライブラリを使用すると、開発者はSQLクエリの作成や手動でのデータベーススキーマのマイグレーションから解放され、エラーの発生を防ぎながら効率的にデータベース操作を行うことができます。
以下に、Prismaを使用してデータベースからデータを取得する例を示します。
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
async function main() {
const allUsers = await prisma.user.findMany()
console.log(allUsers)
}
main()
.catch(e => {
throw e
})
.finally(async () => {
await prisma.$disconnect()
})
このコードでは、まずPrismaClientをインポートし、それを使用して新しいPrismaインスタンスを作成します。その後、非同期関数を定義して、その中でPrismaのfindManyメソッドを使用してすべてのユーザーを取得します。
リソース名 | 説明 |
---|---|
Prisma docs | Prismaはモダンなデータベースアクセス(ORM代替)のためのオープンソースのデータベースツールです。 |
TypeORM docs | TypeORMはTypeScriptとJavaScript(ES7、ES6、ES5)で動作するORMです。 |
Sequelize docs | SequelizeはpromiseベースのNode.js ORMで、Postgres、MySQL、MariaDB、SQLite、およびMicrosoft SQL Serverをサポートしています。 |
SaaS
Jamstackと相性が良いSaaS(Software as a Service)プラットフォーム(例えばAlgolia)は、検索エンジン、認証、CMSなどの機能をAPI経由で提供します。これらのサービスは、開発者が特定の機能を自己開発または自己管理せずに、アプリケーションに統合することを可能にします。SaaSは、開発者がアプリケーションの主要な機能に焦点を当てることができ、高度な機能を短時間で提供するための強力な手段となります。
以下に、Algoliaを使用して検索クエリを実行する簡単な例を示します。
import algoliasearch from 'algoliasearch';
const client = algoliasearch('YourApplicationID', 'YourAdminAPIKey');
const index = client.initIndex('your_index');
index
.search('query string')
.then(({ hits }) => {
console.log(hits);
})
.catch(err => {
console.log(err);
});
このコードでは、まずalgoliasearchをインポートし、その後Algoliaクライアントを初期化します。次に、initIndex
メソッドを使用して特定のインデックスに対する参照を取得し、そのインデックスで検索を実行します。
SaaSプラットフォームを学習するためのリソースです。
サービス名 | 主要な機能 | 特性 |
---|---|---|
Algolia | サイト内検索, リアルタイム検索, 検索API | スピードと柔軟性が強調されており、ユーザーが即座に探している情報を見つけることができます。 |
Mailchimp | メールマーケティング, 自動化サービス, オーディエンス管理 | 利用者がメールキャンペーンを作成、送信、分析できるようにする一方で、顧客データの管理と分析も提供します。 |
Typeform | オンラインフォームと調査, クイズ作成, フィードバック収集 | 使いやすさと視覚的な魅力に重点を置いており、利用者が対話的なフォームと調査を作成することができます。 |
認証サービス
以下に、Auth0, Netlify Identity, Magic の3つの認証サービスを比較した表を作成しました。
サービス名 | 主要な機能 | 特性 |
---|---|---|
Auth0 | ユーザー認証, 認可, シングルサインオン (SSO) | 高度にカスタマイズ可能で、多機能な認証プラットフォーム。さまざまなアイデンティティプロバイダとの統合をサポート。 |
Netlify Identity | ユーザー認証, ユーザー管理 | Netlify アプリケーションに統合され、シームレスな認証体験を提供する。Git ベースのワークフローとの相性が良い。 |
Magic | パスワードレス認証, ソーシャルログイン | パスワードレス認証にフォーカスし、開発者が容易に導入できる認証ソリューションを提供。 |
これらの認証サービスはそれぞれ異なる機能と特性を提供しており、アプリケーションの要件により選択することができます。
EコマースAPI
Snipcart、Commerce.js、Commerce Layerは、ウェブサイトに独自のカスタムEコマース機能を追加するためのヘッドレスショッピングカートとEコマースAPIを提供するツールです。これらは、既存のウェブサイトやアプリケーションに迅速にEコマース機能を統合することを可能にします。ヘッドレスEコマースアプローチを採用することで、開発者はユーザー体験を自由にカスタマイズできます。
<!-- Snipcart の例 -->
<button class="snipcart-add-item"
data-item-id="starry-night"
data-item-price="79.99"
data-item-url="/paintings/starry-night"
data-item-description="High-quality replica of The Starry Night by the Dutch post-impressionist painter Vincent van Gogh."
data-item-image="/assets/images/starry-night.jpg"
data-item-name="The Starry Night">
Add to cart
</button>
e-Commerce プラットフォームの比較
サービス名 | 主な機能 |
---|---|
Snipcart | 簡単に設定できるショッピングカート機能と製品管理機能を提供。HTMLとJavaScriptだけでショッピングカートを構築できる。 |
Commerce.js | 商品管理、カートとチェックアウト、顧客管理など、eコマース機能をすべてAPI経由で提供。開発者が必要とする柔軟性とカスタマイズ可能性を提供。 |
Commerce Layer | グローバルなeコマースをサポートするAPIファーストのプラットフォーム。マルチ通貨、マルチ言語、マルチウェアハウスに対応。 |
テスト
テストは、Jamstackアプリケーションの品質を確保するための重要なプロセスです。アプリケーションが期待通りに機能することを保証し、新たな機能の追加や既存のコードの変更によって予期せぬ問題が発生しないことを確認します。これにより、バグの早期発見と修正、そして最終的なユーザーエクスペリエンスの向上が可能となります。
ReactとJest、そしてReact Testing Libraryを使ったユニットテストの一例を以下に示します。このテストでは、<Button />
コンポーネントがクリックされたときに正しい動作を行うかを確認しています。
まず、テスト対象の<Button />
コンポーネントを定義します。
type ButtonProps = {
onClick: () => void;
children: React.ReactNode;
};
const Button = ({ onClick, children }: ButtonProps) => {
return <button onClick={onClick}>{children}</button>;
};
そして、以下のように<Button />
コンポーネントのテストを書きます。
import { render, fireEvent } from '@testing-library/react';
import Button from './Button';
test('calls onClick prop when clicked', () => {
const handleClick = jest.fn();
const { getByText } = render(<Button onClick={handleClick}>Click Me</Button>);
fireEvent.click(getByText('Click Me'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
このテストコードでは、まずjest.fn()
を使ってモック関数handleClick
を作ります。次に、render
関数で<Button />
コンポーネントをレンダリングし、fireEvent.click
でクリックイベントを発火します。最後に、expect
とtoHaveBeenCalledTimes
を使って、ボタンがクリックされたときにhandleClick
が正確に1回呼ばれることを確認します。
リソース名(リンク) | 説明 |
---|---|
Jest docs | JestはJavaScriptで書かれたコードのテストを行うためのライブラリで、ReactやNode.jsなど、さまざまなフレームワークやライブラリと一緒に使用することができます。 |
React Testing Library docs | React Testing Libraryは、Reactコンポーネントをテストするためのツールで、Jestと一緒に使用することが多いです。 |
Enzyme docs | EnzymeはReactコンポーネントのユニットテストを行うためのツールで、Jestと併用されることが多いです。 |
デプロイとパフォーマンス最適化
開発が完了したら、次はウェブサイトをデプロイするステップへと移ります。VercelやNetlifyなどのプラットフォームを利用することで、Jamstackアプリケーションのデプロイが容易になります。また、これらのプラットフォームはCDN(Content Delivery Network)を提供しているため、世界中どこからでも高速にウェブサイトにアクセスすることが可能となります。
さらに、パフォーマンスの最適化も重要なステップです。これには、画像の最適化、コードの分割、キャッシュの活用などが含まれます。これらの最適化手法を使用することで、ウェブサイトのロード時間を短縮し、ユーザー体験を向上させることができます。
デプロイ | 説明 |
---|---|
Vercel docs | Vercelは、Next.jsを開発した会社によるデプロイプラットフォームで、特にJamstackアプリケーションのデプロイに優れています。 |
Netlify docs | Netlifyは、静的サイトジェネレータを用いたサイトの自動ビルドとデプロイを容易にするプラットフォームで、多くのヘッドレスCMSとの連携も可能です。 |
Github Pages docs | GitHub Pagesは、GitHubリポジトリから直接ウェブページをホストするサービスで、特に静的コンテンツのホスティングに適しています。 |
Vercelは、特にNext.jsとの統合性が高く、Jamstack開発に最適なデプロイプラットフォームです。Vercelを使用すると、GitHubリポジトリと連携して自動デプロイを設定することができます。また、Vercelは静的生成(SSG)やサーバーサイドレンダリング(SSR)など、Next.jsの機能をフルに活用することが可能です。
GitHubの活用
GitHubは、ソースコードのバージョン管理はもちろん、チームでのコラボレーションを容易にする機能を提供しています。Pull Requestを用いたコードレビューやIssueを用いたタスク管理など、開発フローを効率化することができます。
以下に、GitHubとGitHub Actionsの学習リソースを表形式で提供します。
GitHubを学ぶ | 説明 |
---|---|
GitHub docs | GitHubの公式ドキュメンテーションは、レポジトリの作成から管理、コラボレーションのベストプラクティスまで、GitHubの使用方法を詳しく解説しています。 |
GitHub Actions docs | GitHub Actionsの公式ドキュメンテーションは、ワークフローの作成、アクションの使用、CI/CDパイプラインの設定など、GitHub Actionsの利用方法を詳しく説明しています。 |
GitHub Learning Lab | GitHub Learning Labは、対話形式のコースを通じてGitHubの基本やGitHub Actionsの使用方法を学べるプラットフォームです。 |
GitHub Actionsによる自動化
GitHub Actionsは、ソフトウェアのワークフローを自動化するためのツールです。これを用いると、テストの実行、デプロイの自動化、定期的なタスクのスケジューリングなど、様々なタスクを自動化することができます。これにより、開発者は手作業で行っていたタスクから解放され、より重要な開発作業に集中することができます。
name: Build and Deploy
on:
push:
branches:
- main
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎️
uses: actions/checkout@v2.3.1
- name: Install and Build 🔧
run: |
npm install
npm run build
- name: Deploy 🚀
uses: actions/setup-node@v2
with:
node-version: '14'
run: npm run deploy
まとめ
以上が、2023年版のJamstack開発に必要なロードマップの一部を紹介しました。Jamstack開発には、様々なツールやサービスが存在しますが、「これがベストだ」というものはありません。現時点で最高のサービスを組み合わせても1年後には下火になっていることも多いです。なので、色々試して要件に合ったものを選ぶことが大切です。