Skip to content

Latest commit

 

History

History
927 lines (688 loc) · 30.2 KB

slides.md

File metadata and controls

927 lines (688 loc) · 30.2 KB
highlighter css colorSchema transition mdc layout glowSeed lang title monacoTypesIgnorePackages
shiki
unocss
dark
fade-out
true
center
4
zh-CN
ESLint One for All Made Easy
@antfu/install-pkg
@clack/prompts
@typescript-eslint/*
eslint-plugin-*
*-eslint-parser
find-up
parse-*
globals
pkg-types
mlly
local-pkg
yargs
fast-glob
debug
globby
estraverse
pathe
acorn
acorn-*
pico*
eslint-visitor-keys

{.w-30.mt--10.mb-5}


layout: intro glowSeed: 15 glowOpacity: 0.3 class: pl-30

Anthony Fu

Senior Frontend Linter at {NuxtLabs}

{Vite} {Vue} {Nuxt} 核心團隊成員

{Vitest} {Slidev} {UnoCSS} {VueUse} {Type Challenges} 作者

{ESLint Stylistic} {Shiki} {Twoslash} 維護者


layout: cover

ESLint One for All Made Easy
一統江湖
化繁為簡

WebConf Taiwan
2024 年 12 月 28 日

layout: center glow: bottom

ESLint v9.0.0 於 發布


layout: quote

🙋 聽說過 ESLint Flat Config 嗎?


layout: quote

🙋 用上 Flat Config 了嗎?


傳統設定檔 .eslintrc

  • 多種檔案來源 .eslintrc .eslintrc.js .eslintrc.json package.json
  • 基於約定的 extends
  • 基於 npm 包名的外掛系統
  • 繼承樹可能很複雜
// .eslintrc.json
{
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended"
  ],
  "plugins": [
    "vue",
    "n"
  ],
  "rules": {
    "vue/html-indent": ["error", 2]
  },
  "overrides": [
    // ...
  ]
}

扁平設定檔

  • 單一來源 eslint.config.js 或是 .cjs .mjs
    -
  • 基於 JS 原生的顯式匯入
  • 外掛系統基於匯入的對象 可以重命名外掛
  • 可組合,更容易追溯
// eslint.config.js
import typescript from '@eslint-typescript/eslint-plugin'
import eslint from '@eslint/js'
import n from 'eslint-plugin-n'
import vue from 'eslint-plugin-vue'

export default [ // 導出一個設定檔數組
  eslint.configs.recommended,
  ...typescript.configs.recommended,
  {
    plugins: {
      vue,
      node: n, // 重命名外掛
    },
    rules: {
      'vue/html-indent': ['error', 2]
    }
  },
  // ...
]

扁平設定檔推出時間線

  • RFC 於 2019 年 1 月創建
  • v8.21.0 中作為實驗性功能推出
  • v8.45.0 中變為穩定版
  • v9.0.0 中成為默認設定檔
  • JavaScript 檔案作為設定檔,具有完全控制權
  • 簡化的繼承和覆蓋
  • 靈活、動態、可定制

遷移工具 @eslint/migrate-config 官方

CLI 工具將舊設定檔轉換為扁平設定檔

npx @eslint/migrate-config .eslintrc.json
// .eslintrc.json
{
  "env": {
    "node": true,
    "es6": true
  },
  "parserOptions": {
    "ecmaVersion": 2020,
    "sourceType": "module"
  },
  "extends": [
    "eslint:recommended",
    "plugin:ava/recommended",
    "prettier"
  ],
  "plugins": ["prettier", "import"],
  "rules": {
    "prettier/prettier": 2,
    "ava/no-ignored-test-files": 0,
    "ava/no-import-test-files": 0,
    "import/no-unresolved": [
      2,
      {
        "ignore": ["ava", "got"]
      }
    ],
    "import/no-unused-modules": 2,
    "import/order": [
      2,
      {
        "newlines-between": "never"
      }
    ]
  }
}
// eslint.config.mjs
import { FlatCompat } from '@eslint/eslintrc'
import _import from 'eslint-plugin-import'
import prettier from 'eslint-plugin-prettier'

const compat = new FlatCompat()
export default [
  ...compat.extends(
    'eslint:recommended',
    'plugin:ava/recommended',
    'prettier'
  ),
  {
    plugins: {
      prettier,
      import: _import,
    },
    languageOptions: {
      ecmaVersion: 2020,
      sourceType: 'module',
    },
    rules: {
      'prettier/prettier': 2,
      'ava/no-ignored-test-files': 0,
      'ava/no-import-test-files': 0,

      'import/no-unresolved': [2, {
        ignore: ['ava', 'got'],
      }],
      'import/no-unused-modules': 2,
      'import/order': [2, {
        'newlines-between': 'never',
      }],
    },
  },
]

layout: fact

One for All{.important-text-3em}

一個設定檔適配各種不同的專案


舊設定檔

{
  "extends": [
    "@antfu/eslint-config",
    "@antfu/eslint-config-ts",
    "@antfu/eslint-config-vue",
    "@antfu/eslint-config-vue-ts"
    // ...需要提供所有的組合
  ],
  "rules": {
    // 為了修改一項設定檔需要非常的多的手動覆蓋
    "indent": ["error", 4],
    "@typescript-eslint/indent": ["error", 4],
    "jsx-indent": ["error", 4],
    "vue/indent": ["error", 4]
  }
}

扁平設定檔

import antfu from '@antfu/eslint-config'

export default antfu({
  vue: true,
  typescript: true,
  stylistic: {
    indent: 4
  }
  // ...
})
設定檔可以接受高階用戶選項
一個設定檔適用於所有專案
像 Prettier 一樣提供最小設定檔,開箱即用
同時擁有 ESLint 完整靈活的可自定義能力

layout: fact

工具生態{.important-text-3em}

隨著新的 Flat Config 帶來的新工具和可能性


Flat Config Utils 社區

import eslint from '@eslint/js'
import unocss from '@unocss/eslint-plugin'
import vue from 'eslint-plugin-vue'
import typescript from 'typescript-eslint'

export default [
  eslint.configs.recommended,
  ...typescript.configs.recommand,
  ...await unocss(),
  {
    files: ['*.vue'],
    ...vue.configs['vue3-recommand'],
    rules: {
      ...vue.configs['vue3-recommand'].rules,
      'vue/html-indent': ['error', 2]
    }
  }
]
import eslint from '@eslint/js'
import unocss from '@unocss/eslint-plugin'
import { compose } from 'eslint-flat-config-utils'
import vue from 'eslint-plugin-vue'
import typescript from 'typescript-eslint'

export default compose(
  eslint.configs.recommended,
  typescript.configs.recommand, // 數組,自動解構
  unocss() // 自動解析 Promise
)
  .append( // 可鏈式擴展
    vue.configs['vue3-recommand']
  )
  // 使用名稱或索引覆蓋任何設定檔
  .override('vue', {
    files: ['*.vue'],
    rules: {
      'vue/html-indent': ['error', 2]
    }
  })

ESLint Typegen 社區

{.w-200.rounded-lg.shadow.border.border-main}


glow: left

Config Inspector 官方

eslint --inspect-config
  • 設定檔可視化
  • 理解設定檔組合
  • 內置設定檔
  • 檔案路徑測試器

<<< ./eslint.demo.config.ts {monaco-write}{height:'220px'}

import antfu from '@antfu/eslint-config'

專案感知的設定檔

例子:
Nuxt ESLint
// 由 Nuxt 根據當前專案的設定檔生成
import withNuxt from './.nuxt/eslint.config.mjs'

export default withNuxt(
  // 你的其他自定義設定檔
)

layout: fact

ESLint 不只是一個 Linter{.important-text-3em}

他還是一個成熟且強大的 AST 工具包

ESLint 也可以是... 格式化工具

集合了風格相關的 ESLint 規則。
格式化和 Lint 一步到位。

eslint.style

VS Code 中的設定檔
{
  // 在保存時自動修覆
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit"
  },

  // 在編輯器中靜默錯誤顯示,但仍然應用自動修覆
  "eslint.rules.customizations": [
    { "rule": "@stylistic/*", "severity": "off" }
  ]
}

ESLint 也可以是... 遷移工具 Codemod


ESLint 也可以是... 多種語言的 Linter

語言 外掛 維護者
Markdown @eslint/markdown {@eslint}
CSS @eslint/css {@eslint}
TypeScript @typescript-eslint {@typescript-eslint} {@bradzacher} {@JoshuaKGoldberg}
Vue eslint-plugin-vue {@ota-meshi} {@vuejs}
Svelte eslint-plugin-svelte {@ota-meshi} {@sveltejs}
Astro eslint-plugin-astro {@ota-meshi}
JSON eslint-plugin-jsonc {@ota-meshi}
YAML eslint-plugin-yml {@ota-meshi}
TOML eslint-plugin-toml {@ota-meshi}
GraphQL graphql-eslint {@dimaMachina}
HTML html-eslint {@yeonjuan}
MDX eslint-mdx {@JounQin}
其他格式 eslint-plugin-format {@antfu}

layout: fact

One for All{.important-text-3em}

一個設定檔適配 所有 專案
一個工具適配 所有 需求

class: "grid grid-cols-[1fr_1fr] p0 h-full" clicks: 1 glow: left

4.1k

@antfu/eslint-config

代碼風格

安裝向導

npx @antfu/eslint-config@latest

特性

  • 自動修覆格式 旨在獨立使用,無需 Prettier
  • 合理的默認設置,最佳實踐,只需一行設定檔
  • 支持 TypeScript、JSX、Vue、JSON、YAML、Toml、Markdown,開箱即用
  • 帶有強主見,但高度可定制
  • 輕松組合通過 Flat Config 進行組合
  • 可選支持 React、Svelte、UnoCSS、Astro、Solid
  • 可選格式化器支持格式化 CSS、HTML、XML 等
  • 風格原則:閱讀最簡,穩定 diff,一致性
    • 排序的匯入,尾隨逗號
    • 單引號,無分號
    • 使用 ESLint Stylistic
  • 默認尊重 .gitignore

layout: intro class: text-center pb-5 glowX: 50 glowY: 120

謝謝

投影片在 antfu.me