Легко создавать и публиковать модуль npm в репозитории npm

Вступление

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

Сделав это, вы поймете:

  1. Как создать пакет npm
  2. Как установить его локально перед публикацией, чтобы проверить его работоспособность
  3. Как установить и использовать опубликованный пакет с помощью синтаксиса импорта ES6 или с помощью инструкции Node.js require
  4. Как управлять семантическими версиями пакета
  5. Как обновить пакет до новой версии и опубликовать заново

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

Предпосылки

Для выполнения этого урока вам понадобится следующее:

  • Допустимая установка контроля версий Git
  • Node.js установлен локально, что вы можете сделать, следуя инструкциям на этой странице.

Это руководство было проверено на Node v13.14.0, npm v6.14.4 и axios v0.20.0

Шаг 1 - Начальная настройка

Создайте новую папку с именем github-repos-search и инициализируйте файл package.json

mkdir github-repos-search
cd github-repos-search
npm init -y

Инициализируйте текущий проект как репозиторий git, выполнив следующую команду из папки github-repos-search:

git init .

Создайте файл .gitignore, чтобы исключить папку node_modules. Добавьте следующее содержимое в .gitignore файл

node_modules

Установите пакет axios, который вы будете использовать для вызова API GitHub.

npm install [email protected]

Ваш package.json теперь будет выглядеть так:

{
  "name": "github-repos-search",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "dependencies": {
    "axios": "^0.20.0"
  },
  "devDependencies": {},
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Внутри package.json файла значение имени - github-repos-search. Таким образом, имя нашего пакета после публикации в репозитории npm станет github-repos-search. Кроме того, имя должно быть уникальным в репозитории npm, поэтому сначала проверьте, существует ли такой репозиторий npm, перейдя к https://www.npmjs.com/package/<your_repository_name_from_package_json>. В противном случае вы получите сообщение об ошибке при публикации пакета в репозиторий npm, если имя уже существует.

Шаг 2 - Написание кода

Создайте новый файл с именем index.js и добавьте в него следующее содержимое:

const axios = require('axios');
const getRepos = async ({
  username = 'myogeshchavan97',
  page = 1,
  per_page = 30
} = {}) => {
  try {
    const repos = await axios.get(
      `https://api.github.com/users/${username}/repos?page=${page}&per_page=${per_page}&sort=updated`
    );
    return repos.data
      .map((repo) => {
        return {
          name: repo.name,
          url: repo.html_url,
          description: repo.description,
          stars: repo.stargazers_count
        };
      })
      .sort((first, second) => second.stars - first.stars);
  } catch (error) {
    return [];
  }
};
getRepos().then((repositories) => console.log(repositories));

Давайте сначала разберемся с кодом.

  • Вы создали getRepos функцию, которая принимает необязательный объект со свойствами username, page и per_page.
  • Затем вы использовали синтаксис деструктуризации объекта для получения этих свойств из объекта.
  • Передача объекта в функцию не является обязательной, поэтому мы инициализировали его значениями по умолчанию, если объект не передается в функцию следующим образом:
{
  username = 'myogeshchavan97',
  page = 1,
  per_page = 30
} = {}
  • Причина назначения пустого объекта {} состоит в том, чтобы не получить ошибку при деструктуризации username объекта, если объект не передан. Прочтите мою предыдущую статью, чтобы подробнее узнать о деструктуризации.
  • Затем внутри функции вы вызываете GitHub API, передавая необходимые параметры, чтобы получить репозитории указанного пользователя, отсортированные по обновленной дате.
const repos = await axios.get(
      `https://api.github.com/users/${username}/repos?page=${page}&per_page=${per_page}&sort=updated`
    );
  • Здесь вы используете синтаксис async / await, поэтому функция getRepos объявлена ​​как async.
  • Затем вы выбираете только необходимые поля из ответа с помощью метода Array map
repos.data
  .map((repo) => {
    return {
      name: repo.name,
      url: repo.html_url,
      description: repo.description,
      stars: repo.stargazers_count
    };
  })

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

.sort((first, second) => second.stars - first.stars);
  • Если есть какая-либо ошибка, вы возвращаете пустой массив в блоке catch.
  • Поскольку функция getRepos объявлена ​​как async, вы вернете обещание, поэтому вы используете обработчик .then для получения результата вызова функции getRepos и вывода на консоль.
getRepos().then((repositories) => console.log(repositories));

Шаг 3 - Выполнение кода

Теперь запустите файл index.js, выполнив следующую команду из командной строки:

node index.js

Вы увидите следующий результат для первых 30 репозиториев:

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

getRepos({
  username: 'gaearon'
}).then((repositories) => console.log(repositories));

Снова запустите файл, выполнив команду node index.js, и вы увидите следующий результат:

Вы можете передать свойства page и per_page, чтобы изменить ответ, чтобы получить первые 50 репозиториев.

getRepos({
  username: 'gaearon',
  page: 1,
  per_page: 50
}).then((repositories) => console.log(repositories));

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

Удалите из файла приведенный ниже код.

getRepos({
  username: 'gaearon',
  page: 1,
  per_page: 50
}).then((repositories) => console.log(repositories));

и вместо этого добавьте строку ниже

module.exports = { getRepos };

Здесь вы экспортируете функцию getRepos как свойство объекта, поэтому позже, если вы захотите экспортировать любую другую функцию, вы можете легко добавить ее к объекту.

Таким образом, приведенная выше строка такая же, как

module.exports = { getRepos: getRepos };

Шаг 4 - Тестирование созданного пакета npm с помощью оператора require

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

Есть простой способ это проверить. Выполните следующую команду из командной строки из папки github-repos-search:

npm link

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

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

Теперь создайте новую папку на рабочем столе с любым именем, например, test-repos-library-node, и инициализируйте файл package.json, чтобы вы могли убедиться, что пакет установлен правильно:

cd ~/Desktop
mkdir test-repos-library-node
cd test-repos-library-node
npm init -y

Если вы помните, свойство name в package.json файле нашего пакета было github-repos-search, поэтому вам нужно потребовать, чтобы пакет использовал то же имя.

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

npm link github-repos-search

Создайте новый файл с именем index.js и добавьте в него следующий код:

const { getRepos } = require('github-repos-search');
getRepos().then((repositories) => console.log(repositories));

Здесь вы импортировали пакет прямо из папки node_modules (это было возможно только потому, что вы связали его с помощью ссылки npm)

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

node index.js

Вы увидите правильный вывод:

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

Шаг 5 - Тестирование созданного пакета npm с помощью оператора импорта

Вы проверили, что пакет работает, используя инструкцию require. Давайте проверим это с помощью оператора импорта ES6.

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

cd ~/Desktop
npx create-react-app test-repos-library-react

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

npm link github-repos-search

Теперь откройте файл src/App.js и замените его следующим содержимым:

import { getRepos } from 'github-repos-search';
import React from 'react';
import './App.css';
function App() {
  getRepos().then((repositories) => console.log(repositories));
  return (
    <div className="App">
      <h2>Open browser console to see the output.</h2>
    </div>
  );
}
export default App;

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

yarn start

Если вы проверите консоль браузера, вы увидите ожидаемый результат:

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

Шаг 6 - Опубликуйте в репозитории npm

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

Вернитесь в папку проекта github-repos-search, в которой вы создали пакет npm.

Давайте добавим метаданные в файл package.json, чтобы отобразить дополнительную информацию о пакете.

Вот последний package.json файл:

{
  "name": "github-repos-search",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "homepage": "https://github.com/myogeshchavan97/github-repos-search",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/myogeshchavan97/github-repos-search.git"
  },
  "dependencies": {
    "axios": "^0.20.0"
  },
  "devDependencies": {},
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "github",
    "repos",
    "repositories",
    "sort",
    "stars"
  ],
  "author": "Yogesh Chavan <[email protected]>",
  "license": "ISC"
}

Вы добавили homepage, repository, keywords и author для получения дополнительной информации (это необязательно). Внесите изменения в соответствии с вашим репозиторием GitHub.

Создайте новый репозиторий GitHub ЗДЕСЬ и нажмите github-repos-search репозиторий на GitHub. Перейдите на https://www.npmjs.com/ и создайте новую учетную запись, если у вас еще нет учетной записи.

Откройте терминал и из папки github-repos-search выполните следующую команду:

npm login

и введите свои учетные данные npm для входа.

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

npm publish

Если вы перейдете к https://www.npmjs.com/package/github-repos-search в браузере, вы увидите опубликованный пакет:

Теперь давайте добавим readme.md файл для отображения некоторой информации о пакете.

Создайте новый файл с именем readme.md внутри папки github-repos-search с содержимым отсюда

Попробуем опубликовать его еще раз с помощью команды npm publish.

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

Если вы проверите наш package.json файл, вы увидите, что в нем указана версия 1.0.0. Вам нужно увеличивать ее каждый раз при публикации нового изменения. Итак, к чему вы должны увеличивать? Для этого вам необходимо понять концепцию семантического управления версиями.

Шаг 7 - Семантическое управление версиями в npm

Значение версии представляет собой комбинацию из 3 цифр, разделенных оператором dot. Допустим, версия a.b.c

  1. Первое значение (a в a.b.c) указывает основную версию пакета - это означает, что эта версия имеет основные изменения кода и может содержать критические изменения API.
  2. Второе значение (b в a.b.c) указывает дополнительную версию, которая содержит незначительные изменения, но не будет содержать критических изменений API.
  3. Третье значение (c в a.b.c) указывает версию патча, которая обычно содержит исправления ошибок.

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

Поэтому измените версию внутри package.json файла с 1.0.0 на 1.0.1 и снова запустите команду npm publish.

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

Подробнее о semantic versioning читайте в моей предыдущей статье

Заключение

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

Полный исходный код этого руководства можно найти в репозитории github-repos-search на GitHub. Вы также можете увидеть опубликованный модуль npm здесь

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