Главная » Хабрахабр » [Перевод] Руководство по Node.js, часть 2: JavaScript, V8, некоторые приёмы разработки

[Перевод] Руководство по Node.js, часть 2: JavaScript, V8, некоторые приёмы разработки

Публикуя первую часть перевода этого руководства по Node.js, мы решили узнать мнение аудитории о том, стоит ли нам продолжать работу над проектом, и провели небольшой опрос. Как оказалось, нашу инициативу поддержали примерно 94% проголосовавших. Поэтому встречайте вторую часть руководства по Node.js.

Сегодня мы поговорим о том, какими знаниями в области JS нужно обладать для того, чтобы продуктивно разрабатывать приложения для платформы Node.js, обсудим различия браузерного и серверного JavaScript-кода, поговорим о JS-движках и о некоторых приёмах Node.js-разработки.

Какими JS-знаниями нужно обладать для Node.js-разработки?

Предположим, вы только начали заниматься программированием. Насколько глубоко вам нужно изучить JavaScript для успешного освоения Node.js? Начинающему трудно достичь такого уровня, когда он приобретёт достаточную уверенность в своих профессиональных навыках. К тому же, изучая программирование, вы можете почувствовать, что не понимаете точно, где заканчивается браузерный JavaScript и начинается разработка для Node.js.

Если вы находитесь в самом начале пути JavaScript-программиста, я посоветовал бы вам, прежде чем писать для Node.js, хорошо освоить следующие концепции языка:

  • Лексические конструкции.
  • Выражения.
  • Типы.
  • Переменные.
  • Функции.
  • Ключевое слово this.
  • Стрелочные функции
  • Циклы
  • Области видимости.
  • Массивы.
  • Шаблонные строки.
  • Применение точки с запятой.
  • Работа в строгом режиме.

На самом деле, этот список можно продолжать, но если вы всё это освоите, это значит, что вы заложите хорошую базу для продуктивной клиентской и серверной разработки на JavaScript.
Следующие концепции языка, кроме того, весьма важны для понимания идей асинхронного программирования, которые являются одной из базовых частей Node.js. В частности, речь идёт о следующем:

  • Асинхронное программирование и функции обратного вызова.
  • Таймеры.
  • Промисы.
  • Конструкция async/await.
  • Замыкания.
  • Цикл событий.

Существует множество материалов по JavaScript, которые позволяют начинающим освоить язык. Например, вот учебный курс автора данного руководства, вот весьма полезный раздел MDN, вот учебник сайта javascript.ru. Изучить базовые механизмы JavaScript можно на freecodecamp.com.

Поговорим об этом. Выше мы говорили о том, что начинающих может беспокоить вопрос о том, где проходит граница между серверной и клиентской разработкой на JavaScript.

Различия между платформой Node.js и браузером

Чем JS-разработка для Node.js отличается от браузерного программирования? Сходство между этими средами заключается в том, что и там и там используется один и тот же язык. Но разработка приложений, рассчитанных на выполнение в браузере, очень сильно отличается от разработки серверных приложений. Несмотря на использование одного и того же языка, существуют некоторые ключевые различия, которые и превращают два эти вида разработки в совершенно разные занятия.

Если к необходимости освоить новую среду добавляется ещё и необходимость изучить новый язык, задача значительно усложняется.
Итак главное различие между клиентом и сервером заключается в окружении, для которого приходится программировать, в экосистемах этих сред. Надо отметить, что если тот, кто раньше занимался фронтендом, начинает изучать Node.js, у него имеется весьма серьёзная возможность довольно быстро освоить всё что нужно благодаря тому, что писать он будет на уже знакомом ему языке.

Всего этого в Node.js, конечно, нет. В браузере основной объём работы приходится на выполнение различных операций с веб-документами посредством DOM, а также — на использование других API веб-платформы, таких, скажем, как механизмы для работы с куки-файлами. Тут нет ни объекта document, ни объекта window, равно как и других объектов, предоставляемых браузером.

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

Если только вы не занимаетесь разработкой опенсорсного приложения, которое может быть запущено где угодно, вы точно знаете, например, на какой версии Node.js будет работать ваш проект. Ещё одно различие между клиентской и серверной разработкой на JS заключается в том, что при работе в среде Node.js разработчик полностью контролирует окружение. Кроме того, это означает, что вы можете, не опасаясь проблем, пользоваться новейшими возможностями языка. Это очень удобно в сравнении с клиентским окружением, где вашему коду приходится работать в имеющемся у пользователя браузере.

