apeescape2.com
  • メイン
  • バックエンド
  • モバイル
  • 収益と成長
  • デザイナーライフ
バックエンド

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

この一連の記事では、静的コンテンツWebサイトのプロトタイプを開発します。人気のあるGitHubリポジトリの最新リリースを追跡するために、毎日更新される単純な静的HTMLページを生成します。静的Webページ生成フレームワークには、それを実現するための優れた機能があります。最も人気のあるGatsby.jsを使用します。

Gatsbyでは、バックエンド(サーバーレス)を使用せずにフロントエンドのデータを収集する方法はたくさんありますが、 ヘッドレスCMSプラットフォーム そして Gatsbyソースプラグイン その中で。ただし、GitHubリポジトリとその最新リリースに関する基本情報を保存するためのバックエンドを実装します。したがって、バックエンドとフロントエンドの両方を完全に制御できます。

また、アプリケーションの毎日の更新をトリガーするための一連のツールについても説明します。手動で、または特定のイベントが発生したときにトリガーすることもできます。



フロントエンドアプリケーションはNetlifyで実行され、バックエンドアプリケーションは無料プランを使用してHerokuで動作します。 定期的に寝ます :「誰かがアプリにアクセスすると、dynoマネージャーは自動的にWeb dynoを起動して、Webプロセスタイプを実行します。」だから、私たちはそれを介してそれを起こすことができます AWS Lambda およびAWSCloudWatch。これを書いている時点で、これはプロトタイプを24時間年中無休でオンラインにするための最も費用効果の高い方法です。

私たちのノード静的ウェブサイトの例:何を期待するか

これらの記事を1つのトピックに集中させるために、認証、検証、スケーラビリティ、またはその他の一般的なトピックについては説明しません。この記事のコーディング部分は、可能な限り単純になります。プロジェクトの構造と正しいツールセットの使用がより重要です。

シリーズのこの最初のパートでは、バックエンドアプリケーションを開発してデプロイします。に 第二部 、フロントエンドアプリケーションを開発してデプロイし、デイリービルドをトリガーします。

Node.jsバックエンド

バックエンドアプリケーションはNode.jsで記述され(必須ではありませんが、簡単にするため)、すべての通信はRESTAPIを介して行われます。このプロジェクトでは、フロントエンドからデータを収集しません。 (あなたがそれをすることに興味があるなら、見てください ギャツビーフォーム 。)

まず、MongoDBのリポジトリコレクションのCRUD操作を公開する単純なRESTAPIバックエンドを実装することから始めます。次に、このコレクション内のドキュメントを更新するために、GitHub API v4(GraphQL)を使用するcronジョブをスケジュールします。次に、これらすべてをHerokuクラウドにデプロイします。最後に、cronジョブの最後にフロントエンドの再構築をトリガーします。

Gatsby.jsフロントエンド

2番目の記事では、の実装に焦点を当てます createPages火 。バックエンドからすべてのリポジトリを収集し、すべてのリポジトリのリストと、返された各リポジトリドキュメントのページを含む単一のホームページを生成します。次に、 フロントエンドをNetlifyにデプロイする 。

AWSLambdaおよびAWSCloudWatchから

アプリケーションがスリープしない場合、この部分は必須ではありません。それ以外の場合は、リポジトリの更新時にバックエンドが稼働していることを確認する必要があります。解決策として、毎日の更新の10分前にAWS CloudWatchでcronスケジュールを作成し、それをトリガーとしてGETにバインドできます。 AWSLambdaのメソッド。バックエンドアプリケーションにアクセスすると、Herokuインスタンスがウェイクアップします。詳細は2番目の記事の最後にあります。

実装するアーキテクチャは次のとおりです。

SpringBootセキュリティトークンベースの認証例

AWSLambdaとCloudWatchがNode.jsバックエンドにpingを実行する様子を示すアーキテクチャ図。GitHubAPIを使用して毎日更新を取得し、バックエンドAPIを使用して静的ページを更新してNetlifyにデプロイするGatsbyベースのフロントエンドを構築します。バックエンドも無料プランでHerokuにデプロイされます。

仮定

この記事の読者は、次の分野の知識があると思います。

  • HTML
  • CSS
  • JavaScript
  • REST API
  • MongoDB
  • 行く
  • Node.js

あなたが知っているならそれも良いです:

  • Express.js
  • マングース
  • GitHub API v4(GraphQL)
  • Heroku、AWS、またはその他のクラウドプラットフォーム
  • React

バックエンドの実装について詳しく見ていきましょう。これを2つのタスクに分割します。 1つ目は、REST APIエンドポイントを準備し、それらをリポジトリコレクションにバインドすることです。 2つ目は、GitHubAPIを使用してコレクションを更新するcronジョブを実装することです。

