Prettier 使用指南

码农日常3小时前更新 Trunks
2 0 0

1、什么是 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 支持更多文件的格式化。

2、使用方法

安装

在项目中,安装到开发依赖上

Bash
npm install --save-dev --save-exact prettier

忽略不想格式化的文件

创建 .prettierignore 忽略你不希望格式化的文件,node_modules 是默认会被忽略的目录。

他的用法就类似于 .gitignore,下面是官方给的例子

.prettierignore
# Ignore artifacts:
build
coverage

命令行执行格式化

在项目中手动调用prettier命令行进行格式化

npx prettier --write .

提前查看会格式化哪些文件,不实际执行格式化

npx prettier --check .

实际使用过程中,还是直接用编辑器的插件的,设置成保存的时候执行格式化。

解决和 ESlint 的冲突

安装 eslint-config-prettier,这个插件会把eslint中可能导致冲突的规则关掉,这样两者就能兼容使用了。

git hooks

可以设置在git提交之前执行一次格式化 ( pre-commit hook ),这样我们仓库里的代码就都是格式化好的了。

只需要在package.json里面加入一些配置。

JSON
{
  "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 中的注释

React JSX
<div>
  {/* prettier-ignore */}
  <span ugly  format=' ' />
</div>

Html 中的注释

HTML
<!-- 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 中的注释

CSS
/* prettier-ignore */
.my  ugly rule
{

}

MarkDown 中的注释

Markdown
<!-- prettier-ignore -->
Do   not    format   this

忽略一定范围的代码

available in v1.12.0+

通常实在文件顶部使用来取消一些自动生成内容的格式化

比如 markdown 里的 toc 和表格等

Markdown
<!-- 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 中的注释

YAML
# prettier-ignore
key  : value
hello: world

GraphQL 中的注释

GraphQL
{
  # prettier-ignore
  addReaction(input:{superLongInputFieldName:"MDU6SXNzdWUyMzEzOTE1NTE=",content:HOORAY}) {
    reaction {content}
  }
}

Handlebars( JavaScript 的语义模板库 )中的注释

Handlebars
{{! prettier-ignore }}
<div>
  "hello! my parent was ignored"
  {{#my-crazy-component "shall" be="preserved"}}
    <This
      is = "also preserved as is"
    />
  {{/my-crazy-component}}
</div>

3、使用配置文件进行配置

最推荐的使用方式是使用配置文件。

prettier支持的配置文件的优先级如下,它使用 cosmiconfig提供配置文件支持的:

  • A "prettier" key in your package.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, or prettier.config.cjs file that exports an object using module.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
//       }
//     }
//   ]
// }

下面是精简版本,默认配置在我这里需要修改的只有两个选项

1、semi,行末是否加分号,有以下几个原因让我选择false

  • 我主要使用的vue他的代码风格就是不加分号的,不加分号代码也能正常运行( 因为编译器是自动给你加分号执行的 ),只需要注意几个会出问题的点。
  • 加分号会增加文件大小,写代码和删代码都需要多按麻烦
  • 我常用的其他语言,比如 Go,Python 和 PowerShell 也可以不用分号

2、使用单引号而不是双引号,同理,Vue 的代码风格使用的是单引号,很多 Js 代码风格都是使用单引号

JavaScript
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
      }
    }
  ]
}
© 版权声明

相关文章

暂无评论

暂无评论...