DEV Community

QLabs
QLabs

Posted on • Originally published at Medium on

How to publish NPM packages

NPM logo

Let’s say you’ve developed a project in JS and want to share it with the world, whether it's a simple project which draws a circle (okay, this might not be the package you want to publish) or a complex one which you want to be used by thousands of developers like Jquery, you can publish them on NPM.

We’ll have 3 parts to this:

  • Publishing to NPM the normal way
  • Using GitHub Actions to automate publishing
  • And using GitHub Actions to test your projects

So, you have your project. You want it to be in a package-ready format to publish when you’re ready. All NPM Packages are in the same format:

So, the index.js file is where we have our base code. You should know what a README.md is and to make your project attractive on NPM, I suggest you put one. The LICENSE file is important, and you should definitely choose one. You can pick one at choosealicense.com.

Now that you have those files, (and make sure you don’t continue without them) we can move on to the package.json and package-lock.json files. These tell NPM about the package, so these are required. Make sure you have NPM and Node.js installed, and if you don’t, you can learn how to install NPM here.

So, we have NPM, Node.js, and the LICENSE, README.md, and index.js files. To create the package.json file, simply open up your terminal or command prompt, and run this command:

npm init
Enter fullscreen mode Exit fullscreen mode

This will walk you through the commands for setting up your project and feel free to skip questions if you don’t know them, but it shouldn’t be that hard. You can also leave questions empty if you don’t want to include them. This should also create the package-lock.json file. If you’ve ever created a python package, the package.json file is basically the same as a setup.py file.

Although the npm init command walks you through some of the essential parts of the package.json file, there are several more things you can add, and you can view the full list here.

Make sure you register and have an account at https://npmjs.org to publish npm packages, and then run

npm login
Enter fullscreen mode Exit fullscreen mode

in your terminal or command prompt. Login with the credentials from your account which you registered on NPM.

Okay, we’ve created all of our files and logged in, now what. We publish the package! Take one last look over your package, make sure everything is how you want it to be, make sure there are as little bugs as possible (you could change the version to vX.X.X alpha or vX.X.X beta instead in case there’s a bug you don’t notice), and then run the final command:

npm publish
Enter fullscreen mode Exit fullscreen mode

Hooray 🎉🎉🎉! We did it! Or did we? Well… kind of. If you didn’t get an error, you’re good, but you might encounter an error which stops it from publishing. It might be because someone else is already using that name from your package. If the error it outputs is something like :

You do not have permission to publish [package-name]. Are you logged in as the correct user?
Enter fullscreen mode Exit fullscreen mode

then that’s your problem. If that’s true, there are 2 options. The first way is obvious, think of a different name. But if you really like your name and want to keep it, you can scope it. This is something many people do, and although people will see it scoped on NPM, it doesn’t look so bad. You simply change your package name from name to @npmusername/package-name . Replace the @npmusername with your username on NPM and package-name with the original name of your package. For example, if your name on NPM was QLabs and the package name was minor, you can change it to @QLabs/minor . Let's say you don’t want to scope it, then you can add JS to the end of it so minor becomes minorjs or minorJS . But since many people use that, it might still come out with that error.

Now, if you still get an error that is telling you to upgrade your NPM account which costs money. Then you don’t have an error in your package.json. Instead of running npm publish run:

npm publish --access public
Enter fullscreen mode Exit fullscreen mode

If it’s not that, you might have made a mistake in the package.json file or didn’t include one. Otherwise, you should put it on https://stackoverflow.com to get your question answered.

So, we’ve fixed all of our errors and published the package, now we test to see that we did the steps correctly. We use the npm install command.

npm install [package-name]
Enter fullscreen mode Exit fullscreen mode

Make sure that when you install, you include the scope if you scoped it when trying to fix the error.

So, we did it! We successfully created an NPM Package! But don’t go yet. There’s more.

Using GitHub Actions to Automatically Publish Releases on NPM

Photo by Luke Chesser on Unsplash

Since almost everyone uses GitHub, I really suggest you use GitHub and put your source code into GitHub.

Now, the majority of packages use GitHub, and GitHub offers some cool advantages with GitHub Actions. If you’ve never used one before, don’t worry. It’ll be easy as pie.

Go to your repo for the package on GitHub, then go to settings>secrets and add a new secret. Name it “NPM_TOKEN”, and then go to NPM, login, and then go to “https://www.npmjs.com/settings/$username/tokens”, and create a new access token for the value of our GitHub secret.

NPM Page when creating a new access token.

Make sure the access level is set to “Read and Publish” and then hit the “Create Token” button. Copy the token and paste it into the GitHub Secret as the value.