Node.js静的サイトジェネレーターバックエンドの開発、ステップ1:シンプルなREST API

WebアプリケーションフレームワークにはExpressを使用し、MongoDB接続にはMongooseを使用します。 ExpressとMongooseに精通している場合は、手順2にスキップできる場合があります。

(一方、Expressに精通している必要がある場合は、チェックアウトできます。 公式Expressスターターガイド ;マングースに慣れていない場合は、 マングースの公式スターターガイド 役立つはずです。)

プロジェクト構造

プロジェクトのファイル/フォルダ階層は単純になります。

プロジェクトルートのフォルダーリスト。config、controller、model、node_modulesフォルダーに加えて、index.jsやpackage.jsonなどのいくつかの標準ルートファイルが表示されます。最初の3つのフォルダーのファイルは、特定のフォルダー内の各ファイル名でフォルダー名を繰り返すという命名規則に従います。

さらに詳細に:

  • env.config.js環境変数構成ファイルです
  • routes.config.js残りのエンドポイントをマッピングするためのものです
  • repository.controller.jsリポジトリモデルで作業するためのメソッドが含まれています
  • repository.model.jsリポジトリとCRUD操作のMongoDBスキーマが含まれています
  • index.jsイニシャライザクラスです
  • package.json依存関係とプロジェクトプロパティが含まれています

実装

実行npm install (または、Yarnがインストールされている場合はyarn)これらの依存関係をpackage.jsonに追加した後:

