pnpm
support
Summary
Enable Ember CLI users to opt into using pnpm
for package management.
Motivation
pnpm
is a popular alternative to both npm
and yarn
that prioritizes correctness, especially for peerDependencies
and monorepos.
pnpm
has very active maintainance, support, and financial funding.
Their website states that pnpm
is:
- Fast:
pnpm
is up to 2x faster than the alternatives - Efficient: Files inside
node_modules
are cloned or hard linked from a single content-addressable storage - Supports monorepos:
pnpm
has built-in support for multiple packages in a repository - Strict:
pnpm
creates a non-flatnode_modules
by default, so code has no access to arbitrary packages.
For folks with lots of projects on their computers, pnpm
is extremely space-efficient.
Where npm
and yarn
would duplicate node_modules
per-project, pnpm
will only download a package (at a specific version) once across your whole machine.
Additionally, npm
and yarn
repeatedly have demonstrated that their strategies with peerDependencies
are not correct, and it is vitally important we use and support a tool that can guide folks towards correctly creating addons. For example, @embroider/macros
relies on node's resolution algorithm, so having peerDependencies
resolved correctly is important for dependencySatisfies
to work as expected in monorepos.
Ember CLI currently only supports npm
(default) and yarn
for project initialization as well as various commands. At present, projects work with pnpm
, but the tooling is unaware.
Detailed design
Enabling pnpm
is designed as opt-in to prevent disruptions to developer's current workflow, much the same as yarn
.
There are a few integration points that we must support for pnpm
(and any package manager):
ember install
ember init
,ember new
,ember addon
ember try:one
,ember try:each
- generated C.I. configs
- Documenation
ember install
There are two mechanisms through which to opt-in.
The first one is the presence of a pnpm-lock.yaml
file in the project root.
The pnpm-lock.yaml
file is generated by pnpm
when you run pnpm install
(or the shorter pnpm i
),
so we assume that its presence means the developer intends to use pnpm
to manage their dependencies.
Alternatively you, you can force Ember CLI to use pnpm
with the --pnpm
flag.
To recap:
ember install ember-resources
withpnpm-lock.yaml
present will usepnpm
ember install ember-resources
withoutpnpm-lock.yaml
present will use npmember install ember-resources --pnpm
will usepnpm
ember init
, ember new
, ember addon
Since this triad of commands is generally ran before a project is set up, there is no pnpm-lock.yaml
file presence to check.
This means we are left with the --pnpm
flag, which will also be added to these commands:
ember new my-app
will use npmember new my-app --pnpm
will usepnpm
The above also applies to ember addon
and ember init
, noting that ember init
doesn't receive any arguments.
--skip-npm
The --skip-npm
flag actually means "skip installation of dependencies" when using ember addon
and ember new
,
including skipping installation with both npm
and yarn
.
This will need to be extended to also skip installation of dependencies when pnpm
is used.
For example:
ember new my-app --pnpm --skip-npm
ember try:one
, ember try:each
At the time of writing this RFC, ember-try
already supports pnpm
, but it is undocumented in the README.
Documentation will need to be added to the README,
as well as the relevant ember-cli
blueprints will need to correctly configure usePnpm: true
in the ember-try.js
config file when the pnpm
flag is present.
generated C.I. configs
At the time of writing this RFC, ember-cli
supports two C.I. environments: Travis and GitHub Actions.
Both the .travis.yml
and .github/workflows/ci.yml
config files for relevant blueprints will need to support the pnpm
option such that C.I. passes on new projects using pnpm
.
for addons
Addons should be stricter than defaults, so that they are good stewards of the ecosystem and don't leak accidental uncertainty to their consumers.
In addon projects, the .npmrc
will need the following defaults:
# all peer dependencies must be declared or forwarded to the consumer
auto-install-peers=false
# we want true isolation in addons -- if a dependency is not declared, we want an error
reslove-peers-from-workspace-root=false
Documentation
These pages presently mention npm
/ yarn
and will need to be updated to include pnpm
- https://cli.emberjs.com/release/basic-use/assets-and-dependencies/
- https://guides.emberjs.com/release/addons-and-dependencies/
How we teach this
The Ember Guides should be updated to reflect the new flags, where applicable,
as well as the new behavior of ember install
in the presence of a pnpm-lock.yaml
-- though most of the guides use ember
as the CLI tool for managing packages.
We may want to consider updating the tutorial (and its automation) to use pnpm
, as npm
is very slow.
In addition, the built-in instructions for ember help
should be updated to reflect the new flags.
Drawbacks
pnpm
is very strict about peers and what dependencies are allowed in a project and will error if a project's package.json is incorrect for a given scenario.pnpm
is very clear about these errors and what to do for action items, but it means that we'll need to make sure thatpnpm
is tested inember-cli
when generating new projects so that we can be certain that folks' "first time experience" is smooth- There may be other package managers in the future, but we cannot see the future. There have been talks about making ember-cli somehow generically handle package-managers, but it is unknown how that would work, and is unneeded for now.
Alternatives
- Figure out a way to generically handle any package manager
- Continue with the partial pnpm support we have today
Unresolved questions
- Are there any other references in the guides to
npm
oryarn
? The only place I could find that mentionedyarn
is here: https://guides.emberjs.com/release/addons-and-dependencies/ - Is there a
--package-manager
flag / option inember-cli
? for blueprint authors, that may be useful. - Should
--skip-npm
be aliased to--skip-install
?