Как создать и опубликовать npm-пакет
Вы установили сотни пакетов с помощью npm install. Теперь вы хотите опубликовать свой собственный. Процесс кажется простым, пока вы не обнаружите устаревшие руководства, рекомендующие Node 12, настройки только для CommonJS и долгоживущие токены, хранящиеся в секретах CI.
Это руководство проведет вас через создание и публикацию npm-пакета с использованием современных безопасных практик, которые будут актуальны и в 2025 году. Мы создадим простую утилиту, правильно настроим её и опубликуем с помощью npm Trusted Publishing.
Ключевые выводы
- Используйте ESM с правильным полем
exportsвместо устаревшего поляmainдля современного разрешения пакетов - Компилируйте TypeScript в JavaScript с файлами деклараций вместо поставки исходного TypeScript
- Включите двухфакторную аутентификацию и используйте npm Trusted Publishing через GitHub Actions OIDC для безопасных автоматизированных релизов
- Всегда проверяйте содержимое пакета с помощью
npm pack --dry-runперед публикацией
Предварительные требования
Перед началом убедитесь, что у вас есть:
- Установленный Node.js версии 18 или выше
- Аккаунт на GitHub
- Базовое знакомство с npm как пользователя
Инициализация настройки npm-пакета с приоритетом ESM
Создайте новую директорию и инициализируйте проект:
mkdir use-toggle && cd use-toggle
npm init -y
git init
Мы создадим простой React-хук под названием useToggle. Этот пример демонстрирует публикацию TypeScript npm-пакета с правильными точками входа.
Настройка package.json для современной публикации
Замените ваш package.json на правильно настроенную версию:
{
"name": "@yourusername/use-toggle",
"version": "0.1.0",
"description": "A simple React hook for boolean toggle state",
"keywords": ["react", "hook", "toggle", "state"],
"license": "MIT",
"author": "Your Name",
"repository": {
"type": "git",
"url": "git+https://github.com/yourusername/use-toggle.git"
},
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"files": ["dist"],
"engines": {
"node": ">=18"
},
"peerDependencies": {
"react": ">=18"
},
"devDependencies": {
"typescript": "^5.4.0",
"react": "^18.0.0",
"@types/react": "^18.0.0"
},
"scripts": {
"build": "tsc",
"prepublishOnly": "npm run build"
}
}
Ключевые моменты для настройки npm-пакета с приоритетом ESM:
type: "module"объявляет ESM по умолчаниюexportsзаменяет устаревшее полеmain— именно так современный Node разрешает точки входаfilesконтролирует, что будет опубликовано (толькоdist/)enginesуказывает Node 18+, избегая проблем совместимости с устаревшими версиями
Настройка компиляции TypeScript
Создайте tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"declaration": true,
"outDir": "dist",
"rootDir": "src",
"strict": true,
"skipLibCheck": true
},
"include": ["src"]
}
Создайте src/index.ts:
import { useState, useCallback } from 'react';
export function useToggle(initial = false): [boolean, () => void] {
const [value, setValue] = useState(initial);
const toggle = useCallback(() => setValue(v => !v), []);
return [value, toggle];
}
Запустите npm run build для компиляции. Вы получите dist/index.js и dist/index.d.ts — JavaScript плюс декларации типов, а не исходный TypeScript.
Безопасная публикация npm-пакета в 2025 году
Создайте аккаунт npm с двухфакторной аутентификацией
- Зарегистрируйтесь на npmjs.com
- Немедленно включите двухфакторную аутентификацию (предпочтительно WebAuthn/passkeys)
- Для всех новых пакетов теперь по умолчанию включено требование 2FA
- С новой моделью входа на основе сессий публикация любого пакета — нового или существующего — требует 2FA во время сессии
Ваша первая ручная публикация
npm login теперь создает токен сессии на два часа. Эти токены:
- Не отображаются в интерфейсе npm
- Автоматически истекают через два часа
- Не могут быть повторно использованы в CI/CD
- Всегда требуют 2FA перед публикацией
Старые инструменты, которые аутентифицируются через устаревшую конечную точку CouchDB, также получают токены сессии на два часа в переходный период.
Для вашего первого релиза:
npm login
npm publish --access public
Флаг --access public обязателен для пакетов с областью видимости (scoped packages) на бесплатных аккаунтах.
Проверьте ваш пакет по адресу https://www.npmjs.com/package/@yourusername/use-toggle.
Discover how at OpenReplay.com.
npm Trusted Publishing с CI
Старые руководства советуют создать NPM_TOKEN и сохранить его как секрет репозитория. Этот подход теперь устарел: классические токены были окончательно отозваны, а долгоживущие токены для CI больше не поддерживаются.
Современная альтернатива — npm Trusted Publishing через GitHub Actions OIDC. GitHub подтверждает свою идентичность npm, и npm автоматически выдает краткосрочные учетные данные — без необходимости хранить токен.
Настройка Trusted Publishing
- На npmjs.com перейдите к вашему пакету → Settings → Publishing access
- Добавьте нового “Trusted Publisher” с данными вашего GitHub-репозитория
Создание workflow
Добавьте .github/workflows/publish.yml:
name: Publish
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
registry-url: 'https://registry.npmjs.org'
- run: npm ci
- run: npm publish --provenance --access public
Флаг --provenance добавляет криптографическое подтверждение, связывающее ваш пакет с его исходным репозиторием — это функция безопасности цепочки поставок, которую npm представил в 2023 году.
Если OIDC не может быть использован (например, для самостоятельно размещенных раннеров), создайте краткосрочный гранулярный токен доступа с помощью:
npm token create
Гранулярные токены могут включить опцию Bypass 2FA для публикации в CI и должны истекать в течение 90 дней.
Что вы увидите в старых руководствах
Избегайте этих устаревших паттернов:
"main": "index.js"безexports— используйтеexportsдля правильного разрешения ESM- Таргетинг на Node 10/12/14 — Node 18+ поддерживается, но новые пакеты должны ориентироваться на современные LTS-версии (Node 20 или 22)
- Пакеты только для CommonJS — ESM является стандартом; поставляйте пакеты с приоритетом ESM
- Постоянный
NPM_TOKENв каждом workflow — классические токены полностью отозваны; используйте Trusted Publishing без токенов
Проверка перед публикацией
Всегда тестируйте пакет локально перед публикацией:
npm pack --dry-run
Это покажет точно, какие файлы будут включены. Если вы видите src/ или node_modules/, ваше поле files требует корректировки.
Заключение
Чтобы создать и опубликовать npm-пакет в 2025 году: используйте ESM с правильным exports, компилируйте TypeScript в JavaScript с декларациями, включите 2FA и автоматизируйте релизы с помощью npm Trusted Publishing. Откажитесь от устаревших паттернов — они создадут проблемы для вас и ваших пользователей.
Часто задаваемые вопросы
Публикуйте скомпилированный JavaScript с файлами деклараций. Поставляйте папку dist, содержащую скомпилированный JS и сгенерированные .d.ts файлы. Это обеспечивает совместимость с различными версиями TypeScript и инструментами сборки. Исходный TypeScript заставляет потребителей компилировать ваш код, что может вызвать конфликты версий и замедлить сборку.
Используйте dependencies для пакетов, которые ваш код объединяет и поставляет. Используйте peerDependencies для пакетов, которые должны предоставить потребители, например React для React-хука. Это предотвращает дублирование копий больших библиотек в финальном бандле. Ваш пакет ожидает версию потребителя, а не включает свою собственную.
Пакеты с областью видимости, такие как @username/package-name, по умолчанию являются приватными на npm. Бесплатные аккаунты npm не могут публиковать приватные пакеты, поэтому вы должны явно указать --access public. Этот флаг сообщает npm опубликовать пакет публично. Он нужен только для первой публикации; последующие версии наследуют уровень доступа.
Используйте npm deprecate @scope/package, чтобы предупредить пользователей без удаления пакета. Полная отмена публикации с помощью npm unpublish ограничена пакетами, опубликованными в течение 72 часов, или теми, у которых минимальное количество загрузок. Для заброшенных пакетов предпочтительнее deprecation, так как это предупреждает пользователей, сохраняя существующие установки.
Understand every bug
Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.