npm allows developers to publish custom packages to the npm registry for others to use. Additionally, enterprises can use private registries to manage internal packages.
Publishing npm Packages
1. Preparation
Register npm account:
bashnpm adduser # or npm login
Verify login:
bashnpm whoami
2. package.json Configuration
Ensure package.json includes necessary fields:
json{ "name": "my-awesome-package", "version": "1.0.0", "description": "An awesome npm package", "main": "index.js", "keywords": ["awesome", "package"], "author": "Your Name <email@example.com>", "license": "MIT", "repository": { "type": "git", "url": "https://github.com/username/my-awesome-package.git" }, "homepage": "https://github.com/username/my-awesome-package#readme", "bugs": { "url": "https://github.com/username/my-awesome-package/issues" }, "files": [ "dist", "README.md", "LICENSE" ], "scripts": { "prepublishOnly": "npm run build && npm run test", "build": "tsc", "test": "jest" } }
Important fields:
name: Package name, must be unique (in public registry)version: Follows semantic versioningprivate: Must be set tofalseor removed to publishfiles: Specifies files to include in the published package
3. Publishing Process
Build and test:
bashnpm run build npm test
Pre-publish check:
bashnpm pack
This generates a .tgz file to check what will be published.
Publish to public registry:
bashnpm publish
Publish with specific tag:
bashnpm publish --tag beta
Publish to private scope:
bashnpm publish --access public
4. Version Management
Update version:
bash# Patch version (1.0.0 -> 1.0.1) npm version patch # Minor version (1.0.0 -> 1.1.0) npm version minor # Major version (1.0.0 -> 2.0.0) npm version major # Prerelease version npm version prerelease --preid beta
Publish new version:
bashgit push --follow-tags npm publish
Private Registry
1. Configure Private Registry
Set global registry:
bashnpm config set registry https://registry.yourcompany.com
Set project-level registry:
Create .npmrc in project root:
shellregistry=https://registry.yourcompany.com
2. Use Scoped Packages
Create scoped package:
json{ "name": "@yourcompany/package-name" }
Configure scope registry:
bashnpm config set @yourcompany:registry https://registry.yourcompany.com
Configure in .npmrc:
shell@yourcompany:registry=https://registry.yourcompany.com
3. Authentication Configuration
Use token authentication:
bashnpm config set //registry.yourcompany.com/:_authToken YOUR_TOKEN
Configure in .npmrc:
shell//registry.yourcompany.com/:_authToken=${NPM_TOKEN}
Use environment variable:
bashexport NPM_TOKEN=your_token_here
4. Publish to Private Registry
Publish scoped package:
bashnpm publish
Publish as public package (in private registry):
bashnpm publish --access public
Common Publishing Commands
bash# Check if package name is available npm view <package-name> # View package information npm info <package-name> # View all versions of package npm view <package-name> versions # View package dependencies npm view <package-name> dependencies # Unpublish (use with caution) npm unpublish <package-name>@<version> # Deprecate package version npm deprecate <package-name>@<version> "This version is deprecated" # Search for packages npm search <keyword> # View current registry npm config get registry # View npm configuration npm config list
.npmignore File
The .npmignore file specifies files to ignore when publishing:
shell# Source code src/ test/ *.ts *.spec.js # Development configuration .eslintrc .prettierrc jest.config.js tsconfig.json # Documentation docs/ *.md !README.md # CI/CD .github/ .gitlab-ci.yml # IDE .vscode/ .idea/
Note: .npmignore overrides the files field.
Best Practices
1. Version Management
- Follow semantic versioning conventions
- Run full tests before publishing
- Use
prepublishOnlyscript to ensure quality - Maintain CHANGELOG.md to record changes
2. Package Structure
shellmy-package/ ├── package.json ├── README.md ├── LICENSE ├── .npmignore ├── src/ │ └── index.ts ├── dist/ │ ├── index.js │ └── index.d.ts └── test/ └── index.test.js
3. Documentation
- Provide clear README.md
- Include installation and usage examples
- Explain API and configuration options
- Provide contribution guidelines
4. Security
- Don't include sensitive information in packages
- Use
npm auditto check for security vulnerabilities - Regularly update dependencies
- Use
.npmignoreto exclude sensitive files
5. Continuous Integration
yaml# .github/workflows/publish.yml name: Publish Package on: push: tags: - 'v*' jobs: publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: '18' registry-url: 'https://registry.npmjs.org' - run: npm ci - run: npm test - run: npm publish env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Common Issues
1. Package Name Conflicts
If package name is already taken, consider:
- Using scoped package:
@username/package-name - Choosing a different name
- Contacting the package owner
2. Publishing Failures
Common reasons:
- Package name already taken
- Missing required fields
- Version number not updated
- Authentication failure
3. Unpublish Restrictions
npm restricts unpublishing:
- Can only unpublish versions within 72 hours
- Cannot unpublish major versions older than 24 hours
- Use
deprecateinstead ofunpublish
Enterprise Solutions
1. Verdaccio
Lightweight private npm registry:
bashnpm install -g verdaccio verdaccio
2. Artifactory
Enterprise-grade artifact repository supporting multiple package managers.
3. Nexus Repository
Another popular enterprise-grade artifact repository solution.
4. GitHub Packages
Use GitHub as a private registry:
bashnpm config set registry https://npm.pkg.github.com npm login --scope=@your-username --registry=https://npm.pkg.github.com
Mastering npm publishing and private registry configuration is crucial for team collaboration and enterprise-level project management.