What Is package.json?

Learn all about a Node project's package.json, npm’s configuration file housed in the root directory of your project. In this tutorial, learn how to manage metadata in an initial package.json file such as name, version, description, and keywords, as well as dependencies and devDependencies. Learn how to run, develop, and optionally publish your project to NPM.

In this tutorial we'll:

  • Learn how package.json relates to your project
  • Identify important fields and metadata
  • Understand how to manage package.json

Goal

Understand what a package.json file is, how it relates to your project, and what common properties we need to know about.

Prerequisites

Watch: What is package.json?

Get to know package.json

If you've worked with Node.js before, you have likely encountered a package.json file. It is a JSON file that lives in the root directory of your project. Your package.json holds important information about the project. It contains human-readable metadata about the project (like the project name and description) as well as functional metadata like the package version number and a list of dependencies required by the application.

An example package.json might look like this:

 {
        "name": "my-project",
        "version": "1.5.0",
        "description": "Express server project using compression",
        "main": "src/index.js",
        "scripts": {
            "start": "node index.js",
			"dev": "nodemon",
			"lint": "eslint **/*.js"
        },
        "dependencies": {
            "express": "^4.16.4",
			"compression": "~1.7.4"
        },
        "devDependencies": {
			"eslint": "^5.16.0",
            "nodemon": "^1.18.11"
        },
		"repository": {
			"type": "git",
			"url": "https://github.com/osiolabs/example.git"
		},
		"author": "Jon Church",
		"contributors": [{
			"name": "Amber Matz",
			"email": "example@example.com",
			"url": "https://www.osiolabs.com/#team"
		}],
		"keywords": ["server", "osiolabs", "express", "compression"]
    }

What is the purpose of package.json?

Your project's package.json is the central place to configure and describe how to interact with and run your application. It is used by the npm CLI (and yarn) to identify your project and understand how to handle the project's dependencies. It's the package.json file that enables npm to start your project, run scripts, install dependencies, publish to the NPM registry, and many other useful tasks. The npm CLI is also the best way to manage your package.json because it helps generate and update your package.json file throughout a project's life.

Your package.json fills several roles in the lifecycle of your project, some of which only apply for packages published to NPM. If you're not publishing your project to the NPM registry or otherwise making it publicly available to others, your package.json is still essential to the development flow.

Your project also must include a package.json before any packages can be installed from NPM. This is probably the top reason why you need one in your project.

Common fields in package.json

Let's look at some of the most common and important fields that can be in a package.json, to better understand how to use and manage this essential file. Some are required for publishing to NPM, while others help the npm CLI run the application or install dependencies.

There are more fields than the ones we cover, and you can read about the rest in the documentation, but these are the essential package.json properties to understand.

name

"name": "my-project"

The name field defines the name of the package. When publishing to the NPM registry, this is the name the package will be listed under. It must be no more than 214 characters, only lowercase letters, and it must be URL-safe (hyphens and underscores allowed, but no spaces or other characters disallowed in URLs).

If publishing your package to NPM, the name property is required and must be unique. You'll receive an error if trying to publish a package under a name that is currently used on the NPM registry. If you aren't developing a package which you'll eventually publish, the name does not have to be unique.

version

"version": "1.5.0",

The version field is very important for any published package, and required before publishing. It is the current version of the software that the package.json is describing.

You are not required to use SemVer, but it is the standard used in the Node.js ecosystem and highly recommended. For an unpublished package, this property isn't strictly required. Typically, the version number is bumped according to SemVer before publishing new versions to NPM. This workflow isn't typically used when a package is not being relied upon as a dependency, or the package isn't being published to NPM. But if a package is being used as a dependency, keeping the version field up to date is very important to make sure others are using the proper version of a package. Learn more about semantic versioning.

license

This is a very important but often overlooked property. The license field lets us define what license applies to the code the package.json is describing. Again, this is very important when publishing a project to the NPM registry, as the license may limit the use of your software by some developers or organizations. Having a clear license in place helps clearly define what terms the software is able to be used under.

The value of this field will usually be the license's identifier code -- a string like "MIT" or "ISC" for the MIT license and ISC license respectively. If you don't wish to provide a license, or explicitly do not want to grant use of a private or unpublished package, you can put "UNLICENSED" as the license. Choose a License is a helpful resource if you're not sure which license to use.

author and contributors

"author": "Jon Church jon@example.com https://www.osioslabs.com/#team",
"contributors": [{
	"name": "Amber Matz",
	"email": "example@example.com",
	"url": "https://www.osiolabs.com/#team"
}],

The author and contributor fields function similarly. They are both "people" fields which can be either a string in the format of "Name <email> <url>" , or an object with fields name, email, url. The email and url are both optional.

Author is for a single person, and contributors is an array of people.

These fields are a useful way to list contacts for a public project, as well as share credit with contributors.

description

The description field is used by the NPM registry for published packages, to describe the package in search results and on the npmjs.com website.

