The Back End: การใช้ Gatsby.js และ Node.js สำหรับการอัปเดตไซต์แบบคงที่

เผยแพร่แล้ว: 2022-03-11

ในชุดบทความนี้ เราจะพัฒนาต้นแบบเว็บไซต์เนื้อหาแบบคงที่ จะสร้างหน้า HTML แบบคงที่ที่เรียบง่ายและอัปเดตทุกวันสำหรับที่เก็บ GitHub ยอดนิยมเพื่อติดตามการเผยแพร่ล่าสุด เฟรมเวิร์กการสร้างหน้าเว็บแบบคงที่มีคุณสมบัติที่ยอดเยี่ยมในการบรรลุเป้าหมายนั้น เราจะใช้ Gatsby.js ซึ่งเป็นหนึ่งในฟีเจอร์ที่ได้รับความนิยมมากที่สุด

ใน Gatsby มีหลายวิธีในการรวบรวมข้อมูลสำหรับส่วนหน้าโดยไม่ต้องมีส่วนหลัง (ไร้เซิร์ฟเวอร์) แพลตฟอร์ม CMS ที่ไม่มีส่วนหัว และปลั๊กอินต้นทางของ Gatsby แต่เราจะใช้แบ็คเอนด์เพื่อจัดเก็บข้อมูลพื้นฐานเกี่ยวกับที่เก็บ GitHub และรีลีสล่าสุด ดังนั้น เราจะสามารถควบคุมทั้งส่วนหลังและส่วนหน้าได้อย่างเต็มที่

นอกจากนี้ ฉันจะอธิบายชุดเครื่องมือเพื่อทริกเกอร์การอัปเดตแอปพลิเคชันของคุณทุกวัน คุณยังสามารถทริกเกอร์มันด้วยตนเองหรือเมื่อใดก็ตามที่มีเหตุการณ์บางอย่างเกิดขึ้น

แอปพลิเคชันส่วนหน้าของเราจะใช้งานบน Netlify และแอปพลิเคชันส่วนหลังจะทำงานบน Heroku โดยใช้แผนบริการฟรี มันจะเข้าสู่โหมดสลีปเป็นระยะ: “เมื่อมีคนเข้าถึงแอพ ตัวจัดการไดโนจะปลุกเว็บไดโนโดยอัตโนมัติเพื่อเรียกใช้ประเภทกระบวนการทางเว็บ” ดังนั้นเราจึงสามารถปลุกมันขึ้นมาได้ผ่าน AWS Lambda และ AWS CloudWatch ในการเขียนนี้ นี่เป็นวิธีที่คุ้มค่าที่สุดในการสร้างต้นแบบออนไลน์ตลอด 24 ชั่วโมงทุกวันไม่เว้นวันหยุด

ตัวอย่างเว็บไซต์ Node Static ของเรา: สิ่งที่คาดหวัง

เพื่อให้บทความเหล่านี้เน้นที่หัวข้อเดียว ฉันจะไม่กล่าวถึงการรับรองความถูกต้อง การตรวจสอบความถูกต้อง ความสามารถในการปรับขนาด หรือหัวข้อทั่วไปอื่นๆ ส่วนการเข้ารหัสของบทความนี้จะง่ายที่สุด โครงสร้างของโครงการและการใช้ชุดเครื่องมือที่ถูกต้องมีความสำคัญมากกว่า

ในส่วนแรกของซีรีส์นี้ เราจะพัฒนาและปรับใช้แอปพลิเคชันแบ็คเอนด์ของเรา ในส่วนที่สอง เราจะพัฒนาและปรับใช้แอปพลิเคชันส่วนหน้าของเรา และเรียกใช้งานบิลด์รายวัน

The Node.js Back End

แอปพลิเคชันส่วนหลังจะถูกเขียนใน Node.js (ไม่บังคับ แต่เพื่อความง่าย) และการสื่อสารทั้งหมดจะกระทำผ่าน REST API เราจะไม่รวบรวมข้อมูลจากส่วนหน้าในโครงการนี้ (หากคุณสนใจที่จะทำอย่างนั้น ให้ดูที่ Gatsby Forms)

