Публикация npm пакета в Sonatype Nexus
Настройка сборки в Vite
Пример vite.config.ts с плагином vite-plugin-dts для экспорта типов TS:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import dts from 'vite-plugin-dts';
export default defineConfig({
plugins: [
react(),
dts({
rollupTypes: true,
tsconfigPath: './tsconfig.app.json',
}),
],
build: {
lib: {
entry: 'src/components/index.ts',
name: 'SunComponentLibrary',
fileName: (format, name) => `${name}.${format}.js`,
},
rollupOptions: {
external: ['react', 'react-dom', '@mui/material', '@emotion/react', '@emotion/styled'],
output: {
globals: {
react: 'React',
'react-dom': 'ReactDOM',
'@mui/material': 'MaterialUI',
'@emotion/react': 'EmotionReact',
'@emotion/styled': 'EmotionStyled',
},
},
},
},
});
Бандл по умолчанию кладется в папку dist/.
Имя файла определяется в коллбэке build.lib.fileName и содержит имя модуля и его формат:
es— модуль ES Modules;umd— модуль CommonJS.
Описание проекта в package.json
{
"name": "sun-component-library",
"version": "0.1.0",
"description": "SUN component library",
"type": "module",
"main": "dist/index.umd.js",
"module": "dist/index.es.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.es.js",
"require": "./dist/index.umd.js"
}
},
"files": [
"dist"
],
"publishConfig": {
"registry": "http://localhost:8081/repository/my-test-repo-hosted/"
},
"scripts": {
"build": "tsc -b && vite build",
"lint": "eslint .",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
},
"devDependencies": {
"@chromatic-com/storybook": "^3.2.6",
"@eslint/js": "^9.18.0",
"@storybook/addon-essentials": "^8.6.11",
"@storybook/addon-interactions": "^8.6.11",
"@storybook/addon-onboarding": "^8.6.11",
"@storybook/blocks": "^8.6.11",
"@storybook/react": "^8.6.11",
"@storybook/react-vite": "^8.6.11",
"@storybook/test": "^8.6.11",
"@types/react": "^18.3.18",
"@types/react-dom": "^18.3.5",
"@vitejs/plugin-react": "^4.3.4",
"eslint": "^9.18.0",
"eslint-plugin-react": "^7.37.4",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.16",
"eslint-plugin-storybook": "^0.12.0",
"globals": "^15.14.0",
"prettier": "3.4.2",
"storybook": "^8.6.11",
"typescript": "~5.6.2",
"typescript-eslint": "^8.20.0",
"vite": "^6.0.5",
"vite-plugin-dts": "^4.5.0"
},
"peerDependencies": {
"@emotion/react": "^11.0.0",
"@emotion/styled": "^11.0.0",
"@fontsource/roboto": "^5.1.1",
"@mui/icons-material": "^6.4.0",
"@mui/material": "^6.0.0",
"react": ">=18.0.0",
"react-dom": ">=18.0.0"
},
"eslintConfig": {
"extends": [
"plugin:storybook/recommended"
]
}
}
Здесь в поле exports во вложенном поле .:
types— путь к бандлу с типами;import— путь к ES Modules бандлу;require— путь к CommonJS бандлу.
В поле publishConfig.registry прописывается адрес npm hosted-репозитория в Nexus.
Настройка Sonatype Nexus
1. Установить и запустить Nexus
Развернуть Sonatype Nexus в Docker-контейнере по этой инструкции: [[Sonatype Nexus installation using Docker]]
2. Включить Realm для npm

3. Создать роль для чтения и записи пакетов в репозиторий
Открыть форму создания роли, нажав на странице настроек Security -> Roles кнопку "Create Role", и заполнить поля:

Ниже в разделе Applied Privileges для добавления привилегий нажать кнопку "Modify Applied Privileges" и отфильтровать открывшийся список по значению "npm", после этого выбрать привилегии:
nx-repository-view-npm-*-browsenx-repository-view-npm-*-editnx-repository-view-npm-*-readи сохранить кнопкой "Confirm":

Раздел Applied Roles оставить пустым:

Создать роль, нажав кнопку "Save".
4. Создать пользователя для публикации пакета
Открыть форму создания роли, нажав на странице настроек Security -> Users кнопку "Create local user", и заполнить поля, переместив в конце формы только что созданную роль в правый столбец Granted:

5. Создать репозиторий
Неообходимо создать 3 части репозитория (proxy, hosted и group), принцип действия которых отражен на схеме:

Для создания каждого из них нужно перейти в меню настроек Repository -> Repositories и открыть форму создания кнопкой "Create repository".
Для proxy-репозитория в открывшемся списке Recipe выбрать npm (proxy) и заполнить поля:
- Name - предпочитаемое имя репозитория (желательно добавить в конце "proxy");
- Remote storage - адрес удаленного репозитория с пакетами (ввести адрес общедоступного
https://registry.npmjs.org). Остальные поля оставить по умолчанию, затем создать репозиторий кнопкой "Create repository":

Для hosted-репозитория в открывшемся списке Recipe выбрать npm (hosted) и заполнить поля:
- Name - предпочитаемое имя репозитория (желательно добавить в конце "hosted");
- Deployment policy - политика повторного деплоя одной и той же версии. Остальные поля оставить по умолчанию, затем создать репозиторий кнопкой "Create repository":

Для group-репозитория в открывшемся списке Recipe выбрать npm (group) и заполнить поля:
- Name - предпочитаемое имя репозитория (желательно добавить в конце "group");
- Member repositories - список сгруппированных репозиториев, перетащить в правый столбец Members только что созданные proxy и hosted репозитории. Остальные поля оставить по умолчанию, затем создать репозиторий кнопкой "Create repository":

6. Авторизация в репозитории
Для авторизации выполнить команду вида:
npm login --registry=[адрес-репозитория]/repository/[имя-hosted-репозитория]/
Внимание!!! Важно наличие слэша / в конце команды после имени репозитория. Например, для локально развернутого Nexus:
npm login --registry=http://localhost:8081/repository/sun-component-library-hosted/
Файл с сохраненными учетными данными доступа к репозиториям в ОС Windows находится по адресу:
C:\Users\username\.npmrc
После авторизации в репозитории в файле появляется строка, которая должна иметь вид:
//[адрес-репозитория]/repository/[имя-hosted-репозитория]/:_authToken=NpmToken.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

В случае проблем с авторизацией или несоответствия формата строки авторизации в файле .npmrc — удалить строку из файла, сохранить его и попытаться авторизоваться заново.
7. Публикация пакета в репозиторий
Для публикации пакета сначала выполнить сборку бандла, что как правило выполняется запуском скрипта:
npm run build
После сборки выполнить из директории проекта команду:
npm publish
При выполнении такой команды без дополнительных параметров пакет будет опубликован в hosted-репозиторий, указанный в поле publishConfig.registry файла package.json (см. пример в пункте [[#2. Описание проекта в package.json]]).
Адрес hosted-репозитория для публикации можно указать явно, добавив параметр --registry:
npm publish --registry=http://localhost:8081/repository/my-test-repo-hosted/
8. Установка опубликованного пакета в сторонний проект из group-репозитория Nexus
Для установки необходимо при явно указать адрес group-репозитория с помощью параметра --registry (не забыть слэш / в конце после имени group-репозитория):
npm install sun-component-library@0.1.0 --registry http://localhost:8081/repository/my-test-repo-group/