К тому же, далеко не все пользователи работают на самых свежих версиях браузеров. Так как JavaScript крайне быстро развивается, браузеры просто не успевают достаточно оперативно реализовать все его новшества. Можно, конечно, для преобразования кода в формат, совместимый со стандартом EcmaScript 5, который поддерживают все браузеры, воспользоваться транспилятором Babel, но при работе с Node.js вам это не понадобится. В результате разработчики, которые хотят использовать в своих программах что-то новое, вынуждены это учитывать, заботиться о совместимости их приложений с используемыми браузерами, что может вылиться в необходимость отказа от современных возможностей JavaScript.

На практике это означает, что в настоящее время в Node.js, для подключения внешнего кода, используется конструкция require(), а в браузерном коде — import. Ещё одно различие между Node.js и браузерами заключается в том, что в Node.js используется система модулей CommonJS, в то время как в браузерах можно наблюдать начало реализации стандарта ES Modules.

V8 и другие JavaScript-движки

V8 — это название JavaScript-движка, используемого в браузере Google Chrome. Именно он отвечает за выполнение JavaScript-кода, который попадает в браузер при работе в интернете. V8 предоставляет среду выполнения для JavaScript. DOM и другие API веб-платформы предоставляются браузером.

Именно этот факт сделал возможным появление и развитие платформы Node.js. JS-движок независим от браузера, в котором он работает. В результате прямо-таки взрывного роста популярности Node.js V8 оказался движком, который в наши дни отвечает за выполнение огромного количества серверного JS-кода. V8 был выбран в качестве движка для Node.js в 2009 году.

Благодаря этому V8 также используется, посредством проектов наподобие Electron, при разработке настольных приложений. Экосистема Node.js огромна.

Надо отметить, что, помимо V8, существуют и другие движки:

  • В браузере Firefox применяется движок SpiderMonkey.
  • В Safari применяется JavaScriptCore (он ещё называется Nitro).
  • В Edge используется движок Chakra.

Список JS-движков этим не ограничивается.

Именно эта спецификация стандартизирует JavaScript. Эти движки реализуют спецификацию ECMA-262, называемую ещё ECMAScript. Свежую версию стандарта можно найти здесь.

▍Разработка JS-движков и стремление к производительности

Движок V8 написан на C++, его постоянно улучшают. Он может выполняться на многих системах, в частности, на Mac, Windows и Linux. Здесь мы не будем говорить о деталях реализации V8. Сведения о них можно найти в других публикациях, в том числе — на официальном сайте V8. Они со временем меняются, иногда — очень серьёзно.

Это приводит, в частности, к росту производительности веб-браузеров и платформы Node.js. V8 постоянно развивается, то же самое можно сказать и о других движках. Всё это идёт на пользу пользователям и программистам. Производители движков для браузеров постоянно соревнуются, борясь за скорость выполнения кода, продолжается это уже многие годы.

▍Интерпретация и компиляция

JavaScript считается интерпретируемым языком, но современные движки занимаются далеко не только интерпретацией JS-кода. Они его компилируют. Это веяние можно наблюдать с 2009-го года, когда компилятор JavaScript был добавлен в Firefox 3.5, после чего и другие производители движков и браузеров переняли эту идею.

Со времени появления Google Maps в 2004-м году JavaScript эволюционировал, превратился из языка, на котором, для реализации интерактивных возможностей веб-приложений, обычно писали по несколько десятков строк, в язык, на котором пишут браузерные приложения, состоящие из тысяч или даже сотен тысяч строк кода. V8 выполняет компиляцию JavaScript для повышения производительности кода. В современных условиях компиляция кода имеет огромный смысл, так как, хотя выполнение этого шага может отложить момент запуска кода, после компиляции код оказывается гораздо более производительным, чем тот, который обрабатывался бы исключительно интерпретатором и запускался бы быстрее, но работал бы медленнее. Такие приложения могут выполняться в браузере часами, что серьёзно отличается от старых сценариев использования JS, код на котором, например, мог применяться лишь для проверки правильности данных, вводимых в формы.

А именно, поговорим о том, как завершать работу Node.js-приложений. Теперь, обсудив некоторые положения, касающиеся JS-движков, интерпретации и компиляции кода, перейдём к практике.

Выход из Node.js-приложения

Существует несколько способов завершения работы Node.js-приложений.

Но нас больше интересуют программные способы завершения работы приложений. Так, при выполнении программы в консоли, завершить её работу можно, воспользовавшись сочетанием клавиш ctrl+c. И начнём мы, пожалуй, с самой грубой команды выхода из программы, которую, как вы сейчас поймёте, лучше не использовать.

Выглядит это так: Модуль ядра process предоставляет удобный метод, который позволяет осуществить программный выход из Node.js-приложения.

