Add Prettier
Summary
This RFC proposes adding Prettier to the blueprints
that back ember new
and ember addon
.
Motivation
Using Prettier removes the ever present and ongoing stylistic debates that tend
to happen on teams. Prettier is incredibly freeing for both developers and
reviewers of a codebase. The developer can author in whatever format they find
easiest to type out, avoiding needless wasted time trying to get that
indentation just right, and either setup an automated "format on save"
operation in their editor or use a quick command line invocation to --fix
all
files at once.
This dove tails very nicely with Embers deeply ingrained goal of using shared solutions to solve common problems, and aligns very well with the general trend to play better with the general JavaScript ecosystem.
Detailed design
Due to the pre-existing design (and improvements added to the blueprints in
ember-cli/rfcs#121)
implementation is very straight forward. The general idea is that we will
update the app
and addon
blueprints to add a few Prettier related packages
to the package.json
, update the linting configuration to enforce Prettier
styles, and update the other blueprint code to ensure that its output is
Prettier compatible.
Packages
The following packages will be added to the package.json
of both app
and addon
blueprints:
- prettier - The main package (used by the other packages).
- eslint-config-prettier - Disables stylistic ESLint rules that would conflict with the Prettier output.
- eslint-plugin-prettier - Enables
eslint-config-prettier
srecommended
set, and adds theprettier/prettier
rule to enforce styles.
Configuration Changes
ESLint
The .eslintrc.js
that is generated will be updated to add:
{
extends: ['plugin:prettier/recommended'],
}
Prettier
A .prettierrc.js
will be added with the following contents:
module.exports = {
singleQuote: true,
};
There is a small number of configuration options that can be used in this file, but we are intentionally avoiding modifying the default values for things that are not nearly universally agreed on in the Ember ecosystem.
A .prettierignore
will be added to match the .eslintignore
contents:
# unconventional js
/blueprints/*/files/
/vendor/
# compiled output
/dist/
/tmp/
# dependencies
/bower_components/
/node_modules/
# misc
/coverage/
!.*
# ember-try
/.node_modules.ember-try/
/bower.json.ember-try
/package.json.ember-try
Git
The .gitignore
will be updated to add .eslintcache
so that when using
eslint --cache
the cache file itself won't be added to the repositories
history.
Blueprint Changes
In general, it is recommended that all blueprints provided by addons should
satisfy the default linting configuration of a new Ember application. As such
the blueprints provided by ember-cli
, ember-source
, and ember-data
will
be updated to ensure that they satisfy these new linting rules requirements.
In order to ensure blueprint output follows each individual projects custom
stylistic linting settings as much as possible. The following will be updated
to run lint:fix
(when available) after their existing functionality:
ember generate
ember init
ember-cli-update
package.json
scripts
The app
and addon
blueprints will be updated to add the following
additional entries to scripts
:
{
"scripts": {
"lint": "npm-run-all --aggregate-output --continue-on-error --parallel 'lint:!(fix)'",
"lint:fix": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*:fix",
"lint:js": "eslint . --cache",
"lint:js:fix": "eslint . --fix",
"lint:hbs:fix": "ember-template-lint . --fix"
}
}
A few callouts here:
- The
lint:fix
,lint:js:fix
,lint:hbs:fix
scripts are new (introduced with this RFC) - The
lint
script will be updated to ensure that it avoids running the newlint:fix
script - The
lint:js
script will be updated to add caching
This configuration is specifically intending to allow users to add additional
linters (e.g. stylelint
or markdownlint
) by adding scripts for them, and
they would automatically be rolled up into lint:fix
.
Codemod
In order to make the migration as simple as possible, a codemod will be created: ember-cli-prettier-codemod
.
The codemod will do the following:
- Install the new/required dependencies
- Migrate an application / addon to the new linting configuration
- Commit just the configuration changes.
- Run the new
lint:fix
script to update all files to the new format. - Commit just the auto-fixed output.
While this seems quite simple (and in fact it is pretty easy), leveraging a codemod will make it much easier to deal with rebasing large Prettier migration pull requests. If one of those pull requests gets out of date (e.g. due to a conflict in one of the files) you can simply re-run the codemod on the branch and it will replace the previously created commits.
How we teach this
We do not currently discuss linting or stylistic formatting in either guides.emberjs.com or cli.emberjs.com.
This RFC proposes adding a new subsection that discusses linting under Basic
Use
section of the CLI guides. In
addition, when this RFC is implemented we should do a throughough audit of the
cli.emberjs.com
and guides.emberjs.com
content to ensure that all code
snippets are formatted correctly (e.g. using the Prettier specific formatting
introduced here).
Drawbacks
The largest drawback is generally the cost of the initial migration to Prettier. That migration tends to be quick, but it can cause pain for folks maintaining long lived branches.
Alternatives
Why not adopt standard instead of Prettier?
Prettier is much more popular with 9,249,847 weekly
downloads vs 265,658 weekly
downloads (we all know these download
numbers don't mean a ton, but the order of magnitude can tell us something),
and (aside from the defaulting of singleQuotes
) is much more aligned with the
Ember ecosystems inherent preferences.
Additionally, a very large number of the Ember ecosystem
projects are already using Prettier internally. These include ember-source
,
ember-cli
, ember-data
, @ember/test-helpers
, eslint-plugin-ember
, the
various packages composing the rendering engine, @glimmer/component
,
ember-template-lint
, and many more. Additionally a large number of community
maintained addons are also using it already (here is a
listing
using EmberObservers awesome code search feature).
Unresolved questions
In general, users of
yarn
could be perfectly happy withyarn lint:js --fix
/yarn lint:hbs --fix
(which works today). Should we still add thelint:js:fix
/lint:hbs:fix
scripts?
I went with "yes" here in the initial RFC prose, as I'd general prefer to reduce the differences between users of npm
and yarn
over time.