{ // ... 'dependencies': { 'body-parser': '1.7.0', 'express': '^4.8.7', 'moment': '^2.17.1', 'moment-timezone': '^0.5.13', 'mongoose': '^5.1.1', 'node-uuid': '^1.4.8', 'sync-request': '^4.0.2' } // ... }

私たちのenv.config.jsファイルにはport、environmentしかありません(devまたはprod)、およびmongoDbUri今のところプロパティ:

module.exports = ;

routes.config.jsリクエストマッピングが含まれ、コントローラーの対応するメソッドを呼び出します。

const RepositoryController = require('../controller/repository.controller'); exports.routesConfig = function(app) { app.post('/repositories', [ RepositoryController.insert ]); app.get('/repositories', [ RepositoryController.list ]); app.get('/repositories/:id', [ RepositoryController.findById ]); app.patch('/repositories/:id', [ RepositoryController.patchById ]); app.delete('/repositories/:id', [ RepositoryController.deleteById ]); };

repository.controller.jsファイルはサービスレイヤーです。その責任は、リポジトリモデルの対応するメソッドを呼び出すことです。

const RepositoryModel = require('../model/repository.model'); exports.insert = (req, res) => { RepositoryModel.create(req.body) .then((result) => { res.status(201).send({ id: result._id }); }); }; exports.findById = (req, res) => { RepositoryModel.findById(req.params.id) .then((result) => { res.status(200).send(result); }); }; exports.list = (req, res) => { RepositoryModel.list() .then((result) => { res.status(200).send(result); }) }; exports.patchById = (req, res) => { RepositoryModel.patchById(req.params.id, req.body) .then(() => { res.status(204).send({}); }); }; exports.deleteById = (req, res) => { RepositoryModel.deleteById(req.params.id, req.body) .then(() => { res.status(204).send({}); }); };

repository.model.jsリポジトリモデルのMongoDb接続とCRUD操作を処理します。モデルのフィールドは次のとおりです。

  • owner:リポジトリの所有者(会社またはユーザー)
  • name:リポジトリ名
  • createdAt:最終リリースの作成日
  • resourcePath:最後のリリースパス
  • tagName:最後のリリースタグ
  • releaseDescription:リリースノート
  • homepageUrl:プロジェクトのホームURL
  • repositoryDescription:リポジトリの説明
  • avatarUrl:プロジェクトオーナーのアバターのURL
const Mongoose = require('mongoose'); const Config = require('../config/env.config'); const MONGODB_URI = Config.mongoDbUri; Mongoose.connect(MONGODB_URI, { useNewUrlParser: true }); const Schema = Mongoose.Schema; const repositorySchema = new Schema({ owner: String, name: String, createdAt: String, resourcePath: String, tagName: String, releaseDescription: String, homepageUrl: String, repositoryDescription: String, avatarUrl: String }); repositorySchema.virtual('id').get(function() { return this._id.toHexString(); }); // Ensure virtual fields are serialised. repositorySchema.set('toJSON', { virtuals: true }); repositorySchema.findById = function(cb) { return this.model('Repository').find({ id: this.id }, cb); }; const Repository = Mongoose.model('repository', repositorySchema); exports.findById = (id) => { return Repository.findById(id) .then((result) => { if (result) { result = result.toJSON(); delete result._id; delete result.__v; return result; } }); }; exports.create = (repositoryData) => { const repository = new Repository(repositoryData); return repository.save(); }; exports.list = () => { return new Promise((resolve, reject) => { Repository.find() .exec(function(err, users) { if (err) { reject(err); } else { resolve(users); } }) }); }; exports.patchById = (id, repositoryData) => { return new Promise((resolve, reject) => { Repository.findById(id, function(err, repository) { if (err) reject(err); for (let i in repositoryData) { repository[i] = repositoryData[i]; } repository.save(function(err, updatedRepository) { if (err) return reject(err); resolve(updatedRepository); }); }); }) }; exports.deleteById = (id) => { return new Promise((resolve, reject) => { Repository.deleteOne({ _id: id }, (err) => { if (err) { reject(err); } else { resolve(err); } }); }); }; exports.findByOwnerAndName = (owner, name) => { return Repository.find({ owner: owner, name: name }); };

これは、最初のコミット後に取得したものです。 MongoDB接続とREST操作 。

次のコマンドでアプリケーションを実行できます。

node index.js

テスト

テストのために、リクエストをlocalhost:3000に送信します(例:PostmanまたはcURLを使用):

リポジトリを挿入します(必須フィールドのみ)

役職: http:// localhost:3000 / repository

体:

{ 'owner' : 'facebook', 'name' : 'react' }

リポジトリを取得する

取得する: http:// localhost:3000 / repository

IDで取得

取得する: http:// localhost:3000 / repository /:id

IDによるパッチ

パッチ: http:// localhost:3000 / repository /:id

体:

{ 'owner' : 'facebook', 'name' : 'facebook-android-sdk' }

これが機能したら、更新を自動化するときが来ました。

Node.js静的サイトジェネレーターバックエンドの開発、ステップ2:リポジトリリリースを更新するためのcronジョブ

このパートでは、データベースに挿入したGitHubリポジトリを更新するために、単純なcronジョブ(UTCの深夜に開始)を構成します。 ownerのみを追加しましたおよびname上記の例のパラメータのみですが、これら2つのフィールドは、特定のリポジトリに関する一般的な情報にアクセスするのに十分です。

ソフトウェアプロジェクト管理におけるコスト見積もり

データを更新するには、GitHubAPIを使用する必要があります。この部分については、よく知っていることが最善です GraphQL そして GitHubAPIのv4 。

私たちもする必要があります GitHubアクセストークンを作成する 。そのために最低限必要なスコープは次のとおりです。

必要なGitHubトークンスコープは、repo:status、repo_deployment、public_repo、read:org、およびread:userです。

これによりトークンが生成され、それを使用してGitHubにリクエストを送信できます。

それでは、コードに戻りましょう。

package.jsonに2つの新しい依存関係があります。

  • 'axios': '^0.18.0'はHTTPクライアントであるため、GitHubAPIにリクエストを送信できます
  • 'cron': '^1.7.0' cronジョブスケジューラです

いつものように、npm installを実行しますまたはyarn依存関係を追加した後。

config.jsにも2つの新しいプロパティが必要です。

  • 'githubEndpoint': 'https://api.github.com/graphql'
  • 'githubAccessToken': process.env.GITHUB_ACCESS_TOKEN (独自のパーソナルアクセストークンを使用してGITHUB_ACCESS_TOKEN環境変数を設定する必要があります)

controllerの下に新しいファイルを作成しますcron.controller.jsという名前のフォルダー。単にupdateResositoriesと呼びますrepository.controller.jsの方法予定時刻:

const RepositoryController = require('../controller/repository.controller'); const CronJob = require('cron').CronJob; function updateDaily() { RepositoryController.updateRepositories(); } exports.startCronJobs = function () { new CronJob('0 0 * * *', function () {updateDaily()}, null, true, 'UTC'); };

この部分の最終的な変更はrepository.controller.jsにあります。簡潔にするために、すべてのリポジトリを一度に更新するように設計します。ただし、リポジトリの数が多い場合は、 GitHubのAPIのリソース制限 。その場合は、これを変更して、限られたバッチで実行し、時間をかけて分散させる必要があります。

更新機能の一括実装は次のようになります。

async function asyncUpdate() { await RepositoryModel.list().then((array) => { const promises = array.map(getLatestRelease); return Promise.all(promises); }); } exports.updateRepositories = async function update() { console.log('GitHub Repositories Update Started'); await asyncUpdate().then(() => { console.log('GitHub Repositories Update Finished'); }); };

最後に、エンドポイントを呼び出して、リポジトリモデルを更新します。

getLatestRelease関数はGraphQLクエリを生成し、GitHubAPIを呼び出します。そのリクエストからの応答は、updateDatabaseで処理されます。関数。

async function updateDatabase(responseData, owner, name) { let createdAt = ''; let resourcePath = ''; let tagName = ''; let releaseDescription = ''; let homepageUrl = ''; let repositoryDescription = ''; let avatarUrl = ''; if (responseData.repository.releases) { createdAt = responseData.repository.releases.nodes[0].createdAt; resourcePath = responseData.repository.releases.nodes[0].resourcePath; tagName = responseData.repository.releases.nodes[0].tagName; releaseDescription = responseData.repository.releases.nodes[0].description; homepageUrl = responseData.repository.homepageUrl; repositoryDescription = responseData.repository.description; if (responseData.organization && responseData.organization.avatarUrl) { avatarUrl = responseData.organization.avatarUrl; } else if (responseData.user && responseData.user.avatarUrl) { avatarUrl = responseData.user.avatarUrl; } const repositoryData = { owner: owner, name: name, createdAt: createdAt, resourcePath: resourcePath, tagName: tagName, releaseDescription: releaseDescription, homepageUrl: homepageUrl, repositoryDescription: repositoryDescription, avatarUrl: avatarUrl }; await RepositoryModel.findByOwnerAndName(owner, name) .then((oldGitHubRelease) => { if (!oldGitHubRelease[0]) { RepositoryModel.create(repositoryData); } else { RepositoryModel.patchById(oldGitHubRelease[0].id, repositoryData); } console.log(`Updated latest release: http://github.com${repositoryData.resourcePath}`); }); } } async function getLatestRelease(repository) { const owner = repository.owner; const name = repository.name; console.log(`Getting latest release for: http://github.com/${owner}/${name}`); const query = ` query { organization(login: '${owner}') { avatarUrl } user(login: '${owner}') { avatarUrl } repository(owner: '${owner}', name: '${name}') { homepageUrl description releases(first: 1, orderBy: {field: CREATED_AT, direction: DESC}) { nodes { createdAt resourcePath tagName description } } } }`; const jsonQuery = JSON.stringify({ query }); const headers = { 'User-Agent': 'Release Tracker', 'Authorization': `Bearer ${GITHUB_ACCESS_TOKEN}` }; await Axios.post(GITHUB_API_URL, jsonQuery, { headers: headers }).then((response) => { return updateDatabase(response.data.data, owner, name); }); }

2回目のコミットの後、実装します GitHubリポジトリから毎日更新を取得するcronスケジューラ 。

バックエンドはほぼ完成です。ただし、フロントエンドを実装した後に最後のステップを実行する必要があるため、次の記事で説明します。

Node Static SiteGeneratorバックエンドをHerokuにデプロイする

このステップでは、アプリケーションをHerokuにデプロイします。 彼らと一緒にアカウントを設定する必要があります まだ持っていない場合。 HerokuアカウントをGitHubにバインドすると、継続的デプロイがはるかに簡単になります。そのために、 GitHubでプロジェクトをホストしています 。

Herokuアカウントにログインした後、ダッシュボードから新しいアプリを追加します。

選択

一意の名前を付けます。

Herokuでアプリに名前を付けます。

デプロイメントセクションにリダイレクトされます。デプロイ方法としてGitHubを選択し、リポジトリを検索して、[接続]ボタンをクリックします。

新しいGitHubリポジトリをHerokuアプリにリンクします。

簡単にするために、自動展開を有効にすることができます。 GitHubリポジトリにコミットをプッシュするたびにデプロイされます。

Herokuで自動デプロイを有効にします。

次に、MongoDBをリソースとして追加する必要があります。 [リソース]タブに移動し、[その他のアドオンを検索]をクリックします。 (私は個人的にmLab mongoDBを使用しています。)

HerokuアプリにMongoDBリソースを追加します。

Excelでデータを変換する方法

それをインストールし、「プロビジョニングするアプリ」入力ボックスにアプリの名前を入力します。

HerokuのmLabMongoDBアドオンプロビジョニングページ。

最後に、Procfileという名前のファイルを作成する必要がありますプロジェクトのルートレベルで、Herokuの起動時にアプリによって実行されるコマンドを指定します。

私たちのProcfileこれと同じくらい簡単です:

web: node index.js

ファイルを作成してコミットします。コミットをプッシュすると、Herokuはアプリケーションを自動的にデプロイします。アプリケーションにはhttps://[YOUR_UNIQUE_APP_NAME].herokuapp.com/としてアクセスできます。

動作しているかどうかを確認するために、localhostに送信したのと同じリクエストを送信できます。

Node.js、Express、MongoDB、Cron、Heroku:中途半端です!

3回目のコミットの後、 これは私たちのリポジトリがどのように見えるかです 。

これまでに、 Node.js バックエンドの/ ExpressベースのRESTAPI、GitHubのAPIを使用するアップデーター、およびそれをアクティブ化するためのcronジョブ。次に、バックエンドをデプロイしました。これにより、後でデータが提供されます。 静的Webコンテンツジェネレータ 継続的インテグレーションのためのフック付きのHerokuを使用します。これで準備が整いました 第二部 、フロントエンドを実装してアプリを完成させます!

関連: Node.js開発者が犯す最も一般的な間違いトップ10

基本を理解する

静的および動的なWebページとは何ですか?

公開後、静的Webページにはすべてのセッションで同じデータが含まれます。動的なWebページでは、データをその場で更新できます。

Nodeが人気なのはなぜですか?

Node.jsは軽量、高速、スケーラブル、オープンソースであり、コミュニティによって十分にサポートされています。

Node.jsの目的は何ですか?

Node.jsは、JavaScriptを使用してスケーラブルで軽量な非同期のイベント駆動型Webアプリケーションを構築するためのバックエンドランタイム環境として機能します。

Node.jsの利点は何ですか?

Node.jsは、ブラウザで通常使用されるのと同じ言語(JavaScript)をサーバー側に使用します。軽量で、リクエストの処理中にノンブロッキングI / O操作を使用するように設計されています。

Node.jsはどれほど重要ですか?

人気のあるMEANスタック(MongoDB、Express.js、Angular、Node.js)のメンバーとして、Node.jsは、JavaScriptを使用して高性能でスケーラブルなWebアプリケーションを開発するために重要です。

GraphQLの利点は何ですか?

GraphQLの利点には、サーバーから必要なものだけを収集すること、1つのリクエストで複数のリソースを取得すること、APIが自己文書化されていることなどがあります。

GraphQLが使用されるのはなぜですか?

GraphQLは、ラピッドプロトタイピングと本番環境への展開を可能にします。さらに、すべてのリソースに単一のエンドポイントを使用するため、クライアントサーバー通信が容易になります。

Herokuの目的は何ですか?

Herokuは、アプリの起動とスケーリングの合理化に重点を置いたクラウドプラットフォームです。

開発用のRaspberryPiサーバーを構築する方法

技術

開発用のRaspberryPiサーバーを構築する方法
ウェブサイトの再設計を検討する理由-ヒントと推奨事項

ウェブサイトの再設計を検討する理由-ヒントと推奨事項

Uxデザイン

人気の投稿
Sass Mixins:スタイルシートを乾いた状態に保つ
Sass Mixins:スタイルシートを乾いた状態に保つ
Kubernetesとは何ですか?コンテナ化と展開のガイド
Kubernetesとは何ですか?コンテナ化と展開のガイド
説得力と動き–モーションデザインの原則へのガイド
説得力と動き–モーションデザインの原則へのガイド
最高のデータ視覚化ツールの完全な概要
最高のデータ視覚化ツールの完全な概要
BlackBerryに何が起こったのか:ゾンビストックまたはカムバックキング?
BlackBerryに何が起こったのか:ゾンビストックまたはカムバックキング?
 
ウェブサイトの再設計の基礎–ケーススタディ
ウェブサイトの再設計の基礎–ケーススタディ
バイオテクノロジー評価の特異性とベストプラクティス
バイオテクノロジー評価の特異性とベストプラクティス
WebRTCアプリケーションを構築する1年:スタートアップエンジニアリングの教訓
WebRTCアプリケーションを構築する1年:スタートアップエンジニアリングの教訓
ゲシュタルトの設計原則を探る
ゲシュタルトの設計原則を探る
国際送金市場はどのように進化していますか?
国際送金市場はどのように進化していますか?
人気の投稿
  • C ++コーディングを学ぶ
  • C ++にヘッダーファイルをインクルードする方法
  • w2時給vs給与計算機
  • c orp vs s corp
  • ルビーとレール上のルビー
  • Webフォントと印刷フォント
  • 近接性の定義のゲシュタルト原理
カテゴリー
プロセスとツール 設計プロセス リモートの台頭 収益性と効率性 人とチーム エンジニアリング管理 技術 ヒントとツール バックエンド モバイルデザイン

© 2021 | 全著作権所有

apeescape2.com