Lessons learned from creating my first Javascript package
Published in · 6 min read · Dec 20, 2022
As developers, we are always trying to figure out how to make our solutions extensible and reusable. We hate rewriting the same code over and over again. Walking the line between maximum production and automation takes a lot of work. At times, it becomes clear that a solution can be abstracted outside of the current project and pulled directly in from a third party. I want to share a recent solution that made perfect sense to create an NPM package and use that solution directly in our application. To this point, I had never created an NPM package, so I hope it will be helpful to share my experience in this post.
Why Build an NPM Package?
We could write solutions directly in the apps we build, which will suffice. But great solutions reduce duplication and follow the code patterns necessary to achieve DRY code.
As “The Pragmatic Programmer” states:
Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
Sometimes we can create a definitive solution outside our application and pull the module inside our app to achieve an end. This is an excellent exercise for the developer and gives back to the programming community, as your solution will likely solve someone else’s problem. Writing a solution that can be used anywhere forces the developer to problem-solve unambiguously; that alone is a selling point for me. I’m not arguing that every solution should be turned into a package, but we should be equipped with the tools and know-how when needed.
I won’t cover all the nitty-gritty in this tutorial, but I thought it would be helpful to give a high-level overview of the necessary steps to creating and using your first NPM package.
These are the steps I followed to create my first NPM Package.
This step is necessary for publishing your package when it’s ready. I could walk you through this portion, but NPM already has excellent documentation for flow:
Once that is complete, we can move on to the fun part.
The application I work on has a two-factor login flow. The last step in the login flow was providing the user with input for the One-Time Password. The first iteration used a number input stylized to look as good as possible. Still, our designer wanted an input that presented each number with its input broken into six separate inputs. Here are some images to make it more straightforward:
Original Input
Input Created by my NPM package
It was challenging to build this input from scratch, but as I started the process, I quickly realized this solution made sense as a reusable module that should exist as an NPM package. This input requires quite a bit of Javascript to handle the edge cases and ensure the user is presented with a smooth experience as they make their input. Here is how I created Honeycrisp, my first NPM Package.
Note: You can demo the package I created here -> Codepen
The easiest way to create a package.json
file is to run the npm init
command from your project root:
> mkdir path-to-project/honeycrisp
> cd path-to-project/honeycrisp
> npm init
npm init
will guide you through options that will define your package.json file. Here is mine after running npm init:
{
"name": "honeycrisp",
"version": "1.0.0",
"description": "A crispy input",
"main": "app.js",
"scripts": {
"test": "test"
},
"author": "",
"license": "ISC"
}
The point of interest here is the main
field. As the NPM docs describe it:
The “main” field is a module ID that is the primary entry point to your program. That is, if your package is named
foo
, and a user installs it, and then doesrequire("foo")
, then your main module's exports object will be returned.
The package.json
file above is the most simplistic version of a package.json file needed. There are quite a few more fields that can be leveraged to define your project. It’s very helpful to consult the official docs here —
Package.json Docs:
I used the name app.js
for my main file. For the simplicity of this tutorial, I kept all of my code in one file. It’s not essential to understand everything about this code. I just wanted to share this for demonstration purposes.
This is all the code necessary to create the input demonstrated above. This project is still actively being updated, as there are plenty of upgrades to be made. Feel free to consult the package on GitHub for the latest version: HONEYCRISP ON GITHUB
After writing that file, I updated my version in the package.json file and tested my solution.
NPM Pack
is an excellent tool for testing your package without publishing it. NPM uses semantic versioning, and instead of publishing a new version to NPM every time you want to test a change, you can create a TAR file, save it locally, and test that against the application you are applying it to.
How to use npm pack
—
First, update your package.json file to a new version. The version is arbitrary, but you should be logical about the flow. Mine looks like this now:
{
"name": "honeycrisp",
"version": "1.0.1", // <- update version
"description": "A crispy input",
"main": "app.js",
"scripts": {
"test": "test"
},
"author": "",
"license": "ISC"
}
Second, from the root of your project, run the NPM Pack command:
> npm packnpm notice
npm notice 📦 [email protected]
npm notice === Tarball Contents ===
npm notice 173B package.json
npm notice === Tarball Details ===
npm notice name: honeycrisp
npm notice version: 1.0.1
npm notice filename: test-1.0.1.tgz
npm notice package size: 204 B
npm notice unpacked size: 173 B
npm notice shasum: 2c069041cc1d121d0a0a0286b60fe86e80b5a
npm notice integrity: sha512-X6RzbgcmgYeb/[...]gQoUMy2H3QyiA==
npm notice total files: 1
npm notice
test-1.0.0.tgz
Third, copy the file to the root of your machine:
cp honeycrisp-1.0.1.tgz
Lastly, from the root of the application you are using it, install the local version of the package:
> cd path/to/application
> npm install ~/honeycrisp-1.0.1.tgz
Now you can test out your changes within the intended application. If something is not working correctly, make the changes to your package, bump the version and run npm pack
again.
Here is some additional documentation for NPM Pack:
After you are satisfied with the implementation of your package. Proceed to the most gratifying step in the process, publishing!
From the root of your project run:
> npm publish
That command will create a TAR file, and NPM will automatically push it to a public registry. Your package can now be used by you and anyone else with access to NPM!
Hopefully, this served as a useful walkthrough for building your first NPM package. NPM has done a great job of taking the hard work off your plate and allowing you to focus on the technical details of your project.
Additional considerations after you complete the first version of your package:
- Make an excellent readme within your readme. Explain how to use the package and why a developer should use your package.
- Our solutions will need to change over time. Define contributing guidelines so the community can help you improve your implementation.
- Promote it!
Check out my first package Honeycrisp
Here is a link to my NPM Package: Honeycrisp
I plan to make plenty of updates as time goes on. As it stands right now, it’s very straightforward, so using it as an example for starting your project may work well. Of course, I would love feedback or contributions too.