フロントエンド:静的サイトの更新にGatsby.jsとNode.jsを使用する

公開: 2022-03-11

一部のプロジェクト要件では、静的ページの生成で十分であるだけでなく、速度とスケーラビリティの点でも最も効率的です。

このシリーズの前半では、Node.js、Express、MongoDB、cron、Herokuを組み合わせて、毎日のスケジュールに従ってGitHubのAPIを使用するCI対応のバックエンドを提供しました。 これで、Gatsbyをミックスに追加して、静的ページ生成プロジェクトを完了する準備ができました。

フロントエンドの開発:それをギャツビーのウェブサイトにする

GatsbyのWebサイトはReactに基づいているため、Reactを使用してWebサイトを構築する方法に既に精通している場合に役立ちます。

スタイリングには、Bootstrap、reactstrap、react-markdownが好きでした。 GitHubのリリースノートはMarkdown形式で保存されているため、コンバーターが必要です。

静的ウェブサイトプロジェクトの構造

ファイル/フォルダの構造は次のようになります。

空のパブリックフォルダーとpackage.jsonなどのファイル用のsrcフォルダーを持つ標準のフロントエンドプロジェクトルート。 srcフォルダーの下には、global.cssのstylesサブフォルダーと、all-repositories.jsおよびrepository.jsのtemplatesサブフォルダーがあります。

これらのファイルは何のためのものですか? どれどれ:

  • env.developmentenv.productionは、環境変数の構成ファイルです。
  • all-repositories.jsテンプレートは、リポジトリのリストを含むホームページに使用されます。
  • repository.jsテンプレートは、特定のリポジトリの詳細を表示するために使用されます。
  • gatsby-node.jsは、バックエンドエンドポイントを使用し、 createPageメソッドを実行する場所です。
  • package.jsonには、いつものように、依存関係とプロジェクトのプロパティが含まれています。
  • global.cssはメインのスタイルシートファイルです。

GatsbyWebサイトの実装

