Skip to content

Dependency Management

James Calcaben edited this page Oct 16, 2019 · 3 revisions

NPM Dependency Management in the PWA Studio Project

PWA Studio is a "monorepo" managed by lerna, a tool for managing multiple NPM packages in a single repo. It contains several NPM packages in its packages/ folder, each with a package.json file, and the root directory contains a package.json file which stores mutual dependencies of the child packages.

The NPM scripts are designed so that nearly all operations, even ones for individual packages, should be run from the root directory.

This can make it confusing when you want to add a library.

When you want to add a library to a file in a particular package:

For All Dependencies

First, always add the package to the root level devDependencies. This helps ensure that the packages rely on the same versions of common libraries, so there are no subtle bugs due to incompatibilities, or duplicate dependencies in a bundle. For any new dependency, whether a runtime or dev-only dependency always run this command:

```sh
yarn install --save-dev <moduleToAdd>
```

The root package should have no dependencies, only devDependencies.

Next, you may need to run an additional command to fully install the dependency.

For Venia Dependencies

If the package is used directly in the @magento/venia-concept code, add it to the package root devDependencies and to the dependencies of the Venia package file.

Venia's frontend code is bundled by Webpack at build time, so it does not import from node_modules at runtime. However, Venia is distributed as a self-building package, so all of its frontend and build-time dependencies are dependencies.

After adding to root devDependencies as described above, run this command from the root directory:

npx lerna add --scope @magento/venia-concept <moduleToAdd>

For Runtime Dependencies

If the package must require() the dependency at runtime, add it to the dependencies of the package. Packages like @magento/pwa-buildpack and @magento/upward-js are distributed individually on NPM. These are meant to work outside the PWA Studio environment. They also run in Node, so they will expect the dependency to be present without PWA Studio being installed. These are "production" dependencies.

In many projects, the frontend libraries are devDependencies, since they are bundled before running in the browser. However, the @magento/peregrine package exports ES6 modules, which enables an advanced form of bundle compression called tree-shaking. When used as ES6 modules, Peregrine files will import their dependencies directly from node_modules, so any runtime Peregrine dependencies are "production" dependencies as well.

After adding to root devDependencies as described above, run this command from the root directory:

npx lerna add --scope <targetPackage> <moduleToAdd>

For instance, to install NPM module foo-library into the package @magento/peregrine, the command would be:

npx lerna add --scope @magento/peregrine foo-library

For Testing and Development Dependencies

Many libraries in PWA Studio are used only for testing, linting, or debugging, such as the jest test framework. When writing a test or adding a lint rule, you may need to install additional libraries. If the package will only be used during development, add it only to the devDependencies of the root package file. Run the command described above, and then you're done.

For Peer Dependencies

An NPM "peer dependency" allows the consumer of a package to control the version of a shared dependency more precisely, and is commonly used when making plugins. Both @magento/pwa-buildpack and @magento/upward-js contain plugins for other libraries, so they list those libraries as peerDependencies which must be installed alongside them.

After adding to root devDependencies as described above, add peerDependencies manually to the package.json of the appropriate package. Make sure the semver string exactly matches the semver string in the root package dependency.

Summary

  • All dependencies of any kind must be listed in the devDependencies of the root package.json file.
  • All direct dependencies of Venia must also be added to the dependencies of the packages/venia-concept/package.json file.
  • All runtime dependencies and peer dependencies of other libraries must be listed in those libraries' package.json files.
  • All dev dependencies are listed only in the root package.json file; no other package.json file should have any devDependencies.