Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8862

静的サイトジェネレータGatsbyを秒速で理解する

$
0
0

Gatsbyは静的サイトジェネレータフレームワークです。
フロントエンドを作成するときは最近はReactやvueなどのJSフレームワークを使って作成することが多いです。
メリットも大きい反面、webpackやparcelでbundle.jsを作成し、動的に仮想DOMツリーを生成するSPAの欠点として以下のことが挙げられます。

  • bundle.jsのファイルサイズが肥大化する(Code Splittingをして適切な分割読み込みや先読みである程度は回避できるが、依存ライブラリのファイルサイズが増えると厳しい)
  • そもそも仮想DOMツリーの構築に初回のJS実行時間がかかる(SSRをしてもバックエンドでJSによる動的にDOM構築をするため、遅い)
  • TwitterやFacebookシェアのOGPを実装しようとするとSSRの実装に迫られる(SSRは複雑度を増すのでSPAとしてはあまりやりたくない・・・)

静的サイトジェネレート(JAMStackというらしいです)はこれらの課題を解決する方法の1つです。
具体的にはReactなどの仮想DOMツリーを予めビルドして、htmlファイル(とわずかなJS実装)を生成します。
(ページ単位にhtmlを生成し、GatsbyのLinkコンポーネントを使うことでページ間のリンク構造も保ったまま出力されます)
特にブログやサービスのランディングページなどのパフォーマンスが求められる実装に威力を発揮します。
また、ページ単位にhtmlが出力されるため、OGPタグもページ別に割り当てることができます。
後は出力されたフォルダを丸ごとホスティングするだけで高速なレンダリングが実現できます。

個人的にはGatsbyでランディングページを作り、ウェブアプリケーション本体はReactなどのフレームワークで作り、SEO的観点や読み込みパフォーマンス遅延による初回ユーザ離脱防止のため、ランディングページの実装はアプリケーション本体から分離したほうがいいのではないかと最近は考えています。
(SSRしない)

Gatsbyのインストール

はじめにGastbyのサンプルプロジェクトの作成やGatsbyのビルドを行うため、Gatsbyコマンドをインストールします。

$ npm install-g gatsby-cli
or
$ yarn global add gatsby-cli

Gatsbyの構成

Gatsbyの構成に関してもうちょっと詳しい説明してくれている記事
参考:Reactベース静的サイトジェネレータGatsbyの真の力をお見せします

この記事では理解のため、Gatsbyのサンプルを作成します。

$ gatsby new <サイト名> <git clone元>

git clone元は未指定の場合、デフォルトでgatsby-starter-defaultからクローンされます。
(なれたら、自分用の雛形をgithubに作っておくと便利かもしれません)

Gatsbyプロジェクトの最低限の構成は次のようになります。
(gatsby-browser.js、gatsby-node.js、gatsby-ssr.jsはオプションなので一旦省略してます)

├── gatsby-config.js
├── public
├── src
│   ├── components
│   |   ├── image.js
│   |   ├── layout.css
│   |   ├── layout.js
│   |   └── seo.js
│   ├── images
│   └── pages
│       ├── 404.js
│       └── index.js
└── package.json

gatsby-config.jsにはgastbyのビルド設定(OGP情報のテンプレート、ファイル参照設定、プラグインの設定が記載されています)
publicフォルダにはビルド結果が出力されます。
srcフォルダに実装を行います。
pagesフォルダに表示する各ページの実装を行います。
ファイル名がそのままルーティングのパスとなります。ただしindex.jsのみパスは'/'、ルーティングが存在しない場合は404.jsのファイルに到達する
imagesフォルダにはデフォルトでページで使う画像ファイル一式を格納します。
componentsには各ページで使うコンポーネントの部品を格納します。

package.jsonは次のようになっています。
(必要最低限なライブラリ)

package.json
"dependencies":{"gatsby":"^2.19.7","gatsby-image":"^2.2.39","gatsby-plugin-manifest":"^2.2.39","gatsby-plugin-offline":"^3.0.32","gatsby-plugin-react-helmet":"^3.1.21","gatsby-plugin-sharp":"^2.4.3","gatsby-source-filesystem":"^2.1.46","gatsby-transformer-sharp":"^2.3.13","react":"^16.12.0","react-dom":"^16.12.0","react-helmet":"^5.2.1"}

react, react-domはReactフレームワークでの実装をしているため、使っています。
react-helmetはOGPなどのmetaデータの埋め込みを行うために使用しています。
gatsby-imageは画像、gatsby-plugin-sharp、gatsby-transformer-sharpは画像変換、
gatsby-source-filesystemは画像ファイル取得、
gatsby-plugin-manifestはPWA用manifestファイル生成用、
gatsby-plugin-offlineはServiceWorkerでのオフラインローディング用
でそれぞれ使われています。

