Создание модуля Node.js
В Node.js модуль представляет собой набор функций и объектов JavaScript, которые могут использоваться внешними приложениями. Описание фрагмента кода как модуля относится не столько к самому коду, а скорее к тому, что он делает – любой файл или набор файлов Node.js можно считать модулем, если его функции и данные доступны для использования внешними программами.
Поскольку модули предоставляют функциональные блоки, которые можно повторно использовать в разных более крупных программах, они позволяют создавать слабосвязанные приложения, которые масштабируются по мере усложнения и дают возможность поделиться своим кодом с другими разработчиками. Имея возможность писать модули, которые экспортируют полезные функции и данные, вы можете внести свой вклад в широкое сообщество Node.js – фактически все пакеты, которые вы используете в npm, были объединены и распространены в виде модулей. Поэтому сегодня создание модулей – важный, необходимый навык для разработчика Node.js.
В этом мануале вы научитесь создавать модули Node.js. Мы создадим модуль, который предлагает цвета, которые веб-разработчики могли бы использовать в своих проектах. Вы разработаете модуль, сохраните цвета в виде массива и предоставите функцию для извлечения случайного цвета. После этого мы рассмотрим различные способы импорта модуля в приложение Node.js.
Требования
- Установка Node.js и npm. В данном мануале используется версия 10.17.0. Чтобы установить ее на macOS, читайте этот мануал. Чтобы установить ее на Ubuntu 18.04 через PPA, выполните этот мануал. Вместе с Node.js устанавливается и npm (в данном мануале используется версия 6.11.3).
- Базовые навыки работы с файлом package.json и командами npm.
- Навыки работы с Node.js REPL. Больше информации по этому вопросу вы найдете здесь.
1: Создание модуля
Сейчас вы создадите ваш первый модуль Node.js. Он будет содержать коллекцию цветов в массиве и функцию для извлечения случайного цвета. Вы будете использовать встроенное свойство exports, чтобы сделать функцию и массив доступными для внешних программ.
Сначала нужно решить, какие данные о цветах мы будем хранить в своем модуле. Каждый цвет будет объектом, который содержит свойство name (по нему люди могут легко его идентифицировать) и code (это строка, содержащая цветовой код HTML). Цветовые коды HTML представляют собой шестизначные шестнадцатеричные числа, которые позволяют изменять цвет элементов на веб-странице. Узнать больше о цветовых кодах HTML можно здесь.
Затем нужно решить, какие цвета вы хотите поддерживать в своем модуле. Модуль будет содержать массив по имени allColors, который будет содержать шесть цветов. Также модуль будет включать функцию getRandomColor(), которая будет случайным образом выбирать цвет из массива и выводить его на экран.
В терминале создайте новую папку colors и перейдите в нее:
mkdir colors
cd colors
Инициализируйте npm, чтобы позже другие программы могли импортировать этот модуль:
npm init -y
Флаг -y пропустит запросы по настройке вашего package.json. Если бы мы собирались опубликовать этот модуль в npm, нам нужно было бы ответить на все эти запросы соответствующими данными.
В этом случае вы получите такой вывод:
{
"name": "colors",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Теперь откройте текстовый редактор (например nano) и создайте новый файл, который будет служить точкой входа для модуля:
nano index.js
Этот модуль будет делать несколько вещей. Сначала мы определим класс Color, который будет содержать название цвета и его код. Добавьте следующие строки для создания этого класса:
class Color {
constructor(name, code) {
this.name = name;
this.code = code;
}
}
Теперь, когда у вас есть структура данных для класса Color, добавьте в ваш модуль несколько экземпляров. Добавьте следующий выделенный массив в файл:
class Color {
constructor(name, code) {
this.name = name;
this.code = code;
}
}
const allColors = [
new Color('brightred', '#E74C3C'),
new Color('soothingpurple', '#9B59B6'),
new Color('skyblue', '#5DADE2'),
new Color('leafygreen', '#48C9B0'),
new Color('sunkissedyellow', '#F4D03F'),
new Color('groovygray', '#D7DBDD'),
];
Затем добавьте функцию, которая случайным образом выбирает элемент из только что созданного массива allColors:
class Color {
constructor(name, code) {
this.name = name;
this.code = code;
}
}
const allColors = [
new Color('brightred', '#E74C3C'),
new Color('soothingpurple', '#9B59B6'),
new Color('skyblue', '#5DADE2'),
new Color('leafygreen', '#48C9B0'),
new Color('sunkissedyellow', '#F4D03F'),
new Color('groovygray', '#D7DBDD'),
];
exports.getRandomColor = () => {
return allColors[Math.floor(Math.random() * allColors.length)];
}
exports.allColors = allColors;
Ключевое слово exports ссылается на глобальный объект, доступный в каждом модуле Node.js. Все функции и объекты, хранящиеся в объекте exports, открываются, когда другие модули Node.js импортируют его. Например, функция getRandomColor() была создана непосредственно в объекте exports. Затем мы добавили в объект exports свойство allColors, которое ссылается на локальной массив allColors, созданный ранее в скрипте.
Когда другие модули импортируют этот модуль, allColors и getRandomColor() будут доступны для использования.
Сохраните и закройте файл.
Итак, вы создали модуль, который содержит массив цветов и функцию, которая извлекает один случайный цвет. Вы также экспортировали массив и функцию, чтобы их могли использовать внешние программы. Далее мы попробуем использовать модуль в других приложениях.
2: Тестирование приложения с помощью REPL
Прежде чем создавать полное приложение, лучше уделить немного времени тестированию и убедиться, что модуль работает. На этом этапе мы используем REPL для загрузки модуля colors. Находясь в REPL, мы вызовем функцию getRandomColor(), чтобы увидеть, ведет ли она себя так, как мы ожидаем.
Запустите REPL Node.js в той папке, в которой находится файл index.js:
node
Когда REPL запустится, вы увидите командную строку, которая начинается с символа >. Это означает, что вы можете ввести код JavaScript, который будет сразу же оценен.
Читайте также: Использование интерактивной оболочки REPL в Node.js
Сначала введите следующую строку:
colors = require('./index');
В этой команде require() загружает модуль colors в его точку входа. Когда вы нажмете ENTER, вы получите:
{
getRandomColor: [Function],
allColors: [
Color { name: 'brightred', code: '#E74C3C' },
Color { name: 'soothingpurple', code: '#9B59B6' },
Color { name: 'skyblue', code: '#5DADE2' },
Color { name: 'leafygreen', code: '#48C9B0' },
Color { name: 'sunkissedyellow', code: '#F4D03F' },
Color { name: 'groovygray', code: '#D7DBDD' }
]
}
REPL показывает значение colors, которое представляет все функции и объекты, импортированные из файла index.js. Когда вы используете ключевое слово require, Node.js возвращает все содержимое объекта exports данного модуля.
Напомним, что вы добавили getRandomColor() и allColors в exports в модуле colors. По этой причине вы видите их в REPL, когда они импортируются.
Теперь в командной строке протестируйте функцию getRandomColor():
colors.getRandomColor();
Вы получите случайный цвет:
Color { name: 'groovygray', code: '#D7DBDD' }
Поскольку индекс выбирается случайно, вывод может отличаться. Теперь, когда вы подтвердили, что модуль colors работает, выйдите из REPL Node.js:
.exit
Это вернет вас в командную строку терминала.
Используя REPL, вы только что подтвердили, что модуль работает должным образом. Давайте теперь загрузим свой модуль в приложение, как в реальном проекте.
3: Сохранение локального модуля как зависимости
При тестировании модуля в REPL вы импортировали его с относительным путем: то есть вы использовали расположение файла index.js относительно рабочего каталога, чтобы получить его содержимое. Этот метод работает, но обычно в программировании лучше импортировать модули по их именам, чтобы при изменении контекста импорт работал. На этом этапе мы установим модуль colors с помощью функции install.
Установите новый модуль Node.js вне папки colors. Сначала перейдите в предыдущий каталог и создайте новую папку:
cd ..
mkdir really-large-application
Перейдите в каталог нового проекта:
cd really-large-application
Как и в случае с модулем colors, инициализируйте папку с помощью npm:
npm init -y
Данный package.json сгенерирует:
{
"name": "really-large-application",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Теперь установите модуль colors и используйте флаг –save, чтобы он был записан в файл package.json:
npm install --save ../colors
Вы только что установили свой модуль colors в новом проекте. Откройте файл package.json, чтобы увидеть новую локальную зависимость:
nano package.json
Вы обнаружите, что в него были добавлены следующие выделенные строки:
{
"name": "really-large-application",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"colors": "file:../colors"
}
}
Закройте файл.
Модуль colors был скопирован в каталог node_modules. Проверьте это с помощью следующей команды:
ls node_modules
Она вернет следующий вывод:
colors
Используйте установленный локальный модуль в этой новой программе. Снова откройте текстовый редактор и создайте еще один файл JavaScript:
nano index.js
Ваша программа сначала импортирует модуль colors. Затем она произвольно выберет цвет, используя предоставленную модулем функцию getRandomColor(). Наконец, она выведет на консоль сообщение о том, какой цвет использовать.
Введите следующий код в index.js:
const colors = require('colors');
const chosenColor = colors.getRandomColor();
console.log(`You should use ${chosenColor.name} on your website. It's HTML code is ${chosenColor.code}`);
Сохраните и закройте файл.
Ваше приложение теперь может сообщать пользователю случайный цвет для веб-сайта.
Запустите этот скрипт:
node index.js
Ваш вывод будет примерно таким:
You should use leafygreen on your website. It's HTML code is #48C9B0
Итак, вы успешно установили модуль colors и можете управлять им, как и любым другим пакетом npm, используемым в вашем проекте. Однако, если вы добавите больше цветов и функций в свой локальный модуль colors, вам придется запустить в своих приложениях команду npm update, чтобы иметь возможность использовать новые параметры. Далее мы попробуем настроить автоматические обновления при изменении кода модуля.
4: Связывание с локальным модулем
Если ваш локальный модуль находится в активной разработке, постоянно обновлять пакеты вручную может быть утомительно. Но вы можете связать модули. Связывание модулей гарантирует, что все обновления в локальном модуле немедленно отразятся в приложениях, использующих его.
На этом этапе мы свяжем модуль colors с вашим приложением. Мы также изменим модуль colors и проверим, появились ли его последние изменения в приложении (без переустановки или обновления вручную).
Сначала удалите локальный модуль:
npm un colors
npm связывает модули с помощью символических ссылок (или симлинков): это ссылки, которые указывают на файлы или каталоги на вашем компьютере. Связывание модуля выполняется в два этапа:
- Создание глобальной ссылки на модуль. npm создает симлинк между глобальным каталогом node_modules и каталогом модуля. Глобальный каталог node_modules – это каталог, в котором установлены все общесистемные пакеты npm (каждый пакет, который вы устанавливали с флагом -g).
- Создание локальной ссылки. npm создает симлинк между локальным проектом, использующим модуль, и глобальной ссылкой модуля.
Сначала создайте глобальную ссылку, вернувшись в каталог colors и используя команду link:
cd ../colors
sudo npm link
После этого оболочка вернет:
/usr/local/lib/node_modules/colors -> /home/8host/colors
В каталоге node_modules вы создали симлинк на каталог colors.
Вернитесь в каталог really-large-application и создайте ссылку на пакет:
cd ../really-large-application
sudo npm link colors
Вы получите подобный вывод:
/home/8host/really-large-application/node_modules/colors -> /usr/local/lib/node_modules/colors -> /home/8host/colors
Примечание: Вместо link можно использовать ln. Например, команда npm ln colors будет работать точно таким же образом.
Как показывают выходные данные, вы только что создали символическую ссылку из локального каталога node_modules приложения на глобальную ссылку, которая указывает на фактический каталог с модулем colors.
Процесс связывания завершен. Запустите файл, чтобы убедиться, что он работает:
node index.js
You should use sunkissedyellow on your website. It's HTML code is #F4D03F
Функциональность вашей программы не повреждена. Затем убедитесь, что обновления применяются сразу же. В текстовом редакторе снова откройте файл index.js:
cd ../colors
nano index.js
Теперь добавьте функцию, которая выбирает лучший из существующих оттенков синего. Она не принимает аргументов и всегда возвращает третий элемент массива allColors. Добавьте эти строки в конец файла:
class Color {
constructor(name, code) {
this.name = name;
this.code = code;
}
}
const allColors = [
new Color('brightred', '#E74C3C'),
new Color('soothingpurple', '#9B59B6'),
new Color('skyblue', '#5DADE2'),
new Color('leafygreen', '#48C9B0'),
new Color('sunkissedyellow', '#F4D03F'),
new Color('groovygray', '#D7DBDD'),
];
exports.getRandomColor = () => {
return allColors[Math.floor(Math.random() * allColors.length)];
}
exports.allColors = allColors;
exports.getBlue = () => {
return allColors[2];
}
Сохраните и закройте файл. Откройте файл index.js в каталоге really-large-application:
cd ../really-large-application
nano index.js
Отправьте вызов недавно созданной функции getBlue() и выведите предложение со свойствами цвета. Добавьте эти строки в конец файла:
const colors = require('colors');
const chosenColor = colors.getRandomColor();
console.log(`You should use ${chosenColor.name} on your website. It's HTML code is ${chosenColor.code}`);
const favoriteColor = colors.getBlue();
console.log(`My favorite color is ${favoriteColor.name}/${favoriteColor.code}, btw`);
Сохраните и закройте файл.
Теперь код использует новую функцию getBlue(). Выполните файл:
node index.js
Вы получите такой вывод:
You should use brightred on your website. It's HTML code is #E74C3C
My favorite color is skyblue/#5DADE2, btw
Ваш скрипт смог использовать новую функцию в модуле colors без команды npm update. Это облегчит внесение изменений в это приложение в процессе разработки.
При написании больших и сложных приложений подумайте о том, как связанный код можно сгруппировать в модули и как вы хотите эти модули настроить. Если ваш модуль будет использоваться только одной программой, он может оставаться в том же проекте и работать по относительному пути. Если же вы собираетесь переместить его из каталога этого проекта в другое место, лучше использовать установку или связывание. Модули в активной разработке также выигрывают от автоматических обновлений ссылок. Если модуль не находится в активной разработке, использование npm install может быть более простым вариантом.
Читайте также: Подготовка приложения Node.js к производству в Ubuntu 18.04
Tags: Mac OS, Node.js, REPL, Ubuntu 18.04