GatsbyとTypeScriptを使用して書店のランディングページを作成する方法
著者は、 Diversity in Tech Fund を選択して、 Write forDOnationsプログラムの一環として寄付を受け取りました。
序章
ランディングページは、商品やサービスを宣伝するWebページであり、顧客がサイトに到着したときにランディングする場所を提供します。 企業にとって、それらはオンライン広告やマーケティングメールのリンク先になることがよくあります。 商用ランディングページの主な目標は、訪問者を潜在的なクライアントまたは顧客に変えることです。 このため、ランディングページを作成することは、Web開発者にとって貴重なスキルです。
このチュートリアルでは、次の2つのテクノロジーを使用してランディングページを作成します。
- Gatsby 、静的Webサイトを生成するように設計されたReactベースのフロントエンドフレームワーク。 Gatsbyを使用すると、ランディングページをすばやく生成できます。これは、さまざまなプロジェクトの多数のランディングページを作成するときに役立ちます。
- TypeScript はJavaScriptのスーパーセットであり、ビルド時に静的型と型チェックを導入します。 TypeScriptは、コードが誇張される前にコードの問題を開発者に警告する強力な型付けシステムにより、JavaScriptの最も広く使用されている代替手段の1つになっています。 ランディングページの場合、TypeScriptは、売り込みテキストやサインアップフォームの入力など、動的な値に対して無効に入力されたデータを防ぐのに役立ちます。
このチュートリアルで作成するランディングページの例は、書店を宣伝し、ランディングページの次の一般的なコンポーネントを含みます。
- 書店のヘッダー
- ストアに関連するヒーロー画像
- 機能/サービスのリストを含む売り込み
- ビジネスに関するメーリングリストに読者を追加するために使用できる電子メールサインアップフォーム
サンプルプロジェクトは、チュートリアルが終了するまでに次の画像のようになります。
前提条件
- 開発サーバーを実行してパッケージを操作するには、マシンにNodeとnpmをインストールする必要があります。 このチュートリアルは、Node.jsバージョン14.17.2およびnpm6.14.13でテストされています。 macOSまたはUbuntu20.04にインストールするには、Node.jsをインストールしてmacOSにローカル開発環境を作成する方法またはPPAを使用したインストールセクションの手順に従います。 Ubuntu20.04にNode.jsをインストールするには。
- Gatsby CLIツールがインストールされ、
gatsby-starter-default
テンプレートから作成された新しいGatsbyサイトが必要になります。 最初のギャツビーウェブサイトの設定方法のステップ1に従って、新しいプロジェクトを開始します。 このチュートリアルでは、このプロジェクトをbookstore-landing-page
と呼びます。 - TypeScriptで動作するようにGatsbyプロジェクトを設定する必要があります。 [X5X] TypeScript を使用してGatsbyプロジェクトをセットアップする方法のステップ1からステップ4に従って、適切な依存関係をインストールし、新しい
tsconfig.json
ファイルを作成します。 TypeScriptでseo.tsx
ファイルをリファクタリングします。 - GatsbyはReactベースのフレームワークであるため、ReactコンポーネントおよびJSXに精通している必要があります。 このチュートリアルには、formsでのイベントハンドラーの使用も含まれます。 これらの概念などについては、React.jsシリーズのコーディング方法で学ぶことができます。
ステップ1—Header
およびLayout
コンポーネントのリファクタリング
このステップでは、前提条件のチュートリアルで作成したbookstore-landing-page
プロジェクトの既存のheader.tsx
およびlayout.tsx
コンポーネントをリファクタリングすることから始めます。 これには、デフォルトの型定義をカスタム型インターフェースに置き換え、一部のGraphQLクエリを改訂することが含まれます。 この手順を完了すると、ランディングページのヘッダーにページのタイトルと説明を入力し、将来のコンポーネントを実装するためのレイアウトコンポーネントを作成します。
Header
Header
コンポーネントは、ブラウザウィンドウの上部にページのタイトルと説明を表示します。 ただし、このコンポーネントをリファクタリングする前に、プロジェクトのルートディレクトリにあるgatsby-config.js
ファイルを開いて、サイトのメタデータを更新します。 後で、Layout
コンポーネントからgatsby-config.js
を照会して、このデータを取得します。
選択したテキストエディタでgatsby-config.js
を開きます。 エクスポートされたモジュールのsiteMetaData
で、title
とdescription
の値を、次の強調表示されたコードに示すように、書店の名前とビジネススローガンに変更します。
bookstore-landing-page / gatsby-config.js
module.exports = { siteMetadata: { title: `The Page Turner`, description: `Explore the world through the written word!`, author: `@gatsbyjs`, }, plugins: [ ...
これらの変更を行った後、gatsby-config.js
ファイルを保存して閉じます。
次に、bookstore-landing-page/src/components
ディレクトリ内で、header.tsx
ファイルを開きます。 ここから、<Header />
コンポーネントをリファクタリングして、デフォルトのPropTypes
の代わりにTypeScriptタイピングを使用します。 コードに次の変更を加えます。
bookstore-landing-page / src / components / header.tsx
import * as React from "react" import { Link } from "gatsby" interface HeaderProps { siteTitle: string, description: string } const Header = ({ siteTitle, description }: HeaderProps) => ( ... ) export default Header
Header
宣言の後にHeader.PropTypes
およびHeader.defaultProps
オブジェクトを削除し、siteTitle
を使用して、カスタムタイプのインターフェイスHeaderProps
に置き換えました。およびdescription
プロパティ。 次に、機能コンポーネントに渡される引数のリストにdescription
を追加し、それらをHeaderProps
タイプに割り当てました。 新しく定義されたHeaderProps
インターフェースは、<Layout/>
コンポーネントのGraphQLクエリから<Header/>
コンポーネントに渡される引数のカスタムタイプとして機能します。
次に、<Header />
コンポーネントのJSXで、開始header
タグのスタイルを変更して、背景色が青になり、テキストが中央揃えになるようにします。 siteTitle
を埋め込まれた<Link/>
コンポーネントに保持しますが、description
を別の<h3/>
タグに追加し、フォントの色を白にします。
bookstore-landing-page / src / components / header.tsx
... const Header = ({ siteTitle, description }: HeaderProps) => ( <header style={{ background: `#0069ff`, textAlign: `center`, }} > <div style={{ margin: `0 auto`, maxWidth: 960, padding: `1.45rem 1.0875rem`, }} > <h1 style={{ margin: 0 }}> <Link to="/" style={{ color: `white`, textDecoration: `none`, }} > {siteTitle} </Link> </h1> <h3 style={{ color: 'white' }}> {description} </h3> </div> </header> ) export default Header
これで、データがこのコンポーネントに渡されるときにインラインスタイルが設定されます。
変更内容をheader.tsx
ファイルに保存し、gatsby develop
を実行して、ブラウザのlocalhost:8000
に移動します。 ページは次のようになります。
説明がまだレンダリングされていないことに注意してください。 次のステップでは、これをlayout.tsx
のGraphQLクエリに追加して、確実に表示されるようにします。
<Header/>
コンポーネントの準備ができたら、ランディングページのデフォルトの<Layout/>
コンポーネントをリファクタリングできるようになりました。
Layout
<Layout />
コンポーネントはランディングページをラップし、サイトの将来のページのスタイルとフォーマットを共有するのに役立ちます。
このコンポーネントの編集を開始するには、テキストエディタでlayout.tsx
を開きます。 ファイルの最後にあるデフォルトのタイプ定義を削除し、import
ステートメントの後にLayoutProps
という名前の新しいインターフェイスを定義します。 次に、<Layout/>
に渡される引数にインターフェイスタイプを割り当てます。
bookstore-landing-page / src / components / layout.tsx
/** * Layout component that queries for data * with Gatsby's useStaticQuery component * * See: https://www.gatsbyjs.com/docs/use-static-query/ */ import * as React from "react" import { useStaticQuery, graphql } from "gatsby" import Header from "./header" import "./layout.css" interface LayoutProps { children: ReactNode } const Layout = ({ children }: LayoutProps) => { ... } default export Layout
インターフェイスは、ReactライブラリでインポートしたReactNode
タイプを使用します。 このタイプ定義は、ほとんどのReact子コンポーネントに適用されます。これは、<Layout/>
がデフォルトでレンダリングするものです。 これにより、<Layout/>
のカスタムタイプのインターフェイスを定義できるようになります。
次に、<Layout/>
コンポーネント内にあるデフォルトのGraphQLクエリを修正します。 siteMetaData
オブジェクト内に、gatsby-config.js
で設定したdescription
を追加します。 次に、siteTitle
と同様に、フェッチした値を新しいdescription
変数に格納します。
bookstore-landing-page / src / components / layout.tsx
... const Layout = ({ children }: LayoutProps) => { const data = useStaticQuery(graphql` query SiteTitleQuery { site { siteMetadata { title description } } } `) const siteTitle = data.site.siteMetadata?.title || `Title` const description = data.site.siteMetadata?.description || 'Description' ...
これで、description
を小道具としてレイアウトの返されたJSXの<Header/>
コンポーネントに渡すことができます。 description
は、HeaderProps
インターフェイスで必須プロパティとして定義されているため、これは重要です。
bookstore-landing-page / src / components / layout.tsx
... return ( <> <Header siteTitle={siteTitle} description={description}/> ... </> ) export default Layout
layout.tsx
ファイルを保存して終了します。
レイアウトの最終的な変更として、layouts.css
に移動し、ページのbody
のすべてのテキストを中央に配置して、スタイルを変更します。
bookstore-landing-page / src / components / layout.css
... /* Custom Styles */ body { margin: 0; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; color: hsla(0, 0%, 0%, 0.8); font-family: georgia, serif; font-weight: normal; word-wrap: break-word; font-kerning: normal; -moz-font-feature-settings: "kern", "liga", "clig", "calt"; -ms-font-feature-settings: "kern", "liga", "clig", "calt"; -webkit-font-feature-settings: "kern", "liga", "clig", "calt"; font-feature-settings: "kern", "liga", "clig", "calt"; text-align: center; } ...
layout.css
ファイルを保存して閉じ、開発サーバーを起動して、ブラウザーでサイトをレンダリングします。 これで、ヘッダーにレンダリングされたdescription
値が見つかります。
Gatsbyサイトのベースファイルをリファクタリングしたので、ページにヒーロー画像を追加して、顧客にとってより視覚的に魅力的なものにすることができます。
ステップ2—ヒーロー画像を追加する
ヒーロー画像は、ランディングページの商品やサービスをサポートするビジュアルです。 このステップでは、書店のランディングページの画像をダウンロードし、gatsby-plugin-image
プラグインの<StaticImage />
コンポーネントを使用してサイトにレンダリングします。
注:このプロジェクトはGatsbyバージョン3.9.0を使用しているため、非推奨のgatsby-image
パッケージを使用することはできません。 このパッケージはgatsby-plugin-image
に置き換えられました。 この新しいプラグインは、gatsby-plugin-sharp
の助けを借りて、処理機能を備えた応答性の高い画像をレンダリングします。
まず、自由に使用できる画像を提供するサイトUnsplashから本棚の画像をダウンロードします。
curl https://images.unsplash.com/photo-1507842217343-583bb7270b66 -o src/images/bookshelf.png
このコマンドは、curl
を使用してイメージをダウンロードします。 -o
フラグは、images
ディレクトリ内のbookshelf.png
という名前のファイルに設定した出力を示します。
次に、src/pages/index.tsx
ファイルを開きます。 Gatsbyのデフォルトのスターターテンプレートにはすでに<StaticImage/>
コンポーネントが含まれているため、新しくダウンロードした画像を指すように属性を置き換えます。
bookstore-landing-page / src / pages / index.tsx
import * as React from "react" import { StaticImage } from "gatsby-plugin-image" import Layout from "../components/layout" import Seo from "../components/seo" const IndexPage = () => ( <Layout> <Seo title="Home" /> <StaticImage src="../images/bookshelf.png" alt="Bookshelf hero image" /> </Layout> ) export default IndexPage
src
属性を追加して、Gatsbyをimages
ディレクトリ内の正しい画像に誘導し、次にalt
属性を追加して、画像の代替テキストを提供しました。
ファイルを保存して閉じてから、開発サーバーを再起動します。 これで、ダウンロードした本棚の画像が中央にレンダリングされます。
画像がサイトにレンダリングされたら、ページにコンテンツを追加することに進むことができます。
ステップ3—セールスピッチと機能コンポーネントの作成
ランディングページの次の部分では、書店の売り込みを保持する新しいコンポーネントを作成します。 これはあなたの顧客があなたの店に来るべき理由を説明します。
bookstore-landing-page/src/components
内で、salesPitchAndFeatures.tsx
という名前の新しいファイルを作成します。 新しいファイル内で、React
をインポートし、SalesPitchAndFeatures
という新しい機能コンポーネントを作成して、エクスポートします。
bookstore-landing-page / src / components / salesPitchAndFeatures.tsx
import * as React from "react" const SalesPitchAndFeatures = () => { <> </> } export default SalesPitchAndFeatures
このコンポーネントのインターフェイスには、string
タイプのオプションのsalesPitch
プロパティが含まれます。 タイプArray<string>
のfeatures
のリストもあります。これは必須です。
bookstore-landing-page / src / components / salesPitchAndFeatures.tsx
import * as React from "react" interface SalesPitchAndFeaturesProps { salesPitch?: string features: Array<string> } ...
salesPitch
とfeatures
のデータは、salesPitchAndFeatures.tsx
内にハードコーディングされますが、別の場所(gatsby-config.js
など)に保存してクエリを実行することもできます。 GraphQLで必要なデータ。 content
オブジェクトのタイプはSalesPitchAndFeaturesProps
になります。
bookstore-landing-page / src / components / salesPitchAndFeatures.tsx
... interface salesPitchAndFeaturesProps { salesPitch?: string features: Array<string> } const content: SalesPitchAndFeaturesProps = { salesPitch: "Come and expand your world at our bookstore! We are always getting new titles for you to see. Everything you need is here at an unbeatable price!", features: [ "Tens of thousands of books to browse through", "Engage with the community at a book club meeting", "From the classics to the newest publications, there's something for everybody!" ]} const SalesPitchAndFeatures = () => { return ( <> ...
salesPitch
プロップは文字列であり、features
プロップは文字列の配列であることに注意してください。これは、インターフェイスで設定した場合と同じです。
機能のリストを表示する機能も必要です。 showFeatures(f)
関数を作成します。
bookstore-landing-page / src / components / salesPitchAndFeatures.tsx
... const showFeatures: any = (f: string[]) => { return f.map(feature => <li>{feature}</li>) } const SalesPitchAndFeatures = () => { return ( <> ...
showFeatures
に渡される引数f
は、タイプArray<string>
であり、タイプstring
の機能の配列と一致しています。 レンダリングされたJSXに変換されたリストを返すには、.map()
配列メソッドを使用します。
return
ステートメントにコンテンツを入力し、divs
でラップして、スタイル設定にクラス名を割り当てます。
bookstore-landing-page / src / components / salesPitchAndFeatures.tsx
... const SalesPitchAndFeatures = () => { return ( <div className='features-container'> <p className='features-info'> {content.salesPitch} </p> <ul className='features-list'> {showFeatures(content.features)} </ul> </div> ) } export default SalesPitchAndFeatures
salesPitchAndFeatures.tsx
を保存して閉じます。
次に、layout.css
を開いて、<SalesPitchAndFeatures/>
コンポーネントで追加されたクラス名にスタイルを追加します。
bookstore-landing-page / src / components / layout.css
... .features-container { border: 1px solid indigo; border-radius: 0.25em; padding: 2em; margin: 1em auto; } .features-list { text-align: left; margin: auto; }
これにより、売り込みと機能のリストの周囲に境界線が追加され、要素間に間隔が追加されて読みやすくなります。
layout.css
を保存して閉じます。
最後に、このコンポーネントをランディングページにレンダリングします。 src/pages/
ディレクトリでindex.tsx
を開きます。 <SalesPitchAndFeatures/>
コンポーネントをレンダリングされたレイアウトの子に追加します。
bookstore-landing-page / src / pages / index.tsx
import * as React from "react" import { StaticImage } from "gatsby-plugin-image" import Layout from "../components/layout" import SalesPitchAndFeatures from "../components/salesPitchAndFeatures" import SEO from "../components/seo" const IndexPage = () => ( <Layout> <SEO title="Home" /> <div style={{ maxWidth: `450px`, margin: ' 1em auto'}}> <StaticImage src="../images/bookshelf.png" alt="Bookshelf hero image" /> <SalesPitchAndFeatures/> </div> </Layout> ) export default IndexPage
また、div
を追加して、画像と売り込みの両方にスタイリングを適用しました。
ファイルを保存して終了します。 開発サーバーを再起動すると、画像の下に売り込みと機能のリストが表示されます。
これで、ランディングページに売り込みがあり、潜在的な顧客になぜ彼らがあなたのビジネスに行くべきかを伝えるのに役立ちます。 次に、ランディングページの最後のコンポーネントであるEメールサインアップフォームを作成します。
ステップ4—サインアップフォームコンポーネントの作成
電子メールサインアップボタンは、ユーザーが電子メールアドレスを入力し、製品またはビジネスに関するその他のニュースや情報にサインアップできるようにする一般的なランディングページコンポーネントです。 これをランディングページに追加すると、ユーザーは顧客になるための実用的なステップを実行できます。
まず、bookstore-landing-page/src/components
にsignupForm.tsx
という名前の新しいファイルを作成します。 このコンポーネントにはカスタムタイプはありませんが、独自の特別なReactベースのタイプを持つイベントハンドラーがあります。
まず、<SignUpForm/>
コンポーネントとそのreturn
ステートメントをビルドします。ヘッダーは次のとおりです。
[label bookstore-landing-page/src/components/signupForm.tsx] import * as React from "react" const SignUpForm = () => { return ( <h3>Sign up for our newsletter!</h3> ) } export default SignupForm
次に、マークアップを追加して、onSubmit
属性を持つform
要素を作成します。この要素は、今のところnull
に初期化されています。 間もなくこれにイベントハンドラが含まれますが、今のところ、label
、input
、およびbutton
タグを使用してフォームの記述を終了します。
bookstore-landing-page / src / components / signupForm.tsx
import * as React from "react" const SignUpForm = () => { return ( <React.Fragment> <h3>Sign up for our newsletter!</h3> <form onSubmit={null}> <div style={{display: 'flex'}}> <input type='email' placeholder='email@here'/> <button type='submit'>Submit</button> </div> </form> <React.Fragment> ) } export default SignupForm
テキストフィールドにメールアドレスを入力し、レンダリングされたランディングページでサインアップをクリックしても、何も起こりません。 これは、フォームが送信されるたびにトリガーされるイベントハンドラーを作成する必要があるためです。 ベストプラクティスは、イベントハンドラーのreturn
ステートメントの外部に別の関数を作成することです。 この関数には通常、トリガーされたイベントを表す特別なe
オブジェクトがあります。
別の関数を作成する前に、関数をインラインで作成して、イベントオブジェクトの静的タイプを把握し、後でそのタイプを使用できるようにします。
bookstore-landing-page / src / components / signupForm.tsx
... return ( <React.Fragment> <h3>Sign up for our newsletter!</h3> <form onSubmit={(e) => null}> <div style={{display: 'flex'}}> <input type='email' placeholder='email@here' style={{width: '100%'}}/> <button type="submit">Submit</button> </div> </form> </React.Fragment> ) ... } export default SignupForm
Visual Studio Code のようなテキストエディターを使用している場合、e
パラメーターにカーソルを合わせると、TypeScriptの IntelliSense を使用して、予想されるタイプが表示されます。ケースはReact.FormEvent<HTMLFormElement>
です。
個別の関数の予想されるタイプがわかったので、次にこれを使用して、handleSubmit
と呼ばれる新しい個別の関数を作成します。
bookstore-landing-page / src / components / signupForm.tsx
import * as React from "react" const SignupForm = () => { const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => { e.preventDefault(); alert(alert('The submit button was clicked! You\'re signed up!')) } return ( <React.Fragment> <h3>Sign up for our newsletter!</h3> <form onSubmit={handleSubmit}> <div style={{display: 'flex'}}> <input type='email' placeholder='email@here'/> <button type='submit'>Submit</button> </div> </form> </React.Fragment> ) } export default SignupForm
handleSubmit
関数は、フォームが送信されたときにブラウザアラートをトリガーするようになりました。 これは一時的なプレースホルダーであることに注意してください。 ユーザーを実際にメーリングリストに追加するには、これをバックエンドデータベースに接続する必要がありますが、これはこのチュートリアルの範囲を超えています。
signupForm.tsx
ファイルを保存して閉じます。
次に、index.tsx
ファイルを開き、新しい<SignupForm/>
コンポーネントを追加します。
bookstore-landing-page / src / pages / index.tsx
import * as React from "react" import { StaticImage } from "gatsby-plugin-image" import Layout from "../components/layout" import SalesPitchAndFeatures from "../components/salesPitchAndFeatures" import SignupForm from "../components/signupForm" import Seo from "../components/seo" const IndexPage = () => ( <Layout> <Seo title="Home" /> <div style={{ maxWidth: `450px`, margin: ' 1em auto'}}> <HeroImage /> <SalesPitchAndFeatures /> <SignupForm /> </div> </Layout> ) export default IndexPage
ファイルを保存して終了します。
開発サーバーを再起動すると、完成したランディングページがブラウザに表示され、電子メールのサインアップボタンが表示されます。
これで、書店のランディングページのすべてのコアコンポーネントの構築が完了しました。
結論
Gatsbyは高速な静的Webサイトを作成し、TypeScriptではデータを静的に入力できるため、ランディングページを作成すると優れたユースケースになります。 その一般的な要素のタイプ(ヘッダー、ヒーロー画像、電子メールのサインアップなど)を形成して、データの形式が正しくないと、本番環境に入る前にエラーが発生するようにすることができます。 Gatsbyは、ページの構造とスタイルの大部分を提供し、その上に構築できるようにします。 この知識を使用して他のランディングページを作成し、他の製品やサービスをより迅速かつ効率的に宣伝できます。
TypeScriptの詳細については、 TypeScriptシリーズでコーディングする方法を確認するか、Gatsby.jsシリーズで静的Webサイトを作成する方法を参照してください。ギャツビーについて。