prettier使用指南
01.什么是prettier
prettier是一个代码格式化工具,支持下列编程语言的代码格式化
- JavaScript (including experimental features)
- JSX
- Angular
- Vue
- Flow
- TypeScript
- CSS, Less, and SCSS
- HTML
- JSON
- GraphQL
- Markdown, including GFM and MDX
- YAML
和其他lint工具比如eslint的区别
prettier的配置项比较少(容易配置),且只专注于代码样式,而eslint还提供语法检查,现在的eslint也集成了formatter功能。
prettier相比eslint支持更多文件的格式化。
02.使用方法
安装
在项目中,安装到开发依赖上
代码语言:javascript复制npm install --save-dev --save-exact prettier
忽略不想格式化的文件
创建 .prettierignore忽略你不希望格式化的文件,node_modules是默认会被忽略的目录。
他的用法就类似于.gitignore
,下面是官方给的例子
# Ignore artifacts:
build
coverage
命令行执行格式化
在项目中手动调用prettier命令行进行格式化
npx prettier --write .
提前查看会格式化哪些文件,不实际执行格式化
npx prettier --check .
实际使用过程中,还是直接用编辑器的插件的,设置成保存的时候执行格式化。
解决和eslint的冲突
安装 eslint-config-prettier,这个插件会把eslint中可能导致冲突的规则关掉,这样两者就能兼容使用了。
git hooks
可以设置在git提交之前执行一次格式化( pre-commit hook ),这样我们仓库里的代码就都是格式化好的了。
只需要在package.json里面加入一些配置。
代码语言:javascript复制{
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"**/*": "prettier --write --ignore-unknown"
}
}
如果你使用eslint,请确保lint-staged里,eslint的执行顺序放在前面
需要安装husky 和 lint-staged这两个依赖才能实现,其中husky是帮助我们添加git hooks的工具,而lint-staged则是筛选那些staged的git文件执行lint。
执行npx mrm lint-staged
就会把两个工具都安装好。
用注释忽略格式化代码
// prettier-ignore
注释会忽略抽象语法树下一行代码的格式化
举个例子
代码语言:javascript复制matrix(
1, 0, 0,
0, 1, 0,
0, 0, 1
)
// prettier-ignore
matrix(
1, 0, 0,
0, 1, 0,
0, 0, 1
)
执行prettier格式化后:
代码语言:javascript复制matrix(1, 0, 0, 0, 1, 0, 0, 0, 1);
// prettier-ignore
matrix(
1, 0, 0,
0, 1, 0,
0, 0, 1
)
JSX中的注释
代码语言:javascript复制<div>
{/* prettier-ignore */}
<span ugly format='' />
</div>
HTML中的注释
代码语言:javascript复制<!-- prettier-ignore -->
<div class="x" >hello world</div >
<!-- prettier-ignore-attribute -->
<div
(mousedown)=" onStart ( ) "
(mouseup)=" onEnd ( ) "
></div>
<!-- prettier-ignore-attribute (mouseup) -->
<div
(mousedown)="onStart()"
(mouseup)=" onEnd ( ) "
></div>
CSS中的注释
代码语言:javascript复制/* prettier-ignore */
.my ugly rule
{
}
MarkDown中的注释
代码语言:javascript复制<!-- prettier-ignore -->
Do not format this
忽略一定范围的代码
available in v1.12.0
通常实在文件顶部使用来取消一些自动生成内容的格式化
比如markdown里的toc和表格等
代码语言:javascript复制<!-- prettier-ignore-start -->
<!-- SOMETHING AUTO-GENERATED BY TOOLS - START -->
| MY | AWESOME | AUTO-GENERATED | TABLE |
|-|-|-|-|
| a | b | c | d |
<!-- SOMETHING AUTO-GENERATED BY TOOLS - END -->
<!-- prettier-ignore-end -->
YAML
代码语言:javascript复制# prettier-ignore
key : value
hello: world
GraphQL
代码语言:javascript复制{
# prettier-ignore
addReaction(input:{superLongInputFieldName:"MDU6SXNzdWUyMzEzOTE1NTE=",content:HOORAY}) {
reaction {content}
}
}
Handlebars
代码语言:javascript复制{{! prettier-ignore }}
<div>
"hello! my parent was ignored"
{{#my-crazy-component "shall" be="preserved"}}
<This
is = "also preserved as is"
/>
{{/my-crazy-component}}
</div>
03.使用配置文件进行配置
最推荐的使用方式是使用配置文件。
prettier支持的配置文件的优先级如下,它使用 cosmiconfig提供配置文件支持的:
- A
"prettier"
key in yourpackage.json
file. - A
.prettierrc
file written in JSON or YAML. - A
.prettierrc.json
,.prettierrc.yml
,.prettierrc.yaml
, or.prettierrc.json5
file. - A
.prettierrc.js
,.prettierrc.cjs
,prettier.config.js
, orprettier.config.cjs
file that exports an object usingmodule.exports
. - A
.prettierrc.toml
file.
这里我使用 .prettierrc.js
来配置,因为偏好json那种风格的配置文件,但是json有个最大的问题是不支持注释。所以我这里用了js,把每一项都写上了注释,方便以后改的时候查看。
vscode读取这种单独配置文件的优先级会高于插件内配置。
可配置选项
代码语言:javascript复制module.exports = {
// 1.一行代码的最大字符数,默认是80(printWidth: <int>)
printWidth: 80,
// 2.tab宽度为2空格(tabWidth: <int>)
tabWidth: 2,
// 3.是否使用tab来缩进,我们使用空格(useTabs: <bool>)
useTabs: false,
// 4.结尾是否添加分号,false的情况下只会在一些导致ASI错误的其工况下在开头加分号,我选择无分号结尾的风格(semi: <bool>)
semi: false,
// 5.使用单引号(singleQuote: <bool>)
singleQuote: true,
// 6.object对象中key值是否加引号(quoteProps: "<as-needed|consistent|preserve>")as-needed只有在需求要的情况下加引号,consistent是有一个需要引号就统一加,preserve是保留用户输入的引号
quoteProps: 'as-needed',
// 7.在jsx文件中的引号需要单独设置(jsxSingleQuote: <bool>)
jsxSingleQuote: false,
// 8.尾部逗号设置,es5是尾部逗号兼容es5,none就是没有尾部逗号,all是指所有可能的情况,需要node8和es2017以上的环境。(trailingComma: "<es5|none|all>")
trailingComma: 'es5',
// 9.object对象里面的key和value值和括号间的空格(bracketSpacing: <bool>)
bracketSpacing: true,
// 10.jsx标签多行属性写法时,尖括号是否另起一行(jsxBracketSameLine: <bool>)
jsxBracketSameLine: false,
// 11.箭头函数单个参数的情况是否省略括号,默认always是总是带括号(arrowParens: "<always|avoid>")
arrowParens: 'always',
// 12.range是format执行的范围,可以选执行一个文件的一部分,默认的设置是整个文件(rangeStart: <int> rangeEnd: <int>)
rangeStart: 0,
rangeEnd: Infinity,
// 18. vue script和style标签中是否缩进,开启可能会破坏编辑器的代码折叠
vueIndentScriptAndStyle: false,
// 19. endOfLine: "<lf|crlf|cr|auto>" 行尾换行符,默认是lf,
endOfLine: 'lf',
// 20.embeddedLanguageFormatting: "off",默认是auto,控制被引号包裹的代码是否进行格式化
embeddedLanguageFormatting: 'off',
}
// 14. requirePragma: <bool>,格式化有特定开头编译指示的文件 比如下面两种
/**
* @prettier
*/
// or
/**
* @format
*/
// 15.insertPragma: <bool> 自当插入pragma到已经完成的format的文件开头
// 16. proseWrap: "<always|never|preserve>" 文章换行,默认情况下会对你的markdown文件换行进行format会控制在printwidth以内
// 13. 指定parser,因为pretter会自动选择,所以一般不用指定(parser: "<string>" parser: require("./my-parser"))
// "babel" (via @babel/parser) Named "babylon" until v1.16.0
// "babel-flow" (same as "babel" but enables Flow parsing explicitly to avoid ambiguity) First available in v1.16.0
// "babel-ts" (similar to "typescript" but uses Babel and its TypeScript plugin) First available in v2.0.0
// "flow" (via flow-parser)
// "typescript" (via @typescript-eslint/typescript-estree) First available in v1.4.0
// "espree" (via espree) First available in v2.2.0
// "meriyah" (via meriyah) First available in v2.2.0
// "css" (via postcss-scss and postcss-less, autodetects which to use) First available in v1.7.1
// "scss" (same parsers as "css", prefers postcss-scss) First available in v1.7.1
// "less" (same parsers as "css", prefers postcss-less) First available in v1.7.1
// "json" (via @babel/parser parseExpression) First available in v1.5.0
// "json5" (same parser as "json", but outputs as json5) First available in v1.13.0
// "json-stringify" (same parser as "json", but outputs like JSON.stringify) First available in v1.13.0
// "graphql" (via graphql/language) First available in v1.5.0
// "markdown" (via remark-parse) First available in v1.8.0
// "mdx" (via remark-parse and @mdx-js/mdx) First available in v1.15.0
// "html" (via angular-html-parser) First available in 1.15.0
// "vue" (same parser as "html", but also formats vue-specific syntax) First available in 1.10.0
// "angular" (same parser as "html", but also formats angular-specific syntax via angular-estree-parser) First available in 1.15.0
// "lwc" (same parser as "html", but also formats LWC-specific syntax for unquoted template attributes) First available in 1.17.0
// "yaml" (via yaml and yaml-unist-parser) First available in 1.14.0
// 17. htmlWhitespaceSensitivity: "<css|strict|ignore>" html中的空格敏感性
// 针对不同文件或目录设置不同配置的方法,json格式例子
// {
// "semi": false,
// "overrides": [
// {
// "files": "*.test.js",
// "options": {
// "semi": true
// }
// },
// {
// "files": ["*.html", "legacy/**/*.js"],
// "options": {
// "tabWidth": 4
// }
// }
// ]
// }
下面是精简版本,默认配置在我这里需要修改的只有两个选项
- semi,行末是否加分号,有以下几个原因让我选择false
- 我主要使用的vue他的代码风格就是不加分号的,不加分号代码也能正常运行(因为编译器是自动给你加分号执行的),只需要注意几个会出问题的点。
- 加分号会增加文件大小,写代码和删代码都需要多按麻烦
- 我常用的其他语言,比如go,python和powershell也可以不用分号
- 使用单引号而不是双引号,同理,vue的代码风格使用的是单引号,很多js代码风格都是使用单引号
module.exports = {
semi: false,
singleQuote: true,
}
关于js使用单引号的好处,为什么不用双引号
- 首先,双引号其实是c语言(类c 的java,c#都是这样)带来的强迫症,c语言用单引号表示单个字符,双引号表示字符串,c语言区分这两个我猜是因为要斤斤计较内存的使用的缘故,编译的时候给单个字符内存分配和给字符串内存分配的占用是不同的。但是在js,python这些语言里面,单引号双引号都可以用字符串,就没必要一定遵循这个强迫症了。
- shell和powershell这两种语言里面用单引号表示纯字符串,双引号则是可以添加变量的字符串。因为这两种脚本也是比较常用的,为了统一,干脆所有字符串统一用单引号,双引号留着都不用,比如powershell脚本里面我也不用双引号,而是用format来格式化字符串。
- 用单引号可以少按一个shift,方便一些
- html中用的是双引号,所以js区分一下,用单引号。
其他默认的配置符合我使用习惯的也有可以讨论的:
关于tab用几个空格的讨论我选择用两个空格。
一般两个空格就是最小的缩进了,2个空格和4个空格应该是主流的两种。在前端项目里面一般是两个空格。有以下的原因吧:
- js语言回调函数之类嵌套的场景比较多,如果用4空格缩进会占用过多的空间,2空格就比较紧凑。
- 2空格输入和删除都更方便(虽然我都是用tab输出2空格),方便修改
缺点也是比较紧凑,看着容易累。
针对特定文件覆盖配置
把官方的例子搬了过来。这样就能针对不同文件进行配置了。
代码语言:javascript复制{
"semi": false,
"overrides": [
{
"files": "*.test.js",
"options": {
"semi": true
}
},
{
"files": ["*.html", "legacy/**/*.js"],
"options": {
"tabWidth": 4
}
}
]
}