Npm Publish

4 minute read

Published:

How to publish an npm package

Publishing your own npm (Node Package Manager) package is straightforward. Here’s a concise guide:

Steps

  1. Sign Up / Log In
    Go to the npm official website and sign up or log in.

  2. Initialize Your Project
    In your project directory, run:
    npm init
    

    This will create a package.json file.

  3. Write Your Package Code
    Add your source code and documentation files.

  4. Login via CLI
    Authenticate in your terminal:
    npm login
    
  5. Publish Your Package
    Run:
    npm publish
    

Typical Project Structure

my-npm-package/
├── package.json
├── README.md
├── index.js
└── bin/
└── lib/
    └── ... (your modules)

About the bin Field and CLI Scripts

The bin field in your package.json specifies executable files that should be installed as command-line programs when your package is installed globally (or as a dependency).

When Do You Need a bin File?

  • If your package provides a CLI (Command Line Interface) tool, you need a bin entry.
  • If your package is only a library (used via require/import), you usually do not need a bin field.

Example: Adding a CLI Script

Suppose you want users to run a command like mycli after installing your package.

package.json:

{
  "name": "my-npm-package",
  "version": "1.0.0",
  "bin": {
    "mycli": "./bin/mycli.js"
  }
  // ... other fields
}

bin/mycli.js:

#!/usr/bin/env node

console.log('Hello from my CLI!');

Make sure to add execute permission:
chmod +x bin/mycli.js

How Does the Script Work?

  • When users install your package globally (npm install -g my-npm-package), npm will create a symlink so they can run mycli directly from the command line.
  • The #!/usr/bin/env node line tells the system to use Node.js to run the script.

Why Might a Package Not Have a bin Field?

  • If the package is not intended to be used as a CLI tool, there is no need for a bin entry.
  • Most utility libraries (like lodash, axios, etc.) do not provide CLI commands, so they omit the bin field.

Using commander for CLI Development

commander is a popular library for building command-line interfaces in Node.js. It helps you parse arguments, define commands, and generate help messages easily.

Basic Example

Install commander:

npm install commander

Create a CLI script (bin/mycli.js):

#!/usr/bin/env node
const { program } = require('commander');

program
  .name('mycli')
  .description('An example CLI using commander')
  .version('1.0.0');

program
  .command('greet <name>')
  .description('Greet someone')
  .action((name) => {
    console.log(`Hello, ${name}!`);
  });

program.parse(process.argv);

For local testing, you can use yarn link (or npm link) to create a symlink and debug your package locally before publishing.

After you finish testing, it’s recommended to remove the link to avoid conflicts:

  • In your project directory, run:
    yarn unlink
    # or
    npm unlink
    
  • Optionally, in the global package directory, you can also run:
    yarn unlink <package-name>
    # or
    npm unlink <package-name>
    

This ensures your project uses the published version of the package instead of the local symlink.

Now, after publishing and installing your package globally, you can run:

mycli greet Devin
# Output: Hello, Devin!

For more features and advanced usage, see the commander documentation.

NPM Package Case Studies

1. Optimizing Static Image Size with imgzip

To address the issue of oversized static image assets in the project, I created and published a CLI tool called imgzip as an npm package. This tool compresses image files efficiently while maintaining visual quality, significantly reducing bundle size and improving page load speed.

See more info about devin-img-zip

2. Automating Multilingual Workflows with a Private NPM Package

Our project involves multilingual support. To improve development efficiency, we built a private npm package for automating the translation of locale files. This tool significantly streamlines the i18n process by managing YAML-based translations and supporting batch processing for multiple languages.

Hosted privately, not publicly available on npm registry. See more info at i18n tool

References