อันดับแรก เราจะเริ่มต้นด้วยการนำ REST API แบ็กเอนด์ไปใช้ ที่เปิดเผยการดำเนินการ CRUD ของคอลเล็กชันที่เก็บใน MongoDB ของเรา จากนั้นเราจะกำหนดเวลางาน cron ที่ใช้ GitHub API v4 (GraphQL) เพื่ออัปเดตเอกสารในคอลเล็กชันนี้ จากนั้นเราจะปรับใช้ทั้งหมดนี้กับ Heroku cloud สุดท้าย เราจะสร้างส่วนหน้าขึ้นใหม่เมื่อสิ้นสุดงาน cron

The Gatsby.js Front End

ในบทความที่สอง เราจะเน้นที่การใช้งาน createPages API เราจะรวบรวมที่เก็บทั้งหมดจากส่วนหลัง และจะสร้างโฮมเพจเดียวที่มีรายการของที่เก็บทั้งหมด รวมทั้งหน้าสำหรับเอกสารที่เก็บแต่ละรายการที่ส่งคืน จากนั้นเราจะปรับใช้ส่วนหน้าของเรากับ Netlify

จาก AWS Lambda และ AWS CloudWatch

ส่วนนี้ไม่จำเป็นหากแอปพลิเคชันของคุณไม่เข้าสู่โหมดสลีป ไม่เช่นนั้น คุณต้องแน่ใจว่าส่วนหลังของคุณทำงานอยู่ในขณะที่อัปเดตที่เก็บ คุณสามารถสร้างกำหนดการ cron บน AWS CloudWatch ได้ 10 นาทีก่อนการอัปเดตรายวันและผูกไว้เป็นทริกเกอร์สำหรับวิธี GET ใน AWS Lambda การเข้าถึงแอปพลิเคชันแบ็คเอนด์จะปลุกอินสแตนซ์ Heroku รายละเอียดเพิ่มเติมจะอยู่ที่ส่วนท้ายของบทความที่สอง

นี่คือสถาปัตยกรรมที่เราจะนำไปใช้:

ไดอะแกรมสถาปัตยกรรมที่แสดง AWS Lambda & CloudWatch ping ที่ส่วนหลังของ Node.js ซึ่งรับการอัปเดตรายวันโดยใช้ GitHub API จากนั้นจึงสร้างส่วนหน้าที่ใช้ Gatsby ซึ่งใช้ API แบ็คเอนด์เพื่ออัปเดตหน้าสแตติกและปรับใช้กับ Netlify แบ็กเอนด์ยังปรับใช้กับ Heroku ด้วยแผนฟรี

สมมติฐาน

ฉันคิดว่าผู้อ่านบทความนี้มีความรู้ในด้านต่อไปนี้:

  • HTML
  • CSS
  • JavaScript
  • REST APIs
  • MongoDB
  • Git
  • Node.js

ก็ยังดีถ้าคุณรู้ว่า:

  • Express.js
  • พังพอน
  • GitHub API v4 (GraphQL)
  • Heroku, AWS หรือแพลตฟอร์มคลาวด์อื่น ๆ
  • ปฏิกิริยา

มาดูการใช้งานแบ็กเอนด์กัน เราจะแบ่งออกเป็นสองงาน สิ่งแรกคือการเตรียมตำแหน่งข้อมูล REST API และผูกไว้กับคอลเล็กชันที่เก็บของเรา ประการที่สองคือการใช้งาน cron ที่ใช้ GitHub API และอัปเดตคอลเล็กชัน

การพัฒนา Node.js Static Site Generator Back End, ขั้นตอนที่ 1: A Simple REST API

เราจะใช้ Express สำหรับเฟรมเวิร์กแอปพลิเคชันบนเว็บและ Mongoose สำหรับการเชื่อมต่อ MongoDB ของเรา หากคุณคุ้นเคยกับ Express และ Mongoose คุณอาจข้ามไปยังขั้นตอนที่ 2 ได้

(ในทางกลับกัน หากคุณต้องการความคุ้นเคยกับ Express มากขึ้น คุณสามารถตรวจสอบคู่มือการเริ่มต้นใช้งาน Express อย่างเป็นทางการ หากคุณไม่ได้ใช้ Mongoose คู่มือเริ่มต้น Mongoose อย่างเป็นทางการน่าจะมีประโยชน์)

โครงสร้างโครงการ

ลำดับชั้นของไฟล์/โฟลเดอร์ของโปรเจ็กต์นั้นเรียบง่าย:

รายชื่อโฟลเดอร์ของรูทโปรเจ็กต์ โดยแสดงโฟลเดอร์ config, controller, model และ node_modules รวมถึงไฟล์รูทมาตรฐานสองสามไฟล์ เช่น index.js และ package.json ไฟล์ของสามโฟลเดอร์แรกเป็นไปตามหลักการตั้งชื่อของการทำซ้ำชื่อโฟลเดอร์ในแต่ละชื่อไฟล์ภายในโฟลเดอร์ที่กำหนด

รายละเอียดเพิ่มเติม:

  • env.config.js เป็นไฟล์การกำหนดค่าตัวแปรสภาพแวดล้อม
  • routes.config.js ใช้สำหรับการแมปจุดสิ้นสุดที่เหลือ
  • repository.controller.js มีเมธอดในการทำงานกับโมเดลที่เก็บของเรา
  • repository.model.js มี MongoDB schema ของ repository และ CRUD operation
  • 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 = { "port": process.env.PORT || 3000, "environment": "dev", "mongoDbUri": process.env.MONGODB_URI || "mongodb://localhost/github-consumer" };

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 avatar ของเจ้าของโปรเจ็กต์
 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/repositories

ตัว:

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

รับที่เก็บ

รับ: http://localhost:3000/repositories

รับโดย ID

รับ: http://localhost:3000/repositories/:id

แพทช์โดย ID

แพทช์: http://localhost:3000/repositories/:id

ตัว:

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

เมื่อใช้งานได้ ก็ถึงเวลาอัปเดตอัตโนมัติ

การพัฒนา Back End ของ Node.js Static Site Generator ขั้นตอนที่ 2: งาน Cron เพื่ออัปเดตรีลีสที่เก็บ

ในส่วนนี้ เราจะกำหนดค่างาน cron อย่างง่าย (ซึ่งจะเริ่มในเวลาเที่ยงคืน UTC) เพื่ออัปเดตที่เก็บ GitHub ที่เราแทรกลงในฐานข้อมูลของเรา เราเพิ่มเฉพาะพารามิเตอร์ owner และ name ในตัวอย่างด้านบนเท่านั้น แต่สองฟิลด์นี้เพียงพอสำหรับเราในการเข้าถึงข้อมูลทั่วไปเกี่ยวกับที่เก็บที่ระบุ

ในการอัปเดตข้อมูลของเรา เราต้องใช้ GitHub API สำหรับส่วนนี้ ควรทำความคุ้นเคยกับ GraphQL และ v4 ของ GitHub API

เราต้องสร้างโทเค็นเพื่อการเข้าถึง GitHub ด้วย ขอบเขตขั้นต่ำที่ต้องการคือ:

ขอบเขตโทเค็น GitHub ที่เราต้องการคือ repo:status, repo_deployment, public_repo, read:org และ read:user

นั่นจะสร้างโทเค็นและเราสามารถส่งคำขอไปยัง GitHub ได้

ตอนนี้กลับไปที่รหัสของเรา

เรามีการพึ่งพาใหม่สองรายการใน package.json :

  • "axios": "^0.18.0" เป็นไคลเอนต์ HTTP ดังนั้นเราจึงสามารถส่งคำขอไปยัง GitHub API
  • "cron": "^1.7.0" เป็นตัวกำหนดตารางเวลางาน cron

ตามปกติ ให้รัน npm install หรือ yarn หลังจากเพิ่มการพึ่งพา

เราต้องการคุณสมบัติใหม่สองอย่างใน config.js ด้วย:

  • "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 เพื่อความกระชับ เราจะออกแบบให้อัปเดตที่เก็บทั้งหมดในคราวเดียว แต่ถ้าคุณมีที่เก็บจำนวนมาก คุณอาจใช้ทรัพยากรเกินขีดจำกัดของ API ของ GitHub หากเป็นกรณีนี้ คุณจะต้องแก้ไขเพื่อให้ทำงานในแบทช์ที่จำกัด และกระจายออกไปตามช่วงเวลา

การใช้งานฟังก์ชั่นการอัพเดททั้งหมดในครั้งเดียวจะมีลักษณะดังนี้:

 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 และจะเรียกใช้ GitHub API การตอบสนองจากคำขอนั้นจะถูกประมวลผลในฟังก์ชัน 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); }); }

หลังจากการคอมมิตครั้งที่สอง เราจะใช้ตัวกำหนดตารางเวลา cron เพื่อรับการอัปเดตรายวันจากที่เก็บ GitHub ของเรา

