Все, что вам нужно знать для создания полезного и доступного пакета npm

После запуска опубликовать пакет npm можно так же просто, как ввести npm publish в терминал. Но настроить пакет впервые, протестировать его локально и написать полезный README может быть непросто, если вы новичок.

Недавно я опубликовал свой первый общедоступный пакет npm. Я решил проблему, которая применялась ко многим моим личным проектам, и поэтому подумал - на случай, если у кого-то возникнет такая же проблема - почему бы не сделать код общедоступным в виде пакета npm?

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

Установить npm

Скорее всего, если вы заинтересованы в предоставлении пакета для npm, он у вас уже установлен. Если нет, то он поставляется с Node.js, так что зайдите на сайт Node.js и установите его.

Выберите название пакета

Перед созданием нового репозитория стоит проверить, доступно ли имя вашего пакета на npmjs.com: для пакета без области действия выбранное имя должно быть уникальным. Если вы используете пакет с ограниченной областью действия, например @username/package, это не так важно. Хотя вы, конечно, можете выбрать имя пакета позже, получение его прямо сейчас сэкономит вам время.

Инициализируйте свой проект

Как и для любого проекта Node.js, вам понадобится package.json файл. Для частных проектов вы можете оставить большинство полей пустыми, но для общедоступного пакета npm вы захотите предоставить как можно больше полезной информации.

Файл package.json должен содержать поля name и version, но на самом деле вы, вероятно, захотите покрыть следующие поля:

Поле "engines" необязательно в каждом проекте, но стоит знать, будет ли ваш код работать, например, только в определенных версиях Node.js. Вы можете гарантировать, что разрешены только указанные версии, добавив "enginesStrict": true.

Некоторые из этих полей содержат URL-адреса, которых пока не существует, поэтому на следующем шаге мы подключим наш проект к Github.

Инициализировать Git

Хотя вы можете использовать любую систему контроля версий, в этом руководстве мы остановимся на самом популярном решении: Github. Если вы новичок в GitHub, я рекомендую ознакомиться с официальным руководством.

Создайте новый репозиторий, возьмите URL-адрес и перейдите к своему проекту в терминале. Затем введите следующее:

git init
git add .
git commit -m "Initial commit"
git remote add origin remote repository URL
git push origin master

Преимущество использования GitHub заключается в том, что он сразу же предоставит вам homepage, repository.url и bugs.url для вашего package.json файла.

Позаботьтесь о том, чтобы указать правильные пути

Прежде чем мы перейдем к написанию кода, стоит указать на область, в которой я столкнулся с некоторыми ошибками: пути!

Как и любой другой модуль узла, ваш пакет после установки будет находиться в каталоге node_modules проекта, а не в корне вашего собственного проекта. Итак, при создании проекта вы должны быть осторожны с тем, хотите ли вы использовать абсолютный или относительный путь. Особенно при использовании относительных путей помните о потенциально ином поведении в вашей тестовой среде. Например, должен ли этот путь быть относительно корневого каталога всего проекта или пакета внутри каталога node_modules?

__dirname vs ‘./’

Большинство моих проблем было решено за счет зависимости от глобального объекта __dirname, а не от синтаксиса относительного пути, такого как . или ./my-directory.

Ключевое отличие состоит в том, что __dirname всегда ссылается на каталог, в котором находится исполняемый в данный момент скрипт. Напротив, . дает вам каталог, из которого вы запускали команду узла.

Итак, если мы введем __dirname в dir1/dir2/myfile.js, мы получим dir1/dir2/ независимо от того, где мы находимся в терминале. Но если мы используем . в нашем файле, перейдем к dir1 в терминале и запустим node dir2/myfile.js, вместо этого мы получим dir1!

Ключевое исключение

Если вы помните вышеупомянутое различие, это должно обеспечить бесперебойную работу. Однако есть ключевое исключение: глобальная функция require() принимает синтаксис относительного пути, но в этом случае - и только в этом случае - путь будет относиться к вызывающему ее файлу, как и __dirname!

Модуль пути

Разработчики-ветераны Node.js будут хорошо знакомы со встроенным модулем path. В противном случае это полезный способ обеспечить кроссплатформенную совместимость - и в нем есть несколько удобных инструментов для управления вашими путями. Базовый вариант использования может выглядеть так:

const path = require('path');
const my_path = path.join(__dirname, 'my-dir', 'my-file.js');

Это эквивалентно ./my-dir/my-file.js, если мы запустили его из корневого каталога в терминале.

Напишите код

С моим предупреждением о путях мы можем продолжить создание нашего образца пакета. Чтобы не усложнять задачу, мы сделаем наш пример кода очень простым. Допустим, нам надоело писать console.log(), и мы лучше напишем log(). Мы можем сделать для этого пакет!

В любой файл, который мы выбрали в качестве корня нашего проекта (обычно index.js), добавьте следующее:

function log(msg){
  console.log(msg);
};
module.exports = log;

Когда мы перейдем к импорту log из нашего пакета, синтаксис будет const log = require('my-module-name').

Добавить несколько экспортов

Если вы привыкли к разделению кода в Node.js, вы должны знать module.exports. Он позволяет вам экспортировать переменную, которая может быть любым объектом - часто, как указано выше, функцией.

Если вы хотите обеспечить несколько операций импорта из одного пакета, вы можете включить их в объект. Например, давайте добавим в наш пакет больше функций:

function log(msg){
  console.log(msg);
};
function shout(msg){
  if (typeof msg === str) { 
    console.log(msg.toUpperCase()) 
  } else {
    log(msg)
  };
};
function whisper(msg){
  if (typeof msg === str) { 
    console.log(msg.toLowerCase()) 
  } else {
    log(msg)
  };
};

Чтобы экспортировать каждую функцию, мы можем написать:

module.exports = {log, shout, whisper};

Затем, когда мы позже перейдем к импорту этих методов из нашего модуля, мы можем использовать деструктурирующий синтаксис присваивания ES6 +, чтобы поместить каждую функцию, которая нам нужна, в одной строке:

const { log, shout, whisper } = require('my-module-name');

Добавить аргумент параметров

В качестве альтернативы, вместо того, чтобы экспортировать несколько методов, мы можем предоставить аргумент options внутри нашей исходной функции log. Например, мы могли бы указать параметр громкости с возможными значениями 'shout', 'whisper' и 'default':

function log(msg, options = { loudness: 'default' }){
  if (options && options.loudness) {
    switch (options.loudness) {
      case 'shout':
        if (typeof msg === str) console.log(msg.toUpperCase());
        break;
      case 'whisper':
        if (typeof msg === str) console.log(msg.toLowerCase());
        break;
      default:
        console.log(msg);
    }
  }
};
module.exports = log;

Как это повлияет на импортирование нашего модуля? Теперь, вместо выбора другого метода, пользователи могут управлять поведением log с помощью необязательного аргумента:

const log = require('my-module-name');
log('Hello World', { loudness: 'shout' });

Для нашего случая использования, вероятно, лучше всего использовать параметры, а не отдельные методы, поскольку основные функции log остаются прежними. Но как ваши пользователи узнают, что эти варианты существуют? Это плавно подводит нас к документации.

Напишите отличный README

Если вы размещаете какой-то код в открытом доступе, вам нужно будет объяснить, как другие люди могут его использовать. В зависимости от типа и сложности вашего проекта, написание отличного README может занять большую часть вашего общего времени разработки!

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

Я рекомендую взглянуть на популярные пакеты npm с функциональностью, аналогичной вашей, и посмотреть, как они структурируют свои README.md файлы. Вы также можете проверить 12 самых популярных пакетов на домашней странице npm.

Для простого продукта минимальный файл REAME.md, вероятно, должен включать следующие разделы:

  • Установка / Начало работы: шаги по установке пакета и его импорту в приложение.
  • Пример кода / Быстрый старт: простой пример работы вашего пакета. Для простого пакета многие люди предпочтут увидеть рабочий пример, чтобы сразу начать работу, поэтому поместите его в самом верху.
  • Свяжитесь с нами / авторами: какой-то способ узнать, кто создал пакет и как с ними связаться, если кто-то захочет задать вопрос, сообщить об ошибке или внести свой вклад в пакет. Если вы серьезно относитесь к получению вклада, вы можете включить файл CONTRIBUTING.md: вот популярный шаблон для этого.
  • Лицензия. Наконец, рекомендуется указывать лицензию по отдельности. Опять же, если вы настроены более серьезно, вы можете создать отдельный LICENSE.md файл. На GitHub есть полезное руководство по лицензированию, а также некоторые файлы шаблонов.

Протестируйте свой пакет локально

Прежде чем поделиться своим пакетом со всем миром, вы должны быть уверены, что пакет работает. Есть несколько способов протестировать ваш пакет. Для меня лучше всего сработало следующее:

Шаг 1:

Создайте новый каталог в корневой папке вашего проекта. (Я не рекомендую называть ваш каталог test, поскольку это может привести к путанице, если вы используете среду тестирования - я назвал свой test-directory).

Шаг 2:

Добавьте test-directory в свой .gitignore файл (и, если вы используете файл .npmignore, добавьте его туда же).

Шаг 3:

Для этого шага у вас есть два варианта.

А. Откройте терминал, перейдите к test-directory и введите npm i "absolute/path/to/my/package"

Б. Откройте терминал, перейдите в корневой каталог вашего пакета и введите npm link. Затем перейдите к test-directory и введите npm link my-package-name.

В целом использование npm link (Вариант Б) может обеспечить более плавную разработку, особенно если ваши потребности более сложные: например, если вы разрабатываете несколько взаимозависимых пакетов.

Но мне нравится вариант А, потому что он больше напоминает процесс установки живого пакета npm.

Опубликуйте свой пакет

Если вы счастливы, что ваш пакет работает правильно и у вас есть хороший README.md файл, то вы готовы к запуску!

  • Если вы еще этого не сделали, зарегистрируйтесь в npm. Изображение профиля и ссылка на GitHub могут сделать вас более представительным, если вы надеетесь на соавторов!
  • Войдите в свой терминал, введите npm login и введите свои данные.
  • В терминале перейдите в корневой каталог вашего пакета и введите npm publish

Это так просто! Если имя пакета уже используется, вы получите сообщение об ошибке о том, что пакет не принадлежит вам, и вам придется выбрать другое имя.

Если все прошло успешно, поздравляем - теперь вы являетесь автором пакета npm!

Обновите свой пакет

Отправка кода в систему контроля версий не приведет к автоматическому обновлению пакета npm. Для этого вам нужно запустить npm publish в терминале.

Вы не можете переопределить версию или свой пакет, которые уже были опубликованы, поэтому перед запуском npm publish вам следует обновить версию своего приложения.

Контроль версий

npm использует систему управления версиями под названием Semantic Versioning или SemVer. Вы можете прочитать больше об этом здесь". По умолчанию ваш пакет должен начинаться с версии 1.0.0. Самый маленький класс обновлений - это patch, затем есть minor обновление и major обновление.

В общем, patch предназначен для исправления ошибок с обратной совместимостью. minor обновление предназначено для новых функций с обратной совместимостью. А обновление major включает изменения, нарушающие обратную совместимость.

Чтобы упростить эту задачу, в npm есть методы контроля версий, которые автоматически обрабатывают это за вас:

npm version patch // 1.0.1
npm version minor // 1.1.0
npm version major // 2.0.0

Добавить значки

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

Один из самых простых способов добавить их в ваш README.md файл - использовать Shields.io.

Все, что вам нужно для этого, - предоставить URL-адреса различных служб, которые вы используете, например репозитория GitHub или страницы вашего пакета, а Shields.io предоставит вам уценку со значком.

Вот и все!

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