process.exit()

Когда Node.js встречает в коде такую команду, это приводит к тому, что его процесс мгновенно завершается. Это означает, что абсолютно всё, чем занималась программа, будет довольно грубо и безусловно прервано. Речь идёт о невызванных коллбэках, о выполняемых в момент выхода сетевых запросах, о действиях с файлами, об операциях записи в stdout или stderr.

При его вызове можно передать ему целое число, которое будет воспринято операционной системой как код выхода из программы. Если вас такое положение дел устраивает — можете этим методом пользоваться.

process.exit(1)

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

Выглядит это так: Код выхода, кроме того, можно назначить свойству process.exitCode.

process.exitCode = 1

После того, как программа завершит работу, Node.js вернёт системе этот код.

Однако в случае с Node.js часто встречаются программы, которые, в идеальных условиях, рассчитаны на работу неопределённой длительности. Надо отметить, что работа программы самостоятельно завершится естественным образом после того, как она выполнит все заданные в ней действия. Речь идёт, например, об HTTP-серверах, подобных такому:

const express = require('express')
const app = express()
app.get('/', (req, res) => { res.send('Hi!')
})
app.listen(3000, () => console.log('Server ready'))

Такая программа, если ничего не случится, в теории, может работать вечно. При этом, если вызвать process.exit(), выполняемые ей в момент вызова этой команды операции будут прерваны. А это плохо.

Для завершения работы подобных программ нужно воспользоваться сигналом SIGTERM и выполнить необходимые действия с помощью соответствующего обработчика.

Обратите внимание на то, что для использования объекта process не нужно ничего подключать с помощью require, так как этот объект доступен Node.js-приложениям по умолчанию.

Рассмотрим следующий пример:

const express = require('express')
const app = express()
app.get('/', (req, res) => { res.send('Hi!')
})
app.listen(3000, () => console.log('Server ready'))
process.on('SIGTERM', () => )
})

Что такое «сигналы»? Сигналы — это средства взаимодействия процессов в стандарте POSIX (Portable Operating System Interface). Они представляют собой уведомления, отправляемые процессу для того, чтобы сообщить ему о неких событиях.

Он, в идеале, работает так же, как process.exit(). Например, сигнал SIGKILL сообщает процессу о том, что ему нужно немедленно завершить работу.

Подобные сигналы отправляются из менеджеров процессов, вроде upstart или supervisord, и из многих других. Сигнал SIGTERM сообщает процессу о том, что ему нужно осуществить процедуру нормального завершения работы.

Отправить такой сигнал можно и из самой программы, воспользовавшись следующей командой:

process.kill(process.pid, 'SIGTERM')

Для успешного выполнения подобной команды нужно знать PID процесса, который планируется завершить.

Чтение переменных окружения из Node.js

Модуль ядра process имеет свойство env, которое даёт доступ ко всем переменным окружения, которые были заданы на момент запуска процесса.

Вот пример работы с переменной окружения NODE_ENV, которая, по умолчанию, установлена в значение development:

process.env.NODE_ENV // "development"

Если, до запуска скрипта, установить её в значение production, это сообщит Node.js о том, что программа выполняется в продакшн-окружении.

Подобным образом можно работать и с другими переменными среды, например, с теми, которые установлены вами самостоятельно.

Итоги

Сегодня мы коснулись вопросов браузерного и серверного программирования на JavaScript, поговорили о JS-движках, о том, как завершать работу серверных приложений, и о том, как читать переменные среды из Node.js-программ. В следующий раз мы расскажем о хостингах для Node.js-приложений, о том, как пользоваться Node.js в режиме REPL, о работе с аргументами, которые можно передавать скриптам при их вызове, о взаимодействии с консолью, и об оформлении кода в виде модулей.

Уважаемые читатели! Какие учебные материалы по JavaScript вы посоветовали бы начинающим?


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

[Из песочницы] LVEE — самая неформальная и душевная ИТ-тусовка

О событии Под Минском завершилась ежегодная конференция LVEE 2018 (Linux Vacation/Eastern Europe), организованная белорусской группой пользователей Linux еще в 2005 году. В мероприятии принимали участие более сотни людей из 7 стран, а программу составили 23 доклада, лайтнинги, воркшоп, круглый стол, ...

Губительная ошибка новичков в геймдеве

Перед началом любого дела необходимо составить план, сделать «пробы пера», одним словом — черновик. Именно это помогает определить стартовую точку и понять направление движения. Не хотите тратить тонны усилий впустую? Хотите делать быстрее и качественней остальных? 90% начинающих разработчиков этого ...