
Ave $USER!
Node.JS - это платформа для выполнения JavaScript основаная на движке V8. В этой статье мы установим node.js и напишем простой веб-сервис, который будет показывать топ 10 новостей с Hacker News.
Установка
Windows
Для установки нужно перейти на сайт nodejs.org скачать и установить.
Примечание: Если вы используете
Visual Studio 2015
, установите переменную окруженияGYP_MSVS_VERSION=2015
, что бы собирать модули Node JS с помощьюVisual Studio 2015
Ubuntu
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt-get install -y nodejs
MacOS
brew install node
Проверка
Вместе с node.js будет установлен менеджер пакетов npm
. Что бы проверить версию node
и npm
введем команды
node -v
npm -v
На момент написания статьи я использую node
версии 8.4.0
. Давайте запустим простейший http сервер на node.js.
Создание проекта
У меня все проекты находятся по пути ~/projects/JavaScript
.
Откроем консоль, создадим директорию для нашего проекта hacker-blog
и перейдем в нее.
Сначала нам нужно инициализировать проект командой npm init -y
.
В результате должен появиться файл package.json
. Откроем его и изменим секцию scripts
:
...
"scripts": {
"start": "nodemon index.js"
}
...
Далее установим необходимые модули с помощью следующей команды:
npm install --save express isomorphic-fetch nodemon
Немного о модулях:
- express - мини веб-фреймворк, с очень удобным API
- isomorphic-fetch - модуль позволяет использовать Fetch API на стороне сервера
- nodemon - модуль позволяет автоматически перезапускать скрипт при его изменении
Сначала создадим шаблон для нашего сайта в обычном index.html
файле
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Top 10 Hacker News stories</title>
<style>
html, body {
margin: 0;
min-height: 100%;
background-color: #f6f6ef;
}
.title {
background-color: #f60;
display: flex;
justify-content: center;
}
.stories {
display: flex;
flex-direction: column;
}
.story {
text-decoration: none;
color: #333;
}
.story__details {
font-size: 14px;
color: #888
}
</style>
</head>
<body>
<h1 class="title">Top 10 Hacker News</h1>
<ol class="stories">
<!--STORIES-->
</ol>
</body>
</html>
Здесь все просто, в списке есть комментарий <!--STORIES-->
, который будем использовать как метку, куда поместить наши новости.
Стили можете изменить на свой вкус и цвет.
Теперь создадим файл service.js
где будут функции вызова API Hacker News:
require('isomorphic-fetch');
// Т.к. у нас установлен node 8+ то можем использовать async/await,
// что делает код более читабельным и линейным, нежели лапша из `Promise.then`.
async function getTopStoriesIds(count) {
// Здесь используется URL `https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty`,
// который возвращает массив из числовых значений топ новостей, где мы получам `count` первых значений.
const response = await fetch('https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty');
const ids = await response.json();
return ids.slice(0, count);
}
async function fetchTopStories(ids) {
// Здесь мы получем информацию о каждой новости по ее номеру
// через URL `https://hacker-news.firebaseio.com/v0/item/${id}.json`.
return Promise.all(ids.map(async id => {
const response = await fetch(`https://hacker-news.firebaseio.com/v0/item/${id}.json`);
return response.json();
}));
}
module.exports = {
getTopStoriesIds,
fetchTopStories,
};
И наконец создадим файл index.js
, это и будет наш сервер:
// Импортируем установленные модули
const fs = require('fs');
const Express = require('express');
const app = Express();
// Импортируем наш сервис
const { getTopStoriesIds, fetchTopStories } = require('./services');
// Записываем шаблон в строку
const template = fs.readFileSync('./index.html', 'utf8');
// Функция для отрисовки новости
function renderStory({ url, title, by, time }) {
return `
<li class="story">
<a href="${url}" class="story" target="_blank">${title}</a>
<div class="story__details">by ${by} | ${new Date(time * 1000).toLocaleString()}</div>
</li>
`;
}
// Задаем обрабатчик HTTP запроса
app.get('/', async (req, res) => {
try {
// Ожидаем получение топ 10 новостей
const topIds = await getTopStoriesIds(10);
// Ожидаем получение информации о новостях
const items = await fetchTopStories(topIds);
// Отрисовываем их в строки
const stories = items.map(renderStory);
// Задаем время актуальности запроса
res.setHeader('Cache-Control', 'public, max-age=100');
res.setHeader('Expires', new Date(Date.now() + 100).toUTCString());
// Заменяем нашу метку на строки и отправляем ответ
res.end(template.replace('<!--STORIES-->', stories.join('\n')));
} catch (error) {
// Обрабатываем ошибку, если что-то не так
console.error(error.stack);
res.status(500).send('Something broke!');
}
});
const port = process.env.NODE_PORT || 9191;
// Запускаем сервер
app.listen(port, () => {
console.log(`Served from http://localhost:${port}`);
});
Запуск
Теперь запустим наш сервер командой:
npm start
Перейдя по адресу 127.0.0.1:9191 мы увидим нашу страницу: