Rootree
Github Logo

Anatomy of a package.json

Github Logo

Ever wondered what all those fields in package.json are for? Well, wonder no more! Here’s a brief overview of the fields that we commonly use. (And the whys).

Here is a stripped down version of our theme’s package.json file that we’ll be using as an example:

{
	"name": "@rootreeweb/rootree-theme",
	"version": "9.0.12",
	"private": true,
	"license": "",
	"scripts": {
		"build": "yarn run clean; webpack --mode=production",
		"dev": "webpack --mode=development --watch",
		"lint": "eslint --fix --cache & stylelint **/*.*css --fix --cache",
		"format": "composer format & prettier . --write --cache",
		"version": "node rt-update.mjs",
		"release": "./release.sh"
	},
	"dependencies": {
		"react": "^18.2.0",
		"react-dom": "^18.2.0",
		"splide": "^5.2.2"
	},
	"devDependencies": {
		"prettier": "^3.1.0",
		"sass": "^1.69.5",
		"webpack": "^5.89.0"
	},
	"packageManager": "yarn@4.0.2",
	"main": "./src/index.ts",
	"types": "./src/index.ts",
	"type": "module",
	"files": ["dist"],
	"browserslist": ["extends @wordpress/browserslist-config"],
	"author": "Rootree",
	"description": "Rootree Wordpress Theme",
	"repository": {
		"type": "git",
		"url": "git+https://github.com/rootreeweb/Rootree-Wordpress.git"
	},
	"bugs": {
		"url": "https://github.com/rootreeweb/Rootree-Wordpress/issues"
	},
	"homepage": "https://github.com/rootreeweb/Rootree-Wordpress#readme"
}

Important Fields

These are fields that are important to have in the package.json file, and that you will (or should) see in most of our packages.

  • name:
    • This is fairly straightforward, it’s the name of the package.
    • We use the @rootreeweb scope to indicate that it is a package that we have created.
      • This is important both for when we publish the package to NPM, and to differentiate it from other packages that may have the same name, even if we aren’t publishing.
    • It’s also worth noting that if you rename the package, you will need to run yarn install again to generate the correct lockfile before you do anything else.
      • Wait, what’s a lockfile? A lockfile is a file that is automatically generated by Yarn that contains the exact versions of all the dependencies that are installed. This is important because it ensures that everyone who installs the package will have the same versions of the dependencies, as the package.json file might actually just specify a range of working versions. It also helps keep track of your dependencies’ dependencies.
  • version:
    • This is simply the current version of the package.
    • We use semantic versioning to indicate what kind of changes have been made.
    • If the package is being published, you will need to update this number for the registry to accept the update.
  • private:
    • This is a flag that indicates whether the package should be publishable to a registry.
      • The default value is false, meaning that the package will be publishable.
      • If it is set to true, then the package cannot be published.
    • This is useful for preventing internal packages from being accidentally published.
  • license:
    • This is the license that the package is released under.
    • GitHub makes use of the field, so it is good to set.
  • scripts:
    • This is a list of scripts that can be run using yarn run <script name>.
    • We use this to run our build, linting, etc. scripts.
      • It’s also possible to run scripts from the command line using yarn <script name>. However, this can cause confusing issues as it can conflict with other built-in yarn commands. A common example of this is yarn version runs an internal command instead of our own version command.
    • Common scripts that we use:
      • yarn build Runs any bundling and/or transpilation need for the finished project. There may also be other variations such as yarn build:esm to build for various targets.
      • yarn dev Builds a development version of the project. yarn dev:local is sometimes used to differentiate when a local dev-server is used.
      • yarn check Runs the TypeScript transpiler in noEmit mode to check for type issues without running a full build.
      • yarn format Runs the formatter (Typically Prettier) to pretty-up the code. This sometimes will also initiate the composer script that does the same for the code not handled by prettier.
      • yarn lint Runs the linter (eslint, stylelint, etc.) to check for code quality issues. Once again, this may pass off linting responsibilities for PHP to a composer script. In some projects, yarn lint:php is used to differentiate between the two areas of concern.
      • yarn test Runs the testing framework (vitest, phpunit, etc.) and reports back on coverage. yarn test:watch runs the test framework in watch mode where applicable.
      • yarn run release Preps and releases the NPM package
      • yarn run version Sets the new version number throughout the project.
      • yarn clean Deletes the contents of the output folder. Typically used as part of the build step.
      • yarn prepare Sets up git hooks that have been configured for the project.
  • dependencies:
    • This is a list of dependencies that are required for the package to function.
    • These are included when the package is published. We use this to specify the versions of the packages that we use that are required at run-time, or by other packages that use the package such as React, Splide, etc…
      • Note that we can include our own packages in the list by using the @rootreeweb scope. However, we need to indicate to yarn where to find those packages, separate from the package.json file. Learn more in our private packages guide.
  • devDependencies:
    • This is a list of dependencies that are only required for development.
    • These are not included when the package is published.
    • We use this to specify the versions of the tooling we use such as webpack, SASS, etc…
  • packageManager:
    • This field is automatically set by Yarn to indicate which version of the package manager was used to generate the lockfile.
    • This is useful for ensuring that everyone is using the same version of the package manager. Corepack will download the required version if it is enabled.

