The typical use of jshint
involves including rules in a .jshintrc
or Gruntfile.js
. This does not scale to multi-repo organizations, as .jshintrc
files must be made in each repo, and organization-widge changes to these rules must be copied to each repo's .jshintrc
file.
Fortunately, it's easy to formalize and enforce style standards in your organization's Javascript. Here we describe the pattern we use.
The overview:
- Formalize your style into JSHint rules (i.e. identify the rules you would place in a
.jshintrc
file) - Centralize access to jshint rules via a packaging pattern (described below)
- Require jshint conformance in unit testing/code reviews/deployments.
Assuming your org's deployment cycle requires unit tests before deployment, this puts you in good shape.
Using an internally agreed-upon jshint standard, we created a node package in github which we include in all node projects.
This package is pretty simple, but here are the main points:
- a
jshintrc
file contans the jshint rules of our organization - a "bin" script, which executes
jshint
using thisjshintrc
file, is installed and available to the including repo. No need to installjshint
, however: the module installs its own copy - a custom
jshintignore
policy, which ignoresnode_modules
and.git
.
Other organizations can adopt their own by forking our repo.
All projects in our organization include this in package.json
:
"devDependencies": {
...
"jshinthelper": "git+ssh://[email protected]:gyllstromk/jshinthelper.git#0.5.0"
...
}
(Note the use of the #0.5.0, which is a tag name. This simply identifies the particular commit I want. More on this below.)
Enforcing conformance involves hooking it into the test scripts in package.json
. We use the pretest
script: this is executed before the test
scripts; if it fails, the tests are not run and npm test
fails.
We simply include a jshint
step:
"scripts": {
"pretest": "./node_modules/.bin/jshint .",
"test": "./node_modules/.bin/mocha -R spec"
Note that if you aren't using our jshinthelper
model, this still works: simply install jshint by itself:
$ npm install jshint --save-dev
This installs jshint
to ./node_modules/.bin
and runs based on what's in your .jshintrc
and .jshintignore
files.
The desired style rules will likely evolve with your project. Versioning via npm/git makes managing this easy.
When modifying rules in your jshinthelper
fork, a new version has an attendant git version. This can be used directly in the include:
"devDependencies": {
...
"jshinthelper": "git+ssh://[email protected]:gyllstromk/jshinthelper.git#my_commit_version"
This model works for revision number, branch name, and tags.
This way, if a particular package depends on a version of jshinthelper
, i.e. the rules in that version, it is unaffected by subsequent updates to the jshinthelper
module. Updates to new jshint rules by the package, then, must be explicit: the version of jshinthelper
included must be incremented, installed, and tested.
Alteranatively, it may be desired that a package always comply with the latest jshint rules. In this case, ommit version number in the package inclusion:
"devDependencies": {
...
"jshinthelper": "git+ssh://[email protected]:gyllstromk/jshinthelper.git"
In the above, the latest in master
branch is always used.
Say you need different variants of jshint rules, such as one with use_strict
. This can be done with git branches, for example:
- Make a
use_strict
variant from within thejshinthelper
package:
$ git checkout -b use_strict
- Update the
.jshintrc
file to requireuse_strict
. Commit and push the branch. - In packages where
use_strict
is required, update the inclusion string inpackage.json
:
"jshinthelper": "git+ssh://[email protected]:gyllstromk/jshinthelper.git#use_strict
Many use grunt
as the location in which jshint
rules are placed. I recommend avoiding this in organizations because the logic cannot be centralized; i.e. the jshint rules must be copied to the Gruntfile in each repo, and synchronized on changes.