Now, on GitHub, go to the Actions tab.

Screenshot of the GitHub Actions tab on a repository

On the GitHub Actions Tab, the first section should be titled “Workflows made for your JavaScript repository.” Click “Set up this workflow” on the “Publish Node.js Package” workflow. The editor should pop up with pre-built code. Replace it with:

name: Publish

on:
  release:
    types: [published]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - uses: actions/setup-node@v1
        with:
          node-version: 12
          registry-url: https://registry.npmjs.org/
      - run: yarn install
      - run: npm publish --access public
        env:
          NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
Enter fullscreen mode Exit fullscreen mode

Let’s go through the action.

name: Publish
Enter fullscreen mode Exit fullscreen mode

This sets the name of the action, and that’s what you see after the action is created when you go to the actions tab on your repo.

on:  
  release:    
    types: [published]
Enter fullscreen mode Exit fullscreen mode

This means it’ll run every time you publish a release on GitHub, so you don’t have to go to the command prompt and run npm publish every time to publish a new release.

jobs:  
  build:    
    runs-on: ubuntu-latest
Enter fullscreen mode Exit fullscreen mode

This configures the job build and sets it to the latest version of Ubuntu.

steps:
  - uses: actions/checkout@v1
  - uses: actions/setup-node@v1
  with:
    node-version: 12
    registry-url: https://registry.npmjs.org/
  - run: yarn install
  - run: npm publish --access public
    env:
      NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
Enter fullscreen mode Exit fullscreen mode

This is where we put the steps of the job to run. It does this:

  • Gets the repo files
  • Installs Node.js, with Version 12 using the registry URL of NPM.
  • Installs the package dependencies via yarn install
  • Runs the npm publish command, --access public stops the error we had before from happening. It is run with the environment variable NODE_AUTH_TOKEN which is set to the secret we set earlier.

Now, every time a new release is published on GitHub, it’ll automatically publish one on NPM.

Using GitHub Actions for CI on Your NPM Project

Photo by Markus Winkler on Unsplash

We’ve automated publishing with GitHub Actions, what else can we do with GitHub? Well, GitHub offers an easy way to do CI using GitHub Actions.

Go to the .github/workflows directory of your repo, and create a new file. Paste in the template provided by GitHub on their docs:

name: Node.js Package
on:
  release:
    types: [created]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-node@v1
      with:
        node-version: '12.x'
        registry-url: 'https://registry.npmjs.org'
    - run: npm install
    - run: npm publish
      env:
        NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Enter fullscreen mode Exit fullscreen mode

Let’s go through this workflow.

name: Node.js CI
Enter fullscreen mode Exit fullscreen mode

The name, you can change this to what you want to show up on the actions tab.

on: [push]
Enter fullscreen mode Exit fullscreen mode

This runs every time you commit something to the repo.

jobs:  
  build:
    runs-on: ubuntu-latest
Enter fullscreen mode Exit fullscreen mode

This sets the operating system to test it on. You can change it to windows-latest or macos-latest depending on what you want to test on.

strategy:
  matrix:
    node-version: [8.x, 10.x, 12.x]
Enter fullscreen mode Exit fullscreen mode

This determines the node versions to test on, you can add or remove versions to test on.

steps:
    - uses: actions/checkout@v2
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v1
      with:
        node-version: ${{ matrix.node-version }}
    - run: npm install
    - run: npm run build --if-present
    - run: npm test
      env:
        CI: true
Enter fullscreen mode Exit fullscreen mode

The part we should focus on is the last:

- run: npm install
- run: npm run build --if-present
- run: npm test
  env:
    CI: true
Enter fullscreen mode Exit fullscreen mode

This:

  • Installs the package dependencies using npm install
  • Run’s the build steps defined in your package.json via npm run build
  • Run’s npm test which runs your test script, which is also defined in you package.json

I suggest you read the docs for GitHub Actions on Building and testing Node.js.

We did it! 🎉🎉🎉We successfully published an NPM Package! 🎉🎉🎉 But that’s not it! We automated publishing and tested our project with GitHub Actions.

Now, NPM seems like a good package manager, but another JS package manager is out there: Yarn (there’s pnpm too, but I don’t use it much). So which to use? NPM is a necessity since Yarn can’t publish packages, but Yarn is very good with efficiency. My choice is to use both since Yarn installs faster while NPM takes longer (not that much longer though) and NPM can publish packages and other things Yarn can’t do. If you’re deciding, you should really check out this article in the JavaScript in Plain English publication by Harsha Vardhan.

Further Reading, Examples, & Package Managers


Top comments (0)