Сегодня я перескочил с FCC Frontend на FCC Backend в моем стремлении завершить скоростной забег Chingu FCC Speedrun Challenge. Почему? Фронтенд становился утомительным, и мне захотелось немного его перемешать, чтобы продвигаться дальше.

На этот раз я разработал микросервис Timestamp. По сути, это всего лишь небольшой api, который ответит json-объектом, содержащим как временную метку unix, так и обычную дату на английском языке, если вы его передадите - вы отправляете ему один, он вычисляет другой и возвращает вам оба.

Для меня это было действительно простое приложение, но я понимаю, что есть и другие, которые только начинают работать с Node.js, поэтому я собираюсь собрать своего рода учебник, чтобы помочь любому, кто испытывает затруднения. немного напуган этим проектом.

Во-первых, я буду использовать некоторую терминологию:

  • Node.js - серверный JavaScript
  • Express.js - отличный JavaScript для создания веб-сервера в Node.js
  • Moment.js - отличная библиотека для работы с датами
  • Pug.js - шаблонизатор (так что наш HTML может содержать переменные, переданные из нашего приложения Express.js)

Разбираем нашу проблему:

Чтобы реализовать это приложение, нам понадобится лишь крошечный фрагмент кода. Нам нужен код, чтобы:

  • Разверните сервер Node / Express для обработки HTTP-запросов
  • Создайте модуль, который принимает запрос api, состоящий из даты в одном из двух ожидаемых форматов, и возвращает соответствующий объект JSON, содержащий эту дату в обоих форматах.
  • Направлять запросы к этому модулю
  • Показать индексную страницу, описывающую приложение и способы его использования

Сначала создадим серверное приложение:

Это довольно просто и очень похоже на то, что вы найдете в любом базовом руководстве по Express. Оставьте мне сообщение в комментариях ниже, если какой-либо из следующих фрагментов не имеет смысла. По сути, вам просто требуется express (потому что вы создаете экспресс-приложение) и http (потому что вы хотите развернуть http-сервер для обработки запросов к вашей веб-странице (чтобы люди могли переходить к нему и использовать его). Затем вы требуется файл «маршрутов» (мы создадим его немного позже), настроить «express.static» (что действительно важно, иначе ваш код внешнего интерфейса не сможет найти ваши CSS и JavaScript веб-интерфейса, что является огромным боль отлаживать - да знаю по опыту).

Затем вы «используете» маршруты из запрошенного вами файла маршрутизации (чтобы ваше приложение знало, куда отправлять различные запросы, «/» переходит на домашнюю страницу, «/ api» будет перенаправлен на ваши серверные маршруты, поэтому запрос api будет должным образом обработаны.

И, наконец, раскручиваешь сервер: D

// Get dependencies
const express = require('express');
const http = require('http');
const app = express();
// Get our API routes
const api = require('./routes/api');
// Make sure our app can find our css and javascript frontend files
// which are located in the public folder
app.use(express.static('public'));
// Route to the routes :D
app.use('/api/v1', api);
app.use('/api/', api);
app.use('/', api);
// Enable pug (jade) for view rendering
app.set('view engine', 'pug');
// Create the server and fire it up
const server = http.createServer(app);
const port = process.env.PORT || '3000';
app.set('port', port);
server.listen(port, () => console.log(`API running on localhost:${port}`));

Во-вторых, создание модуля для обработки временных меток:

Вы, вероятно, будете очень удивлены, насколько легко moment.js делает эту часть. Серьезно, взгляните на приведенный ниже код. Момент просто берет дату и, бац, конвертирует ее.

Если вам интересно, что такое бизнес module.exports - вам действительно стоит прочитать You Don't Know JS: ES6 & Beyond, Кайл отлично все объясняет - гораздо лучше, чем У меня есть время или место здесь.

const moment = require('moment');
module.exports = {
    parse: function (req, res) {
        const date = req.params.query;
        let processedDate = {
            "unix": null,
            "natural": null
        }
        if (+date >= 0) {
            processedDate.unix = +date;
            processedDate.natural = moment.unix(+date).format("MMMM D, YYYY")
        }
        if (isNaN(+date) && moment(date, "MMMM D, YYYY").isValid()) {
            processedDate.unix = moment(date, "MMMM D, YYYY").format("X");
            processedDate.natural = date;
        }
        res.send(processedDate);
    }
}

В-третьих, маршрутизируйте запросы:

Здесь мы начнем с того, что потребуем экспресс-маршрутизатор, экспресс-маршрутизатор и модуль временной метки, который мы создали выше. Затем остается просто перенаправить запросы api к нашему модулю отметок времени, а все остальное - к нашему интерфейсу.

const express = require('express');
const router = express.Router();
// modules this api provides routing for
const timestamp = require('../timestamp/timestamp');
// TimeStamp Microservice Routes
// (note, catching a variety of urls and routing them to the same place)
router.route('/timestamp/api/v1/:query').get(timestamp.parse);
router.route('/timestamp/api/:query').get(timestamp.parse);
router.route('/timestamp/:query').get(timestamp.parse);
// If it's not an api request, display the index page (found in frontend)
router.get('*', (req, res) => {
  const fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
  res.render('index.pug', {
    fullUrl: fullUrl,
    title: 'Timestamp Microservice'
  });
});
module.exports = router;

Последний кусок - индексная страница на фронтенде:

Примечание: для этого я использовал мопса. Вы можете использовать любой шаблонизатор, какой захотите, или просто HTML, если на то пошло. Я выбрал pug, потому что «мне это нравится», я думаю, что это делает HTML немного аккуратнее, плюс он позволяет мне отправлять данные из бэкэнда и просто вставлять переменные в свой HTML во фронтенде - и это довольно просто в использовании.

doctype html
html
  head
    meta(charset='utf-8')
    meta(http-equiv='X-UA-Compatible', content='IE=edge')
    meta(name='viewport', content='width=device-width, initial-scale=1.0')
    title #{title} - FCC Speedrun
    link(id='favicon', rel='icon', type='image/x-icon', href='https://cdn.gomix.com/6b38c407-645c-4cad-beea-3f7aaf616b9c%2Ffavicon.ico')
    link(href='https://fonts.googleapis.com/css?family=Roboto', rel='stylesheet')
    link(href='/main.css', rel='stylesheet')
body
    h1 Timestamp Microservice
    h2 Example Usage
p #{fullUrl}api/v1/timestamp/December%2015,%202015<br>
    p #{fullUrl}api/v1/timestamp/1450137600
h2 Example Output
    p { "unix": 1450137600, "natural": "December 15, 2015" }

Обратите внимание на использование # {fullUrl} и # {title} - это переменные, которые я передал в свой индексный маршрут в разделе маршрутизации на стороне сервера выше.

Примечания:

Мой прогресс в Speedrun до сих пор: