В этом руководстве я проведу вас через процесс создания и публикации простого пакета в реестре npm.

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

Предположения

В этом руководстве предполагается, что вы используете Git в качестве системы контроля версий и GitHub для размещения своего кода.

TL;DR

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

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

1. Начало работы

Что такое npm?

Npm - это менеджер пакетов по умолчанию для Node.js и крупнейший в мире реестр программного обеспечения. Разработчики с открытым исходным кодом используют npm для обмена программным обеспечением. Он состоит из клиента командной строки (устанавливается автоматически вместе с Node.js) и онлайн-базы данных общедоступных и оплачиваемых частных пакетов, называемой регистрацией npm.

Обновить узел и npm

Во-первых, убедитесь, что у вас последняя версия Node.js и npm. Откройте окно терминала и убедитесь, что версия npm обновлена:

~ $ npm i -g npm@latest

Создать учетную запись npm

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

Войти в npm

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

~ $ npm login

Вы должны получить подобное сообщение:

~ $ npm login
Username: <your-username>
Password:
Email: (this IS public) <your-email>
Logged in as <your-username> on https://registry.npmjs.org/.

Излишне говорить, что <your-username> и <your-email> будут вашим собственным именем пользователя и адресом электронной почты.

2. Инициализировать пакет.

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

Без очевидной причины я назову свой пакет «spongepoop». Однако вы можете выбрать любое другое имя для своего пакета.

~ $ mkdir spongepoop

Внутри каталога вашего пакета запустите команду инициализации:

~ $ cd spongepoop
spongepoop $ npm init

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

Файл Package.json

Когда вы закончите, вы увидите новый файл package.json, созданный в корневом каталоге пакета. Все пакеты npm содержат такой файл. Этот файл используется для описания вашего пакета и позволяет npm обрабатывать зависимости пакета.

Объем пакета

На npm много пакетов. Выбранное вами имя могло уже быть выбрано кем-то другим. В этом случае вы можете создать пакет с ограниченным объемом.

Пакет с ограниченной областью видимости имеет имя пользователя (или название организации), добавленное в начало имени пакета, и выглядит примерно так:

@ somescope / somepackagename

Возможно, вы уже видели этот шаблон именования в таких пакетах, как @ babel / cli, @ Emotion / core или @ storybook / addons.

В этом образце я буду использовать «spongepoop».

Проверьте npm scopes для получения дополнительной информации.

Версия пакета

Каждому пакету npm нужен номер версии. Это помогает разработчикам узнать, безопасно ли обновляться до определенной версии вашего пакета, не нарушая их код.

Система управления версиями, которую использует npm, называется SemVer (семантическое управление версиями). По сути, номер версии состоит из трех частей:

MAJOR.MINOR.PATCH

Для версии 10.12.5 старший номер 10, младший номер 12 и номер патча 5.

Части номера версии должны увеличиваться следующим образом:

Версия MAJOR увеличивается, если вы вносите несовместимые изменения API.

Версия MINOR увеличивается при добавлении обратно совместимых функций.

Версия PATCH увеличивается при исправлении ошибок с обратной совместимостью.

Вам не нужно беспокоиться об управлении номером версии вручную. Для увеличения этих чисел существует команда npm:

$ npm version patch     # 0.1.0 -> 0.1.1
$ npm version minor     # 0.2.6 -> 0.3.0
$ npm version major     # 2.1.4 -> 3.0.0

Начните с версии 0.1.0, затем используйте команду npm version по мере продвижения разработки.

Обратите внимание, что ваш рабочий каталог должен быть чистым (без незафиксированных изменений) для использования команды npm version.

Проверьте SemVer и npm version для получения дополнительной информации.

3. Опубликовать сейчас

То, что у вас есть сейчас, достаточно для публикации вашего пакета. Давай, попробуй:

spongepoop $ npm publish

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

spongepoop $ npm publish --access=public

Появится связка строк, а затем, наконец, строка, которая выглядит следующим образом:

+ [email protected]

Это означает, что ваш пакет был успешно опубликован в npm с номером версии 0.1.0, и вы можете установить его в любом проекте, как и любой другой пакет npm:

another-project $ npm i spongepoop

4. Создайте репозиторий.

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

spongepoop $ git init

Затем создайте репо на GitHub. Я выбрал лицензию MIT, но вы можете выбрать любую лицензию, которую хотите.

После того, как вы создали репо на GitHub, добавьте удаленный URL-адрес в локальное репо:

spongepoop $ git remote add origin <your-repo-url>
spongepoop $ git pull origin master

Вы должны получить три новых файла в каталоге пакета: LICENSE, .gitignore и README.md. Пришло время написать код.

5. Создайте файл EditorConfig.

Конфигурационный файл редактора помогает определить согласованные стили кодирования между различными редакторами и IDE, и он доступен для чтения всеми популярными редакторами кода, включая Sublime Text, Atom и VSCode.

Создайте файл .editorconfig внутри каталога вашего пакета:

root = true
# General settings for whole project
[*]
indent_style = space
end_of_line = lf
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
# Format specific overrides
[*.md]
max_line_length = 0
trim_trailing_whitespace = false

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

6. Начните писать код.

Создайте файл src / index.js внутри каталога вашего пакета и начните писать код:

/**
* Adds two numbers and returns the result in poop emoji.
* @param {Number} a First number
* @param {Number} b Second number
*/
module.exports = function(a, b) {
  return Array.apply(null, Array(a + b)).map(
    function() {
      return '💩';
    }
  ).join('');
};

Вы можете структурировать свой код как хотите. Мне лично нравится помещать все файлы исходного кода в каталог src.

Файл «main» - это точка входа в вашу программу. Возможно, вам потребуется отредактировать package.json и изменить основной файл на src / index.js

{
  ...
  "main": "src/index.js",
  ...
}

Теперь давайте проверим нашу маленькую функцию:

spongepoop $ node  # start node REPL in the package directory
> var pooper = require('.'); // the dot resolves to the main file
> pooper(1,2); // logs three poop emojis
'💩💩💩'

Проверьте npm docs для получения дополнительной информации о файле package.json.

7. Используйте современный JavaScript.

Язык JavaScript получил значительное обновление, которое предоставляет огромное количество полезных функций. На дворе 2019 год, и вы уже должны быть знакомы с большинством новых функций, но если вы еще не знакомы, то можете проверить этот отличный пост от Flavio Copes.

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

Начнем с переписывания кода:

/**
* Adds two numbers and returns the result in poop emoji.
* @param {Number} a First number
* @param {Number} b Second number
*/
export const spongepoop = (a, b) => '💩'.repeat(a + b);

Давайте еще раз проверим нашу функцию:

spongepoop $ node
> var pooper = require('.');
.../spongepoop/src/index.js:7
export const spongepoop = (a, b) => '💩'.repeat(a + b);
^^^^^^
SyntaxError: Unexpected token export

Теперь мы получаем синтаксическую ошибку. Это связано с тем, что Node.js еще не полностью поддерживает все новые функции. Чтобы решить эту проблему, мы можем использовать инструмент для преобразования кода в простой синтаксис ES5, который поддерживается всеми версиями Node.js. Инструмент, который мы ищем, называется Вавилон.

Транспилировать код

Внутри каталога пакета установите следующие зависимости:

spongepoop $ npm i -D @babel/core @babel/cli @babel/preset-env

@babel/core Содержит основные функции Babel.
@babel/cli Позволяет использовать Babel из терминала.
@babel/preset-env Предустановка, включающая все плагины для поддержки современного JS.

Вы можете настроить Babel разными способами, один из них - с помощью файла .babelrc.

Создайте файл .babelrc в корне пакета и измените его содержимое, чтобы оно соответствовало следующему:

{
  "presets": [
    "@babel/preset-env"
  ]
}

Затем создайте сценарий для преобразования кода в нормальный синтаксис ES5 с помощью Babel CLI. Добавьте сценарий сборки в файл package.json:

{
  ...
  "scripts": {
    ...
   "build:commonjs": "babel src --out-dir lib",
    ...
  },
  ...
}

Запуск этого сценария npm run build:commonjs создаст каталог lib с транспилированным кодом внутри. Commonjs - это стандартная спецификация модуля, которую использует Node.js.

Наконец, измените основной файл в package.json так, чтобы он ссылался на lib / index.js вместо src / index.js. Это направит проекты, использующие ваш пакет, в import или require из каталога lib, где существует обычный код ES5, а не из src.

{
  ...
  "main": "lib/index.js",
  ...
}

Теперь запустите npm run build:commonjs внутри каталога пакета, чтобы собрать (транспилировать) код, затем снова протестируйте пакет:

spongepoop $ node
> var pooper = require('.');
> pooper(2,1); // successfully poops 3 times
'💩💩💩'

Создать версию UMD

UMD означает универсальное определение модуля. Проще говоря, это означает объединение всего вашего кода и всех его зависимостей в один файл. Этого можно добиться с помощью сборщика модулей под названием Webpack.

Добавьте в свой пакет следующие зависимости разработки:

spongepoop $ npm i -D webpack webpack-cli cross-env

Cross-env - это пакет, который позволяет правильно задавать переменные окружения на разных платформах.

Создайте файл конфигурации webpack.config.js для Webpack в корне пакета. Содержимое webpack.config.js должно быть:

const path = require('path');
const { NODE_ENV, FILE_NAME } = process.env;
const filename = `${FILE_NAME}${NODE_ENV === 'production' ? '.min' : ''}.js`;
module.exports = {
  mode: NODE_ENV || 'development',
  entry: [
    './src/index.js',
  ],
  output: {
    path: path.join(__dirname, 'dist'),
    filename,
    libraryTarget: 'umd',
  },
};

Затем добавьте следующие сценарии сборки в package.json:

...
"scripts": {
 ...
 "build:umd": "cross-env FILE_NAME=spongepoop webpack",
 "build:umd:min": "cross-env NODE_ENV=production npm run build:umd",
 ...
},
...

Выполнение команд npm run build:umd и npm run build:umd:min внутри каталога пакета приведет к созданию новой папки с именем dist, содержащей два файла: spongepoop.js и spongepoop.min.js соответственно .

Очистите перед строительством

На всякий случай не забудьте удалить каталоги lib и dist перед сборкой.

Добавьте римраф в качестве зависимости развития:

spongepoop $ npm i -D rimraf

Затем добавьте чистый скрипт:

...
"scripts": {
 ...
 "clean": "rimraf lib dist",
 ...
},
...

Наконец, добавьте сценарий сборки, который выполняет все вышеперечисленное:

...
"scripts": {
 ...
 "build": "npm run clean && npm run build:commonjs && npm run build:umd && npm run build:umd:min",
 ...
},
...

8. Используйте руководство по стилю.

Руководство по стилю - это набор стандартов, определяющих, как должен быть написан и организован код. Чтобы обеспечить соблюдение руководства по стилю, вам понадобится линтер кода.
Линтер кода - это программа, которая помогает экономить время и писать чистый и поддерживаемый код, анализируя ваш код на предмет потенциальных ошибок.

ESLint - самый популярный инструмент для линтинга JavaScript, и он имеет плагины для многих популярных редакторов, таких как VSCode, Sublime Text и Atom, чтобы обеспечить линтинг кода в реальном времени.

Установить ESLint

Установите ESLint как зависимость для разработки:

spongepoop $ npm i -D eslint

Настроить ESLint

ESLint можно настроить с помощью файла configuration. eslintrc. Создайте этот файл в корне пакета и измените его содержимое так, чтобы он выглядел так:

{
  "env": {
    "browser": true,
    "node": true
  }
}

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

Руководство по стилю AirBnB

Если у вас еще нет руководства по стилю, которому можно следовать, то вам обязательно следует принять руководство по стилю AirBnB. Это очень полный набор стандартов кодирования и одно из самых популярных руководств по стилю в Интернете.

Установите it из npm как зависимость для разработки:

spongepoop $ npm i -D eslint-config-airbnb

Руководство по стилю AirBnB требует установки других пакетов, поэтому давайте добавим и их:

spongepoop $ npm i -D eslint-plugin-import
spongepoop $ npm i -D eslint-plugin-jsx-a11y
spongepoop $ npm i -D eslint-plugin-react

Теперь вам нужно объявить, что вы будете использовать руководство по стилю в файле .eslintrc:

{
  "extends": "airbnb",
  "env": {
    "browser": true,
    "node": true
  }
}

Линтинг нестандартного синтаксиса ECMAScript

Новые функции ECMAScript, такие как свойства класса, действительно полезны, но они могут еще не быть частью стандартов, и ESLint выдаст ошибку синтаксического анализа, если вы их используете. Чтобы обойти это, мы будем использовать babel-eslint в качестве парсера ESLint.

Установите babel-eslint как зависимость для разработки:

spongepoop $ npm i -D babel-eslint

Затем используйте его в файле .eslintrc:

{
  "parser": "babel-eslint",
  "extends": "airbnb",
  "env": {
    "browser": true,
    "node": true
  }
}

Добавить скрипт для линтинга

Создайте сценарий «lint» в файле package.json:

{
  ...
  "scripts": {
    ...
    "lint": "eslint src --ext .js,.jsx",
    ...
  },
  ...
}

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

spongepoop $ npm run lint

Выполнение приведенной выше команды приводит к одной ошибке: «Предпочитать экспорт по умолчанию». Вы всегда можете изменить правила eslint в соответствии со своими потребностями. Исправим эту ошибку:

/**
* Adds two numbers and returns the result in poop emoji.
* @param {Number} a First number
* @param {Number} b Second number
*/
const spongepoop = (a, b) => '💩'.repeat(a + b);
export default spongepoop;

9. Проверьте свой код.

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

Jest - это быстрый и полный фреймворк для тестирования JavaScript. Это проект с открытым исходным кодом, поддерживаемый Facebook, и он особенно хорошо подходит (но не ограничивается) для тестирования кода React.

Добавьте Jest как зависимость для разработки:

spongepoop $ npm i -D jest babel-jest

Babel Jest необходим для использования Babel в ваших тестах.

Добавить тестовый скрипт

Отредактируйте package.json и измените тестовый сценарий на использование Jest:

{
  ...
  "test": "jest",
  ...
}

Создайте каталог tests в корне пакета и добавьте образец тестового файла index.test.js:

import pooper from '../src';
describe('Test', () => {
  it('should poop 3 times', () => {
    expect(pooper(1, 2)).toBe('💩💩💩');
  });
});

Вы можете получить несколько ошибок линтинга в тестовом файле, потому что функции describe, it и expect не определены. Это можно легко исправить, включив среду Jest.

Отредактируйте файл .eslintrc, чтобы включить Jest:

{
  ...
  "env": {
    "browser": true,
    "node": true,
    "jest": true
  },
  ...
}

Теперь запустите npm test, и тест должен пройти без проблем.

10. Добавьте символ к вашему пакету

Имеет смысл протестировать ваш пакет в фиктивном проекте, как если бы он был установлен из npm, и посмотреть, правильно ли он работает. Но не имеет смысла npm publish ваш пакет, а затем npm install его каждый раз, когда вам нужно его тестировать.

Существует удобный способ привязать ваш пакет локально в два этапа:

Первый шаг

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

spongepoop $ npm link

Второй шаг

Затем в другом месте, где вы хотите протестировать свой пакет, запустите команду npm link <package-name>, и вы сможете import или require пакет, как если бы он был установленной зависимостью.

Обратите внимание, что <package-name> берется из package.json, а не из имени каталога.

Предположим, вы создали другое тестовое приложение или пакет под названием my-test-app:

my-test-app $ npm link spongepoop

Это создаст символическую ссылку из вашего глобально установленного пакета на node_modules текущей папки.

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

spongepoop $ npm unlink

11. Используйте непрерывную интеграцию

Travis CI - это платформа непрерывной интеграции и доставки, которая запускает ваши тесты каждый раз, когда вы делаете коммит или объединяете пулреквест в репозитории GitHub.

Travis CI бесплатен для проектов с открытым исходным кодом, поэтому перейдите на их веб-сайт и зарегистрируйтесь, используя свою учетную запись GitHub.

Примите авторизацию Travis CI, и вы будете перенаправлены на GitHub.

Нажмите зеленую кнопку Активировать и выберите репозитории, которые вы хотите использовать с Travis CI.

Создайте .travis.yml файл в корне каталога вашего пакета, чтобы сообщить Travis CI, что делать. Содержимое файла должно быть примерно таким:

language: node_js
node_js:
  - node

Зафиксируйте свой код и нажмите, затем проверьте сборку на сайте Travis, она должна пройти.

Подробнее о настройке travis для Node.js вы можете узнать здесь.

12. Добавить статистику покрытия кода

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

Попробуйте выполнить эту команду внутри каталога пакета:

spongepoop $ npx jest --coverage

Вы получите подробную информацию о том, сколько кода покрыто. Давайте добавим для этого сценарий в package.json:

{
  ...
  "test": "jest",
  "coverage": "npm test -- --coverage",
  ...
}

Вы можете показать это людям с помощью инструмента под названием Комбинезон.

Комбинезоны - это размещенный инструмент анализа, который можно интегрировать с Travis CI для получения статистики о покрытии вашего кода. Комбинезоны бесплатны для проектов с открытым исходным кодом, так что зарегистрируйтесь со своей учетной записью GitHub.

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

spongepoop $ npm i -D coveralls

Затем обновите файл .travis.yml следующим образом:

language: node_js
node_js:
  - node
script:
  - npm run coverage -- --coverageReporters=text-lcov | coveralls

Это будет отправлять отчет о покрытии в Комбинезоны после каждой сборки.

Последний шаг, который нужно сделать, - это перейти на https://coshopss.io/ и щелкнуть ссылку Добавить репо в меню:

Затем включите тумблер репозитория:

Зафиксируйте свой код и отправьте его на GitHub. Travis CI должен подхватить толчок и начать новую сборку. После завершения сборки проверьте свое репозиторий на комбинезоне, и вы должны найти обновленный отчет.

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

Давайте добавим значки в файл readme. Вы будете написать файл readme, верно?
Перейдите на shields.io и выберите несколько значков. Я выбрал несколько:

14. Будьте осторожны.

Чтобы избежать ошибок при публикации, давайте перед запуском npm publish убедитесь, что мы тестируем, линтируем и собираем. Измените package.json, чтобы добавить следующие сценарии:

{
  ...
  "lint": "eslint src --ext .js,.jsx",
  "test": "jest",
  "coverage": "npm test -- --coverage",
  "posttest": "npm run lint",
  "prepublishOnly": "npm test && npm run build",
  ...
}

Сценарий prepublishOnly будет запускаться автоматически перед запуском npm publish, а posttest будет запускаться автоматически после npm test выполнения.

Таким образом, всякий раз, когда вы запускаете команду npm publish, следующие сценарии будут выполняться последовательно:
npm test, затем npm run lint, затем npm run build и, наконец, npm publish.

Выполнено

Теперь давайте попробуем опубликовать еще раз, но сначала давайте обновим версию пакета:

spongepoop $ npm version minor
v0.2.0
spongepoop $ npm publish
...
+ [email protected]

Все готово, поздравляем! 🎉

Инструмент командной строки

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

Сначала установите его глобально:

$ npm i -g spongepoop

Затем используйте его где угодно:

$ poop my-new-project

Заключение

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

Спасибо, что дочитали до конца этого руководства.