JavaScript Packaging with package.json
JavaScript Packaging with package.json
¶
Python has infrastructure for installing libraries with dependencies. The frontend world does as well, based on npm.
In this article we will turn a directory into a project by creating a
package.json
file. We will then use this to hold dependency
information as we install packages needed both for the running of our
frontend and tooling packages needed in the building of the frontend.
Overview¶
- Learn about frontend tooling using the NodeJS universe
- Show the convenient way to get all dependencies
- Discuss reproducible builds
Installing Dependencies: The Shootout¶
Python can install packages. Python can track dependencies. Python can do both, and as we who love Python know, it’s one of the darkest corners of Python history. setuptools, distutils, easy_install, setup.py, MANIFEST.in, setup.cfg, pip, requirements.txt, eggs, wheels...it’s been a rocky road for Python to get to an emerging point of consistency.
Let’s concentrate on making a directory into a “project”. In Python,
you would create a setup.py
file with the setuptools
-compliant
data, such as the name of the project. You would also supply some
dependencies, although many people also do that in pip’s
requirements.txt
file. Finally, you would make a virtual
environment, which would install your dependencies into a
site-packages
directory under, for example, lib/python3.5
.
Let’s tackle each part of this, using the new NodeJS/npm toolchain.
Making a Project¶
In Python, if you want a directory to be a “project”, you create a
setup.py
file. This contains, for example, the name of the project.
In the world of Node, a package.json file performs this role. Since it is JSON and not JavaScript, it can only hold configuration data.
You interact with this file primarily through the npm
command and
toolchain. For example, you can let npm
ask you question to create a
new package.json
file:
$ npm init
If you’re in a hurry, tell it to accept the defaults for every question:
$ npm init --yes
You now have a project area. You can check this package.json
file into
version control.
Install Dependencies¶
You have a frontend that depends on jQuery and a backend that depends on Flask. You want to easily install those packages, but you also want to record them as dependencies, so you can reproduce your setup later.
In Python, you might do any of the following:
- Install the package using
pip
, then either usepip freeze
or manually edit arequirements.txt
file to record the dependency - Edit the dependencies list in
setup.py
then executepython ./setup.py install
- Use PyCharm’s visual package installer, then record the fact later
In Python, installing a package and recording a dependency are distinct.
For this task, using npm
is a breath of fresh air:
$ npm install --save jquery
This command says to download the jQuery package, install it local to
the project, and record it as a dependency in package.json
. Instead
of lib/python3.5/site-packages
, though, packages are installed
in a node_modules
subdirectory under the location of
package.json
.
There’s a lot to talk about for npm install. Just a few points for this article:
- You can pass a flag to install packages globally
- You can save packages as a project dependency or a development dependency
- You can record dependency version ranges in rich ways, based on semantic versioning or channels
Note
One reason npm
has gotten so big, so powerful, so quickly: it’s
a company. In 2014 and 2015 it raised $10M in funding. For
better or worse.
PyCharm’s Friendly Face¶
For Python, we know that PyCharm provides a UI
for finding and adding packages, removing them, etc. The same is true for
npm
packages: PyCharm provides an npm UI
for these as well:
You can reach this UI at Preferences -> Node.js and NPM. With this, you
don’t have to use the command line and learn the npm
interface for
installing, updating, and removing npm
packages into node_modules
.
Virtual Environment?¶
We now have our dependency (jQuery) as a file in our project area, recorded as a dependency with a minimum version. At the top in the shootout, we said we would also show having a virtual environment for isolating our software. For Node and npm, this last step is...nothing.
Node packaging was designed to have a two-tier namespace for finding
packages: either local to the project, in a node_modules
subdirectory, or global to the interpreter. The former is checked
first. We only inherit packages from the global environment if
we accidentally install them with npm install -g
.
If you do want that level of isolation, which is the default in
the latest virtualenv
and pyvenv
commands, you can use
nvm to manage your Node
interpreters.
Wrapup¶
With package.json
, we have a way to make a project area,
record package information, install packages, and record dependencies.
This gives us most of what we need for reproducible builds.