I created a new Vue3 app using the Vue CLI and selected Prettier for my linter config. I want to use commitlint, husky and lint-staged to validate commit messages and lint the code before pushing it.
What I did
Based on https://commitlint.js.org/#/guides-local-setup I setup commitlint with husky
npm install --save-dev @commitlint/{cli,config-conventional}
echo "module.exports = { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js
npm install husky --save-dev
npx husky install
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit $1'
Based on https://github.com/okonet/lint-staged#installation-and-setup I setup lint-staged
npx mrm@2 lint-staged
and inside the package.json I replace
"lint-staged": {
"*.js": "eslint --cache --fix"
}
with
"lint-staged": {
"*": "npm run lint"
}
The problem
When modifying the README.md file in the project to
# my-repo
---
new commit
and try to commit that I get the following error message
> git -c user.useConfigOnly=true commit --quiet --allow-empty-message --file -
[STARTED] Preparing...
[SUCCESS] Preparing...
[STARTED] Running tasks...
[STARTED] Running tasks for *
[STARTED] npm run lint
[FAILED] npm run lint [FAILED]
[SUCCESS] Running tasks...
[STARTED] Applying modifications...
[SKIPPED] Skipped because of errors from tasks.
[STARTED] Reverting to original state because of errors...
[SUCCESS] Reverting to original state because of errors...
[STARTED] Cleaning up...
[SUCCESS] Cleaning up...
ā npm run lint:
> my-repo@0.1.0 lint
> vue-cli-service lint "/home/.../my-repo/README.md"
error: Parsing error: Invalid character at README.md:1:1:
> 1 | # my-repo
| ^
2 |
3 | ---
4 |
1 error found.
npm ERR! code 1
npm ERR! path /home/my-repo
npm ERR! command failed
npm ERR! command sh -c lint-staged
npm ERR! A complete log of this run can be found in:
npm ERR! /home/.../.npm/_logs/2021-12-27T10_07_27_498Z-debug.log
husky - pre-commit hook exited with code 1 (error)
What it should do
Only fix the files that have been modified. The linter knows about files it is able to fix (js, ts, vue, html, ...).
When having a modified markdown file I get no errors when opening the terminal and run npm run lint
. But I do get errors when using lint-staged with this setup "*": "npm run lint"
What is the correct setup for lint-staged to lint "lintable" files only?
I've suggested "**/*.{js,vue}": ["npm run lint:js:fix"]
, first of, lint:js:fix
is subjective and up to you. This is what Kent C Dodds is using, so I'm just naming it in the same way.
But you could totally have lint:watermelon-potato-hehe
instead, doesn't matter.
Now, about your propositions:
"**/*.{vue,js,jsx,ts,tsx}": "npm run lint"
, this one is targeting more extensions, which is totally fine. You may not really use .tsx/.jsx
since it's not really popular among Vue devs..ts
itself, it may probably work good enough (maybe you'll need to add some plugins to your ESlint configuration). I'm not into TS so I can't really help on this one but it's out of the husky/lint-staged scope anyway.As for the second part, since I like to setup my own ESlint config, with some simple and well documented API, we're using eslint --ext .js,.vue --fix
. That way I'm sure of what is happening and how to troubleshoot it if needed.
vue-cli-service lint may be a good default package aimed towards Vue with some defaults, I'm not sure what's inside it and even if it's probably just an ESlint with some baked-in configuration, again we prefer to make our own Vue configuration with vanilla ESlint.
So yeah, if you need to go fast, use vue-cli-service lint
for some quick linting, if you want to have a better flow in your project and want to fine grain your config, use vanilla ESlint, you'll get less trouble overall IMO.
"**/*.{vue,js,jsx,ts,tsx}": "eslint --ext .vue,.js,.jsx,.ts,.tsx --fix"
. On the right side, we globally have the same lint:js:fix
scripts but with additional extensions.So, you may ask why are we even writing the extensions on the left side for lint-staged
and on the right side for lint:js:fix
? I'd answer that those are not really needed on the right side (AFAIK), because lint-staged will only run the command to the left list of extensions.
Here, we wanted to be more explicit about the exact extensions we're targeting and also, it enables you to run npm run lint:js:fix
in your CLI at any given point without getting errors on files ESlint is not handling (.txt
, .json
, .md
, .jpg
etc...).
So it could maybe be removed (not sure), fastest way to be sure is to try!
"**/*.{vue,js,jsx,ts,tsx}": "eslint --fix"
, this one may work fine as explained in the previous paragraph. Didn't tried it myself thought.Regarding .html
, you should not have a lot of those in your Vue project. You could use the W3C validator to check for any errors if you really need it.
If you're speaking about your HTML in the template
tags in your .vue
files, those will be ESlint'ed properly. If you setup a Prettier on top of it, you will also get some nice auto-formatting which is really awesome to work with (once your team has agreed on a .prettierrc
config).
Regarding .json
files, those are not handled by ESlint. ESlint is only for JavaScript-ish files. If you want to lint/format your .json
or even any other extensions at all, you can aim towards NPM, find a package that suits your team's needs and add it to your chain like "**/*.json": ["npm run lint-my-json-please"]
and you should be good!
At the end, husky + lint-staged are not doing anything special really. They are tools to automate what you could write yourself in a CLI, so if it's working when done manually and you're happy with the result, you can put it in your config but you need to first found what the proper package and it's configuration.
In your package.json
, you could have the following
"scripts": {
"lint:js": "eslint . --ext .js,.vue",
"lint:js:fix": "eslint --ext .js,.vue --fix",
},
In your .lintstagedrc
{
"**/*.{js,vue}": ["npm run lint:js:fix"]
}
In .husky/pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npm run lint-staged
In .husky/commit-msg
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx --no-install commitlint --edit ""
You can setup ESlint to watch any errors in your files in VScode (a lint + formatter when your files are saved is also doable pretty easily).
That way, you can run npm run lint:js
to check the issues by yourself.
Otherwise, let husky run lint-staged and apply the eslint --fix
to all of your .js
and .vue
files.
Your commitlint.config.js
config should be okay!
As a reminder here, lint:js
will scan all of your JS and Vue files.
While, when you commit and husky is executed (by running the lint:js:fix
script), ONLY the files that you have touched will be linted (that's the whole point of lint-staged
).