How to setup an NPM package
Ever wondered how an NPM package gets initialized? This article walks you through the process.
Every time you'd like to start building a Node app from scratch, it's highly recommended for you to setup an NPM package so that your app can be easily managed and maintained either by you or other developers.
๐ก This article assumes that both Node and NPM are already installed on your operating system. If not, you might want to head up to this other article before you continue on this one.
Table of contents:
- ๐ Create a directory for the app to live in
- ๐ฆ Initialize the NPM package
- ๐ฌ Anatomy of the
package.json
file - ๐ค Taking a shortcut
- ๐งฉ Dependency version specification
๐ Create a directory for the app to live in
The package will hold everything for your app. This includes: source code, configurations, assets and even documentation. Everything co-exists in a directory together, and it can be manually created. You may use your favorite directory creation method. The only recommendation for you is not to use spaces on the directory's name. Why? well, this will make it easier to navigate and prevent errors in some scenarios. Once the directory is created, go inside of it:
mkdir react-from-scratch && cd react-from-scratch
๐ฆ Initialize the NPM package
An NPM package depends a lot on a very important file called package.json
. It stores information about the package using the JSON syntax and though it supports several standard keys/properties, only 2 of them are required: "name"
and "version"
.
One can create and fill this file manually but fortunately, NPM comes with a built-in initializer for this file that helps a lot. To bring it up, one has to use following CLI command:
npm init
When this command is invoked, a questionnaire gets prompted for you to help the initializer fill the document. The questions are shown on your CLI one by one and they look like this:
package name: (react-from-scratch)
version: 0.0.1
description: Very cool react app built from scratch
entry point: src/app.tsx
test command:
git repository: <url-to-git-repo>
keywords: react typescript sass
author: Carlos Jasso
license: MIT
and the resulting file contains this:
{
"name": "react-from-scratch",
"version": "1.0.0",
"description": "Very cool react app built from scratch",
"main": "src/app.tsx",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"react",
"typescript",
"sass"
],
"author": "Carlos Jasso",
"license": "MIT"
}
๐ฌ Anatomy of the package.json
file
Have you noticed that some values are given within parenthesis? Those are the default values that the initializer will write to the package.json
if you just hit the ENTER
key when the question prompts for the answer. You can change those values to anything of your preference.
Each of the fields represents the following:
"name"
: contains your package's name. It must be written in lowercases, not include spaces but it may contain hyphens or underscores. Its default value is the directory's name."version"
: this value must be in the<MajorRelease>.<MinorRelease>.<PatchRelease>
form orx.x.x
. Its default value is1.0.0
."description"
: self explanatory, right? its value can even be an empty string""
(default)."main"
: it references the file that the assembly starts with. Commonly, one can find this field with the values"index.js"
,"app.js"
,"my-app-name.js"
. If you're not sure what to fill this with, you may as well leave it blank and will cause no harm."scripts"
: its value is a nested json object with key/value entries for each of the "actions" needed to execute the package (or app) in one or other way. It by default has a"test"
script that simply printsError: no test specified
to your CLI when executed."keywords"
: an array of words that can be used to describe the package. It's common to find the names of the technologies involved in the project and by default, it's an empty value."author"
: so that it's easy to find out whom a package was created by, it's convenient to add the author's information. It's suggested to follow the format<Name> <email@example.com> <http://example.com)>
but just adding your name should be enough. An empty value is included by default."license"
: a license should be specified to let people know how they are allowed to use your package and what constraints you've set for it. The value must be a SPDX license identifier which default value is"ISC"
.
๐ค Taking a shortcut
At this far, you may be wondering if there's a quicker way to create the package.json
file. Fortunately, there's a way to indicate the NPM initializer to answer all the questions of the questionnaire with their default values. This is done by passing the -y
argument to the command like this:
npm init -y
but this may not be as fun as entering your own data.
๐งฉ Dependency version specification
Most of the times, NODE apps are not only composed by the source code written by a developer but they also feature several packages written by others. In order to keep every dependency neat and tidy, whether they get used on the final product or only during build-time, the package.json
file features a section where those dependencies are specified:
{
...,
"dependencies": {
"react": "^17.0.1",
"react-dom": "~17.0.0"
},
"devDependencies": {
"ts-loader": "8.0.0",
"typescript": ">=4.1.0",
"webpack": "<=5.0.0",
"webpack-cli": "~4.5.0"
}
}
Commonly, the name and version of each dependency is included in the package.json
file and NPM will know what package to look for. Also, the path to a tarball or git URL can be specified.
The version value of a dependency is written in a rather specific notation that is pretty easy to understand:
version
: (no special characters) must matchversion
exactly.>version
: must be greater thanversion
.>=version
: must be greater than or equal toversion
.<version
: must be lower thanversion
.<=version
: must be lower than or equal toversion
.~version
: approximately equivalent toversion
. Allow patch-level or minor-level changes.^version
: allow upgrades compatible withversion
.1.2.x
: could be1.2.0
,1.2.1
, etc., but not1.3.0
.*
: matches any version""
: (empty string) same as*
version1 - version2
: same as>=version1 <=version2
.range1 || range2
: passes if eitherrange1
orrange2
are satisfied.
At first, you may find that the package.json
file doesn't contain neither a "dependencies"
nor a "devDependencies"
section, and that's because those sections aren't included when the file gets first initialized, however, it's important to know what these two sections are used for.
I hope you've found this article to be useful. Now you know how to properly initialize an NPM package and understand the contents of a package.json
file a bit better.
If you'd like to go deeper into the topic, you may want to give this awesome document a read.
fun fact: this is my very first published article ever.
Cover Credits: Mockup psd created by freepik - www.freepik.com | Boboss74, CC BY-SA 4.0, via Wikimedia Commons