バックエンドと同様に、フロントエンドのpackage.jsonに必要な依存関係を追加した後、 npm install (またはYarnがインストールされている場合はyarn )を実行します。

 { // ... "dependencies": { "axios": "^0.18.0", "bootstrap": "^4.3.1", "gatsby": "^2.0.0", "react": "^16.5.1", "react-dom": "^16.5.1", "react-markdown": "^4.0.6", "reactstrap": "^7.1.0" } // ... }

env.developmentファイルとenv.productionファイルには、対応する環境のバックエンドURLのみが含まれています。 前者は:

 API_URL=http://localhost:3000

…本番環境には次のようなものがあります。

 API_URL=https://[YOUR_UNIQUE_APP_NAME].herokuapp.com

gatsby-node.jsは、コードのビルド中に1回だけ実行されます。 したがって、ここでバックエンドから必要なすべての情報を収集する必要があります。 次に、応答をテンプレートで使用して、適切な静的ページを生成します。

この場合、 all-repositories.jsにはすべてのリポジトリが必要であり、 repository.jsには反復ごとに対応するリポジトリが必要です。 最後に、 pathフィールドの一部としてリポジトリのownernameのパラメータを渡して、ページパスを動的に生成できます。

 const axios = require('axios'); require("dotenv").config({ path: `.env.${process.env.NODE_ENV}` }); const getRepositoryData = async () => { console.log(process.env.API_URL); return axios.get(`${process.env.API_URL}/repositories`); }; exports.createPages = async ({ actions: { createPage } }) => { let repositories = await getRepositoryData(); repositories = repositories.data; // Create a page that lists all repositories. createPage({ path: `/`, component: require.resolve('./src/templates/all-repositories.js'), context: { repositories } }); // Create a page for each repository. repositories.forEach(repository => { createPage({ path: `/repository/${repository.owner}/${repository.name}`, component: require.resolve('./src/templates/repository.js'), context: { repository } }); }); };

all-repositories.jsrepository.jsの場合、スタイル設定を省略すると、 pageContextからデータを収集し、Reactでパラメーターを使用するときにそれを使用するだけです。

all-repositories.jsでは、 pageContextrepositoriesフィールドを次のように使用します。

 export default ({pageContext: {repositories}}) => ( // ... <ListGroup> {/* Because the repositories parameter is a list, we are iterating over all items and using their fields */} {repositories.map(repository => (repository.tagName && <ListGroupItem className="repository-list-item"> // ... <Row> {`${repository.repositoryDescription}`} </Row> // ... </ListGroupItem> ))} </ListGroup> // ... );

repository.jsについては、代わりにpageContextrepositoryフィールドを使用します。

 export default ({pageContext: {repository}}) => ( <div className="layout"> {repository.tagName && <ListGroupItem className="repository-list-item"> // ... <h1 className="release-notes">{`Release notes`}</h1> <hr/> {/* This the place where we will use Markdown-formatted release notes */} <ReactMarkdown source={`${repository.releaseDescription}`}/> </ListGroupItem> } // ... </div> );

ここで、バックエンドが稼働していることを確認します。 このプロジェクトでは、http:// localhost:3000として設定したことを思い出してください。

次に、フロントエンドプロジェクトのルートからgatsby developを実行し、http:// localhost:8000を開きます。

バックエンドにいくつかのリポジトリ(所有者/名前)を追加し、update-via-GitHub-API機能を少なくとも1回実行した場合は、次のように表示されます。

GitHubリポジトリのサンプルの基本情報を示す、アプリのホームページを一覧表示するリポジトリ

リポジトリの1つをクリックすると、次のように表示されます。

facebook /reactGitHubリポジトリに関する詳細情報を示すサンプルリポジトリ詳細ページ

上記の変更後、フロントエンドの実装が完了します。

すごい! 今、私たちはただ展開する必要があります。

フロントエンドの展開

この部分では、フロントエンドアプリケーションに変更を加える必要はありません。 Netlifyにデプロイするだけです。そこにアカウントが必要です。

ただし、最初に、コードをGitHub、GitLab、またはBitbucketにデプロイする必要があります。 バックエンドと同様に、コードをGitHubにデプロイしました。

次に、Netlifyにログインし、ダッシュボードの[Gitから新しいサイト]ボタンをクリックします。 画面の手順に従って、Gitプロバイダーを選択し、リポジトリを見つけます。

最後のステップとして、コードを正しく構造化した場合、Netlifyは自動的にビルドコマンドを設定し、次のようにディレクトリを正しく公開します。

Netlifyのビルドオプションの正しい設定:マスターをデプロイし、ビルドコマンドとして「gatsbybuild」を使用して、「public/」ディレクトリに公開します。

次に、「サイトのデプロイ」をクリックします。 ランダムに生成されたNetlifyサブドメインにサイトをデプロイしますが、いつでも変更できます。デプロイメントをhttps://sample-create-page-api-gatsby.netlify.comに変更しました。ここで、ライブデモを見つけることができます。完成したアプリの

ここまでは順調ですね。 ただし、これは静的ページアプリケーションであるため、最新の状態に保つために毎日再構築する必要があります。

ビルドフックを使用した毎日の更新

Netlifyのビルドフックはビルドトリガーとして機能するため、cronジョブの終了後にバックエンドからフックをトリガーできます。 これを行うには、最初にNetlifyでビルドフックを作成します。

「ビルドとデプロイ→継続的デプロイ」セクションの下に、「ビルドフック」があります。 「ビルドフックの追加」をクリックします。

Netlifyでビルドフックを見つける場所

名前を付けて保存します。 (私はbuild-from-backendを呼び出しました。)次に、生成されたリンクをコピーします。

次に、バックエンドプロジェクトを開いて、これらの数行をcron.controller.jsファイルに追加しましょう。 NetlifyのビルドフックURLにPOSTリクエストを送信しているだけです。

 const Axios = require('axios'); const Config = require('../config/env.config'); const NETLIFY_BUILD_HOOK_URI = Config.netlifyEndpoint; function updateGatsby() { if (NETLIFY_BUILD_HOOK_URI) { console.log('Gatsby build request will be send'); Axios.post(NETLIFY_BUILD_HOOK_URI).then(() => { console.log('Gatsby build request was successful'); }); } }

次に、 updateDaily関数を更新します。

 function updateDaily() { RepositoryController.updateRepositories().then(() => { updateGatsby(); }); }

最後に、 env.config.jsファイルを更新して、 netlifyEndpointプロパティを環境変数から収集するように設定します。

 "netlifyEndpoint": process.env.NETLIFY_BUILD_HOOK || ""

ここで、少し前にNetlifyからコピーしたNETLIFY_BUILD_HOOK環境変数を設定する必要があります。 Herokuでは、アプリケーションの「設定」セクションから環境変数を設定できます。

コミットをプッシュした後、バックエンドアプリケーションはビルドリクエストをNetlifyに送信し、cronジョブの最後にページが毎日更新されます。 ビルドフック機能を追加した後のリポジトリは、バックエンドリポジトリとフロントエンドリポジトリの最終バージョンとともに次のようになります。

プロジェクトの最後の仕上げとして、AWSCloudWatchによってトリガーされるAWSLambda関数を使用する方法を示します。この関数は、毎日の更新ごとにバックエンドをウェイクアップします。

AWSLambdaとAWSCloudWatchSimple Request

AWS Lambdaは、サーバーレスコンピューティングプラットフォームです。 ここでの目的には、このプラットフォームの非常に基本的なものだけが必要です。 AWSアカウントが必要です。

まず、アカウントでAWSにログインし、LambdaManagementConsoleを見つけます。 たとえば、 us-east-2の場合、https://us-east-2.console.aws.amazon.com/lambda/homeにあります。

まだ選択されていない場合は、「機能」セクションに移動します。

AWSLambdaの「関数」セクション

ここでは、「関数の作成」をクリックして、関数を最初から作成します。 説明的な名前を付けましょう。 ランタイム言語としてNode.jsを使用します。 次に、次の「関数の作成」をクリックして完成させます。

AWS Lambdaの「Createfunction」ページ。createtriggerMyBackendAtUTCMidnightで、Node.jsランタイムと基本的なLambda権限を持つ新しいロールで入力されます

index.jsにコードを記述できる新しい関数のページにリダイレクトされます。

最初のラムダ関数を実装しましょう。 サードパーティの依存関係がないため、Node.jsのコアモジュールを使用する必要があります。 (代わりにサードパーティの依存関係を有効にする場合は、AWSのこのガイドに従ってください。)

エクスポートされたメソッド名(この場合はhandler )がページの「Handler」パラメーターと一致することを確認してください。

「index.handler」を値として持つHandlerパラメーター

残りは、バックエンドへの単純なGETリクエストです。

 const https = require('https'); exports.handler = async (event) => { return new Promise((resolve, reject) => { https.get(process.env.HEROKU_APP_URL, (resp) => { let data = ''; resp.on('data', (chunk) => { data += chunk; }); resp.on('end', () => { resolve(JSON.parse(data)); }); }).on("error", (err) => { reject("Error: " + err.message); }); }); };

ページでHEROKU_APP_URL環境変数を設定し、構成を保存してください。

AWSLambdaで必要な環境変数を設定します。表示される値はhttps://sample-github-api-consumer-nod.herokuapp.com/repositoriesです。

最後のステップは、CloudWatchトリガールールを追加して、毎日の更新の10分前にこの関数を実行することです。このシリーズのこの記事では、23:50まで機能します。

トリガールールを追加するためのCloudWatchイベントの設定

CloudWatchトリガールールタイプは「Scheduleexpression」になり、受け入れられたフォーマットに従って、cron式はcron(50 23 * * ? *)になります。

AWS CloudWatchの「トリガーの設定」ページ。上記の式とトリガーを有効にして、cronDailyUpdateという新しいルールを作成するように設定されています。

これで、CloudWatchルールによってトリガーされるようにAWSLambda関数を設定しました。

静的Webページを強化する:Gatsby / React and Netlify

Node.js / MongoDB/HerokuバックエンドにAWSLambda/ CloudWatchを追加し、GatsbyとNetlifyがフロントエンドを生成してホストすることで、アプリが完成しました。

以前にライブデモリンクを共有しましたが、プロトタイプの拡張バージョンもチェックしてください。追加の変更がいくつかあります。

これを同様のプロジェクトの青写真として使用できます。これらの記事が、より高速で費用効果の高い方法でアプリのプロトタイプを作成するのに役立つことを願っています。 読んでくれてありがとう!

Toptalは高度なAWSコンサルティングパートナーです。