This string is used to help surface packages when users search the NPM registry. This should be a short summary of what the package is for.

It can also be useful as simple documentation for your project, even if you aren't publishing it to the NPM registry.

keywords

"keywords": ["server", "osiolabs", "express", "compression"]

The keywords field is an array of strings, and serves a similar purpose to the description. This field is indexed by the NPM registry to help find packages when someone searches for them. Each value in the array is one keyword associated with your package.

This field doesn't have much use if you're not publishing to the NPM registry, and you can feel free to omit it.

main

"main": "src/index.js",

The main field is a functional property of your package.json. This defines the entry point into your project, and commonly the file used to start the project.

If your package (let's say its name is foo-lib) is installed by a user, then when a user does require('foo-lib'), it is the module.exports property of the file listed in the main field that is returned by require.

This is commonly an index.js file in the root of your project, but it can be any file you choose to use as the main entry-point to your package.

scripts

"scripts": {
	"start": "node index.js",
	"dev": "nodemon"
}

The scripts field is another functional piece of metadata in your package.json. The scripts property takes an object with its keys being scripts we can run with npm run <scriptName>, and the value is the actual command which is run. These are typically terminal commands, which we put into the scripts field so we can both document them and reuse them easily.

Scripts are powerful tools that the npm CLI can use to run tasks for your project. They can do the job of most task runners used during development. Learn more about npm scripts.

repository

"repository": {
	"type": "git",
	"url": "https://github.com/osiolabs/example.git"
}

You can record the repository the code for a project lives in by providing the repository field. This field is an object which defines the url where the source code is located, and what type of version control system it uses. For open source projects, this is likely GitHub or Bitbucket with Git as the version control system.

An important note is that the URL field is meant to point to where the version control can be accessed from, not just the released code base.

dependencies

"dependencies": {
	"express": "^4.16.4",
    "compression": "~1.7.4"
}

This is one of the most important fields in your package.json, and likely the entire reason you need one. All of the dependencies your project uses (the external code that the project relies on) are listed here. When a package is installed using the npm CLI, it is downloaded to your node_modules/ folder and an entry is added to your dependencies property, noting the name of the package and the installed version.

The dependency field is an object with package names as keys, and a version or version range as a value. From this list, npm knows what packages to fetch and install (and at what versions) when npm install is run in the directory. The dependency field of your package.json is at the heart of your project, and defines the external packages your project requires.

The carets (^) and tildes (~) you see in the dependency versions are notation for version ranges defined in SemVer. Learn more about dependency versions and SemVer.

devDependencies

"devDependencies": {
	"nodemon": "^1.18.11"
}

Similar to the dependencies field, but for packages which are only needed during development, and aren't needed in production.

An example would be using a tool to reload your project during development, like nodemon, which we have no use for once the application is deployed and in production. The devDependencies property lets us explicitly note which dependencies aren't needed in production. When installing your app in a production environment, you can use npm install --production to only install what is listed in the dependency field of package.json.

Recording a devDependency is a great way to document what tools are needed for the app during development. To install a package from npm as a devDependency, you can run npm install --save-dev <package>.

There is another way the devDependencies property is useful to us, and that's by using them in our npm scripts. Learn more about using devDependencies in npm scripts.

Manage your package.json

A package.json file must be valid JSON. This means any missing commas, unclosed quotes, or other formatting errors will prevent npm from interacting with the package.json. If you do introduce an error, the next time you run an npm command you will see an error from npm. It's recommended to use the npm CLI for updating and managing your package.json when possible, to avoid accidentally introducing errors to your package.json, and to make managing your dependencies easier.

Using npm init to create your package.json will help to ensure you generate a valid file.

Dependencies are best managed by using npm's commands npm install, npm uninstall, and npm update, so your package.json and node_modules/ folder are kept in sync. Manually adding a dependency listing will require you to run npm install before the dependency is actually installed to your project.

Because our package.json is only where we record dependencies, and our node_modules/ folder is where the actual code for dependencies is installed, manually updating the dependency field of package.json does not immediately reflect the state of our node_modules/ folder. That's why you want to use npm to help manage dependencies, because it will update both the package.json and node_modules/ folder in tandem.

You can always edit your package.json manually in your text editor and make changes. That works well for most fields, so long as you're careful not to introduce any JSON formatting errors. We recommend you use the npm CLI commands wherever you can, however.

Recap

The package.json file is the heart of any Node project. It records important metadata about a project which is required before publishing to NPM, and also defines functional attributes of a project that npm uses to install dependencies, run scripts, and identify the entry point to our package.

Not all fields available in package.json will apply to you, but we can achieve some powerful benefits by recording information about our application in its package.json file. Understanding the role of package.json and how it relates to npm is an important part of developing Node.js apps, and increasingly an important part of the JavaScript ecosystem.

Further your understanding

Additional resources

Sign in with your Osio Labs account
to gain instant access to our entire library.