(Sometimes) Important Fields

These fields are important to have in some cases, but not in others.

  • main:

    • This is the entry-point for the package.
    • This is used by tools such as webpack to determine where to start bundling the code (If not specified in the webpack config).
    • This is most frequently used in packages to indicate the main file that should be included when the package is required.
  • exports

    • This is a newer version of the main field that allows for multiple entry-points. It should generally be used instead of main and types.
    • This can also include things like stylesheets for the consuming package to use.
    • Example exports:
    {
    	"exports": {
    		".": {
    			"import": {
    				"types": "./dist/esm/index.d.ts",
    				"default": "./dist/esm/index.js"
    			},
    			"require": {
    				"types": "./dist/cjs/index.d.ts",
    				"default": "./dist/cjs/index.cjs"
    			}
    		}
    	}
    }
  • types:

    • This is the entry-point for the type definitions for the package.
    • This is used by tools such as TypeScript to determine where to look for type definitions.
    • This is most frequently used in packages for consumers to find the exported type definitions.
    • As with main, this field is deprecated in favour of exports.
  • type:

    • This is used to indicate that the package is an ES module.
    • This is used by node to determine how to run/import the package.
    • This also can control how the package is bundled by tools such as webpack.
  • files:

    • This is a list of files that should be included when the package is published.
    • This is used by the registry to determine which files to include in the package.
  • workspaces:

    • This is a list of directories that should be treated as workspaces.
    • This is used by tools such as Yarn to determine which directories to install dependencies in.
    • We use this to indicate that the package is a mono-repo. With child packages in the specified directories.
  • engines:

    • This is a list of engines that the package supports.
    • This is used by tools such as Yarn to determine whether the package is compatible with the current environment.
  • peerDependencies

    • These will only be found in shared packages,
    • These are dependencies that should be shared with the consuming packages.
    • Without these, there is a risk that two versions of the same dependency can be used.
    • This is most problematic with React, Zod, and anything that relies on databases.

Package Specific Fields

These are fields that may be present on a project-to-project basis. They are usually used by build tools/other tooling as configuration.

  • browserslist:
    • This is a list of browsers that the package supports.
    • This is used by tools such as Babel to determine which features to include in the transpiled code.
    • We use the @wordpress/browserslist-config preset to indicate that we support the same browsers as WordPress.

Nice to Have Fields

These are fields that are nice to have, but not strictly necessary.

  • author:
    • This is the author of the package.
  • description:
    • This is a short description of the package.
  • repository:
    • This is the repository that the package is stored in.
  • bugs:
    • This is the URL of the bug tracker for the package.
  • homepage:
    • This is the URL of the homepage for the package.