gatsby-config.jsにビルド設定が記載されています。
siteMetadataはmetaタグに使う雛形のデータです。(適宜変更する
pluginsにgatsby関連のプラグイン設定を記述します。
gatsby-source-filesystemプラグインのoptions設定でsrc/imagesフォルダ以下が画像フォルダの参照先に設定されています。
gatsby-plugin-manifestプラグインのoptions設定にPWAのmanifest設定を行います。(適宜変更する
パラメータの設定はmanifest.jsonと同じです。

gatsby-config.js
module.exports={siteMetadata:{title:`Gatsby Default Starter`,description:`Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`,author:`@gatsbyjs`,},plugins:[`gatsby-plugin-react-helmet`,{resolve:`gatsby-source-filesystem`,options:{name:`images`,path:`${__dirname}/src/images`,},},`gatsby-transformer-sharp`,`gatsby-plugin-sharp`,{resolve:`gatsby-plugin-manifest`,options:{name:`gatsby-starter-default`,short_name:`starter`,start_url:`/`,background_color:`#663399`,theme_color:`#663399`,display:`minimal-ui`,icon:`src/images/gatsby-icon.png`,// This path is relative to the root of the site.},},// this (optional) plugin enables Progressive Web App + Offline functionality// To learn more, visit: https://gatsby.dev/offline// `gatsby-plugin-offline`,],}

サンプルではseo.jsにてOGPの設定を行っています。
Gatsbyはデータ関連の取得はgraphqlを介して行われます。
useStaticQueryでgatsby-config.jsのsiteMetadata設定を取得しています。

seo.js
/**
 * SEO component that queries for data with
 *  Gatsby's useStaticQuery React hook
 *
 * See: https://www.gatsbyjs.org/docs/use-static-query/
 */importReactfrom"react"importPropTypesfrom"prop-types"importHelmetfrom"react-helmet"import{useStaticQuery,graphql}from"gatsby"functionSEO({description,lang,meta,title}){const{site}=useStaticQuery(graphql`
      query {
        site {
          siteMetadata {
            title
            description
            author
          }
        }
      }
    `)constmetaDescription=description||site.siteMetadata.descriptionreturn(<HelmethtmlAttributes={{lang,}}title={title}titleTemplate={`%s | ${site.siteMetadata.title}`}meta={[{name:`description`,content:metaDescription,},{property:`og:title`,content:title,},{property:`og:description`,content:metaDescription,},{property:`og:type`,content:`website`,},{name:`twitter:card`,content:`summary`,},{name:`twitter:creator`,content:site.siteMetadata.author,},{name:`twitter:title`,content:title,},{name:`twitter:description`,content:metaDescription,},].concat(meta)}/>
)}SEO.defaultProps={lang:`en`,meta:[],description:``,}SEO.propTypes={description:PropTypes.string,lang:PropTypes.string,meta:PropTypes.arrayOf(PropTypes.object),title:PropTypes.string.isRequired,}exportdefaultSEO

image.jsでは画像ファイルを最適化して取得します。
こちらもgraphqlにてファイル取得し、Sharpで画像変換しています。

image.js
importReactfrom"react"import{useStaticQuery,graphql}from"gatsby"importImgfrom"gatsby-image"/*
 * This component is built using `gatsby-image` to automatically serve optimized
 * images with lazy loading and reduced file sizes. The image is loaded using a
 * `useStaticQuery`, which allows us to load the image from directly within this
 * component, rather than having to pass the image data down from pages.
 *
 * For more information, see the docs:
 * - `gatsby-image`: https://gatsby.dev/gatsby-image
 * - `useStaticQuery`: https://www.gatsbyjs.org/docs/use-static-query/
 */constImage=()=>{constdata=useStaticQuery(graphql`
    query {
      placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) {
        childImageSharp {
          fluid(maxWidth: 300) {
            ...GatsbyImageSharpFluid
          }
        }
      }
    }
  `)return<Imgfluid={data.placeholderImage.childImageSharp.fluid}/>
}exportdefaultImage

index.jsです。
ページ間の遷移はgastbyのLinkコンポーネントを使います。
ちなみにReactのstateをコンポーネント内に普通に持てます。(サンプルでは使ってませんが)

index.js
importReactfrom"react"import{Link}from"gatsby"importLayoutfrom"../components/layout"importImagefrom"../components/image"importSEOfrom"../components/seo"constIndexPage=()=>(<Layout><SEOtitle="Home"/><h1>Hipeople</h1>
<p>WelcometoyournewGatsbysite.</p>
<p>Nowgobuildsomethinggreat.</p>
<divstyle={{maxWidth:`300px`,marginBottom:`1.45rem`}}><Image/></div>
<Linkto="/page-2/">Gotopage2</Link>
</Layout>
)exportdefaultIndexPage

サンプルでは使われていませんが、DBのデータなどを動的に埋め込む際は
gatsby-node.jsに実装を記述します。
動的なページを生成する際に場合に威力を発揮します。
参考:GatsbyJS v2 はじめの一歩 (7) 動的にページを生成する

開発時

次のコマンドで開発モードで起動できます。

$ gatsby develop

ファイル編集時は自動的にブラウザ上で編集反映(hot reloading)してくれます。(イタレリツクセリ)

リリースビルド

次のコマンドでリリースビルドが行えます。(minifyや最適化)

$ gastby build

ビルド完了後、publicフォルダに生成されるので丸ごとサーバのpublicフォルダやGitHub Pages、Netlify、FireStorage、S3などにアップロードすればホスティング完了です。
localhostで確認するにはserveコマンドを使う方法があります。

$ gatsby serve

S3にアップロードするのであれば、gatsby-plugin-s3プラグインをつかえばさらに簡単にデプロイできます。
Deploying to S3/Cloudfront


Viewing all articles
Browse latest Browse all 8862

Trending Articles