เราเกือบเสร็จแล้วกับส่วนหลัง แต่ขั้นตอนสุดท้ายที่ควรทำหลังจากติดตั้งส่วนหน้าแล้ว เราจะกล่าวถึงในบทความถัดไป

การปรับใช้ Node Static Site Generator แบ็คเอนด์ไปที่ Heroku

ในขั้นตอนนี้ เราจะปรับใช้แอปพลิเคชันของเรากับ Heroku ดังนั้น คุณจะต้องสร้างบัญชีกับพวกเขา หากคุณยังไม่มี หากเราผูกบัญชี Heroku ของเรากับ GitHub เราจะปรับใช้อย่างต่อเนื่องได้ง่ายขึ้นมาก ด้วยเหตุนี้ ฉันจึงโฮสต์โปรเจ็กต์ของฉันบน GitHub

หลังจากลงชื่อเข้าใช้บัญชี Heroku แล้ว ให้เพิ่มแอปใหม่จากแดชบอร์ด:

เลือก "สร้างแอปใหม่" จากเมนูใหม่ในแดชบอร์ด Heroku

ตั้งชื่อเฉพาะ:

การตั้งชื่อแอปของคุณใน Heroku

คุณจะถูกเปลี่ยนเส้นทางไปยังส่วนการทำให้ใช้งานได้ เลือก GitHub เป็นวิธีการทำให้ใช้งานได้ ค้นหาที่เก็บของคุณ จากนั้นคลิกปุ่ม “เชื่อมต่อ”:

การลิงก์ repo GitHub ใหม่ของคุณกับแอป Heroku

เพื่อความง่าย คุณสามารถเปิดใช้งานการปรับใช้อัตโนมัติได้ มันจะปรับใช้เมื่อใดก็ตามที่คุณส่งคำสั่งไปยัง repo GitHub ของคุณ:

เปิดใช้งานการปรับใช้อัตโนมัติใน Heroku

ตอนนี้เราต้องเพิ่ม MongoDB เป็นทรัพยากร ไปที่แท็บทรัพยากรแล้วคลิก "ค้นหาโปรแกรมเสริมเพิ่มเติม" (โดยส่วนตัวฉันใช้ mLab mongoDB)

การเพิ่มทรัพยากร MongoDB ให้กับแอป Heroku ของคุณ

ติดตั้งและป้อนชื่อแอปของคุณในช่องป้อนข้อมูล "แอปที่จะจัดเตรียมให้":

หน้าข้อกำหนดเสริม mLab MongoDB ใน Heroku

สุดท้าย เราต้องสร้างไฟล์ชื่อ Procfile ที่ระดับรูทของโปรเจ็กต์ ซึ่งระบุคำสั่งที่แอปจะดำเนินการเมื่อ Heroku เริ่มทำงาน

Procfile ของเรานั้นง่ายอย่างนี้:

 web: node index.js

สร้างไฟล์และคอมมิต เมื่อคุณส่งคำสั่งแล้ว Heroku จะปรับใช้แอปพลิเคชันของคุณโดยอัตโนมัติ ซึ่งจะสามารถเข้าถึงได้ในชื่อ https://[YOUR_UNIQUE_APP_NAME].herokuapp.com/

เพื่อตรวจสอบว่าใช้งานได้หรือไม่ เราสามารถส่งคำขอเดียวกันกับที่เราส่งไปยัง localhost

Node.js, Express, MongoDB, Cron และ Heroku: มาถึงครึ่งทางแล้ว!

หลังจากการคอมมิตครั้งที่สาม นี่คือสิ่งที่ repo ของเราจะมีหน้าตา

จนถึงตอนนี้ เราได้ใช้งาน REST API แบบ Node.js/Express ในส่วนแบ็คเอนด์ของเรา ตัวอัปเดตที่ใช้ GitHub's API และงาน cron เพื่อเปิดใช้งาน จากนั้นเราได้ปรับใช้แบ็คเอนด์ซึ่งจะให้ข้อมูลสำหรับตัวสร้างเนื้อหาเว็บแบบคงที่ของเราในภายหลังโดยใช้ Heroku พร้อมเบ็ดสำหรับการรวมอย่างต่อเนื่อง ตอนนี้คุณก็พร้อมสำหรับส่วนที่สองแล้ว ซึ่งเราจะติดตั้งส่วนหน้าและทำให้แอปสมบูรณ์!

ที่เกี่ยวข้อง: ข้อผิดพลาดทั่วไป 10 อันดับแรกที่นักพัฒนา Node.js สร้าง