---
title: "ESLint 9.x Flat ConfigとStylelintをVitePressに導入する完全ガイド"
created: "2026-01-09"
status: "published"
description: "VitePressサイトにESLint 9.x Flat ConfigとStylelintを導入した実践ガイドです。TypeScript/JavaScript混在環境での設定方法、GitHub Actions CI/CD自動化、つまづきポイントと解決策を具体的なコード付きで解説します。"
platforms:
wordpress:
published: true
url: "https://wakatchi.dev/eslint-stylelint-vitepress-guide/"
published_date: "2026-03-13"
post_id: 2565
category: "infrastructure/ci-cd"
tags:
- "ESLint 9"
- "Flat Config"
- "Stylelint"
- "TypeScript"
- "GitHub Actions"
- "CI/CD"
- "VitePress"
seo:
focus_keywords:
- "ESLint 9.x Flat Config"
- "ESLint TypeScript JavaScript 混在"
- "Stylelint VitePress"
canonical_url: ""
og_image: ""
x:
published: true
published_date: "2026-03-13"
schema:
"@context": "https://schema.org"
"@type": "Article"
headline: "ESLint 9.x Flat ConfigとStylelintをVitePressに導入する完全ガイド"
description: "VitePressサイトにESLint 9.x Flat ConfigとStylelintを導入した実践ガイドです。TypeScript/JavaScript混在環境での設定方法、GitHub Actions CI/CD自動化、つまづきポイントと解決策を解説します。"
datePublished: "2026-01-09"
dateModified: "2026-03-13"
author:
"@type": "Person"
name: "著者名"
publisher:
"@type": "Organization"
name: "Tech Blog"
mainEntityOfPage:
"@type": "WebPage"
"@id": ""
---

# ESLint 9.x Flat ConfigとStylelintをVitePressに導入する完全ガイド
VitePressで構築した静的サイトに**ESLint 9.x**と**Stylelint**を導入しました。
ESLint 9.xから採用された新しい**Flat Config形式**を採用し、TypeScript/JavaScript/CSSのLint環境を整備しています。
また、GitHub ActionsでCI/CD自動Lintを実現し、コード品質の向上と一貫性のあるコードスタイルの維持を目指しました。
本記事では、導入から設定、つまづきポイントまで、実際のコードを交えて詳しく解説します。
## こんな人におすすめ
この記事は、以下のような方におすすめです。
- **VitePressやVue.jsプロジェクトにLint環境を導入したい方**
- **ESLint 9.xの新しいFlat Config形式を知りたい方**
- **TypeScriptとJavaScriptが混在するプロジェクトでLint設定に悩んでいる方**
- **GitHub Actionsで自動Lintを構築したい方**
- **StylelintでCSSの品質管理を始めたい方**
## 目次
- [ESLint設定の全体像](#eslint設定の全体像)
- [ESLint 9.x Flat Configとは](#eslint-9x-flat-configとは)
- [TypeScript/JavaScript混在環境の設定](#typescriptjavascript混在環境の設定)
- [Stylelintの設定(VitePress対応)](#stylelintの設定vitepress対応)
- [GitHub Actions CI/CDパイプライン](#github-actions-cicdパイプライン)
- [つまづきポイントと解決策](#つまづきポイントと解決策)
- [得られた効果](#得られた効果)
- [よくある質問(FAQ)](#よくある質問faq)
- [まとめ](#まとめ)
## ESLint設定の全体像
今回構築したLint環境の構成を図で示します。
```mermaid
flowchart TD
subgraph ESLint
A[eslint.config.js] --> B[JavaScript Files]
A --> C[TypeScript Files]
A --> D[Cloudflare Functions]
B --> E[js.configs.recommended]
C --> F[tseslint.configs.recommended]
D --> G[Workers Globals]
end
subgraph Stylelint
H[.stylelintrc.js] --> I[CSS Files]
H --> J[Vue SFC]
end
subgraph CI/CD
K[GitHub Actions] --> L[ESLint]
K --> M[Stylelint]
K --> N[Tests]
end
```
## ESLint 9.x Flat Configとは
ESLint 9.xから導入された**Flat Config形式**(`eslint.config.js`)を使用しました。
従来の`.eslintrc.js`形式と比較して、以下のメリットがあります。
| 特徴 | 従来形式(.eslintrc.js) | Flat Config(eslint.config.js) |
|------|------------------------|-------------------------------|
| 記述形式 | JSON/YAML/JS | JavaScript(ESM)のみ |
| ファイルタイプ別設定 | overridesで記述 | files配列で簡潔に |
| 共有設定 | extendsで継承 | スプレッド構文で合成 |
| TypeScript対応 | 別途設定が必要 | ネイティブサポート向上 |
特に、`files`プロパティでファイルタイプごとに異なる設定を適用できるため、**TypeScriptとJavaScriptで別々のパーサーを使用する構成**が実現しやすくなっています。
### eslint.config.js(新規)
```javascript
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import vue from 'eslint-plugin-vue';
import globals from 'globals';
export default [
// Global ignores
{
ignores: [
'node_modules/**',
'docs/.vitepress/dist/**',
'docs/.vitepress/cache/**',
'dist/**',
'coverage/**',
'.wrangler/**',
'build/**'
]
},
// Base JavaScript rules
js.configs.recommended,
// JavaScript files (.mjs, .js)
{
files: ['**/*.mjs', '**/*.js'],
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
globals: { ...globals.node }
},
rules: {
'spaced-comment': ['error', 'always', { markers: ['/'] }],
'no-console': 'off',
'no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
'no-prototype-builtins': 'off'
}
},
// TypeScript configuration
...tseslint.configs.recommended.map(config => ({
...config,
files: ['**/*.ts', '**/*.mts']
})),
// TypeScript specific overrides
{
files: ['**/*.ts', '**/*.mts'],
languageOptions: {
parser: tseslint.parser,
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
project: null
},
globals: {
...globals.node,
...globals.browser
}
},
rules: {
'spaced-comment': ['error', 'always', { markers: ['/'] }],
'no-console': 'off',
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/require-await': 'off',
'no-prototype-builtins': 'off'
}
},
// Cloudflare Pages Functions
{
files: ['functions/**/*.ts'],
languageOptions: {
globals: {
...globals.node,
fetch: 'readonly',
Request: 'readonly',
Response: 'readonly',
Headers: 'readonly'
}
},
rules: { '@typescript-eslint/no-explicit-any': 'off' }
}
];
```
## TypeScript/JavaScript混在環境の設定
このプロジェクトでは、**TypeScript**(`.ts`, `.mts`)と**JavaScript**(`.js`, `.mjs`)が混在しています。
### つまづいた点
最初は`tseslint.configs.recommended`をグローバルに適用していましたが、これにより`.js`ファイルでも`@typescript-eslint`ルールが適用されてエラーが発生しました。
### 解決策
`files`プロパティで`.ts/.mts`ファイルのみにTypeScript設定を適用するように修正しました。
```mermaid
flowchart LR
A[ファイル検出] --> B{拡張子判定}
B -->|.ts / .mts| C[TypeScript Parser]
B -->|.js / .mjs| D[JavaScript Parser]
C --> E[tseslint.rules]
D --> F[js.configs.rules]
```
### 日本語コメントの保護
プロジェクトで日本語コメントを使用しているため、`spaced-comment`ルールに`markers: ['/']`オプションを指定して、日本語コメントを許可しています。
これにより、`// コメント`形式の日本語コメントがエラーにならず、コードの可読性を維持できます。
### Cloudflare Pages Functionsの対応
Cloudflare Workers環境では、`fetch`, `Request`, `Response`, `Headers`などのグローバル変数が利用可能です。
これらを`readonly`として設定することで、未使用変数警告を回避しています。
## Stylelintの設定(VitePress対応)
StylelintでCSSのLint設定を作成しました。
VitePressのカスタムプロパティや疑似クラス/疑似要素に対応するため、一部のルールを無効化しています。
### .stylelintrc.js(新規)
```javascript
export default {
extends: [
'stylelint-config-standard',
'stylelint-config-standard-vue'
],
rules: {
// VitePress対応
'custom-property-pattern': null,
'alpha-value-notation': null,
'color-function-notation': null,
'selector-class-pattern': null,
'selector-id-pattern': null,
'declaration-block-no-shorthand-property-overrides': null,
'selector-pseudo-class-no-unknown': [true, { ignorePseudoClasses: ['global', 'deep', 'slotted'] }],
'selector-pseudo-element-no-unknown': [true, { ignorePseudoElements: ['v-deep', 'v-global', 'v-slotted'] }],
'font-family-name-quotes': null,
'keyframes-name-pattern': null,
'unit-allowed-list': null,
// 日本語コメント対応
'comment-empty-line-before': null,
'comment-whitespace-inside': null,
'declaration-empty-line-before': null,
// VitePressオーバーライド用
'declaration-no-important': null,
'no-duplicate-selectors': null,
'max-empty-lines': 2
},
ignoreFiles: [
'node_modules/**',
'docs/.vitepress/dist/**',
'coverage/**',
'**/*.min.css'
]
};
```
## GitHub Actions CI/CDパイプライン
GitHub ActionsでCI/CDパイプラインを作成しました。
プッシュ時とPR時に自動的にLintが実行されます。
### CI/CDフロー
```mermaid
flowchart LR
A[Push / PR] --> B[Checkout]
B --> C[Setup Node.js]
C --> D[npm ci]
D --> E[ESLint]
D --> F[Stylelint]
D --> G[Tests]
E --> H{全てPass?}
F --> H
G --> H
H -->|Yes| I[✅ Success]
H -->|No| J[❌ Fail]
```
### .github/workflows/lint.yml(新規)
```yaml
name: Lint
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run ESLint
run: npm run lint:js
- name: Run Stylelint
run: npm run lint:css
- name: Run tests
run: npm test
```
### package.json(変更)
Lintスクリプトと依存パッケージを追加しました。
```diff
{
"scripts": {
+ "lint": "npm run lint:js && npm run lint:css",
+ "lint:fix": "npm run lint:js:fix && npm run lint:css:fix",
+ "lint:js": "eslint .",
+ "lint:js:fix": "eslint . --fix",
+ "lint:css": "stylelint \"**/*.css\"",
+ "lint:css:fix": "stylelint \"**/*.css\" --fix"
},
"devDependencies": {
+ "@eslint/js": "^9.39.2",
+ "eslint": "^9.39.2",
+ "eslint-plugin-vue": "^10.6.2",
+ "globals": "^17.0.0",
+ "postcss": "^8.5.6",
+ "postcss-html": "^1.8.0",
+ "stylelint": "^16.26.1",
+ "stylelint-config-standard": "^39.0.1",
+ "stylelint-config-standard-vue": "^1.0.0",
+ "typescript-eslint": "^8.52.0"
}
}
```
### package-lock.jsonの重要性
GitHub Actionsのnpm cache機能を使用するには、`package-lock.json`がリポジトリに含まれている必要があります。
`.gitignore`から除外すると、`npm ci`実行時に「Dependencies lock file is not found」エラーが発生します。
ロックファイルは依存関係の再現性を保証するため、**バージョン管理に含めることが推奨**されます。
### .gitignore(変更)
```diff
# 依存関係
node_modules/
-package-lock.json
yarn.lock
pnpm-lock.yaml
```
## つまづきポイントと解決策
### Lint警告の修正(複数ファイル)
未使用のインポートと変数を修正しました。
**docs/.vitepress/config.mts**:
```diff
- import { loadEnv } from 'vite'
```
**docs/.vitepress/theme/index.ts**:
```diff
- import { useRouter } from 'vitepress'
```
**docs/.vitepress/theme/language-persistence.ts**:
```diff
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
if ((window as any).__VITEPRESS__?.router) {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
- (window as any).__VITEPRESS__.router.onAfterRouteChange?.((to: any) => {
+ (window as any).__VITEPRESS__.router.onAfterRouteChange?.((_to: any) => {
updateLanguageCookie();
});
}
```
**functions/__tests__/middleware.test.ts**:
```diff
- import { describe, it, expect, beforeEach, vi } from 'vitest';
+ import { describe, it, expect } from 'vitest';
- const acceptLanguage = 'en-US';
- const country = 'JP';
+ const _acceptLanguage = 'en-US';
+ const _country = 'JP';
```
**scripts/generate-roadmap.js**:
```diff
- for (const [key, status] of Object.entries(statuses)) {
+ for (const [_key, status] of Object.entries(statuses)) {
```
## 得られた効果
今回のLint導入によって、以下の効果が得られました。
### 定量的な効果
| 項目 | 導入前 | 導入後 |
|------|--------|--------|
| 未使用変数の検出 | 手動のみ | 自動検出(12件修正) |
| CIでの品質チェック | なし | プッシュ時自動実行 |
| コードスタイルの一貫性 | 個人依存 | ルールベースで統一 |
### 定性的な効果
- **レビュー負荷の軽減**: スタイル指摘が自動化され、本質的なコードレビューに集中できるようになりました
- **新規参加者のオンボーディング**: ルールが明文化されることで、チームメンバーがコードスタイルをすぐに理解できるようになりました
- **心理的安全性の向上**: CIで自動チェックされるため、スタイル指摘が個人的なものではなくなりました
## よくある質問(FAQ)
### ESLint 9.x Flat Configで、従来のextendsは使えますか?
いいえ、Flat Configでは`extends`は使用できません。
代わりに、設定オブジェクトをスプレッド構文(`...`)で合成します。
```javascript
// 従来の書き方(Flat Configでは使えない)
module.exports = {
extends: ['eslint:recommended']
};
// Flat Configでの書き方
import js from '@eslint/js';
export default [
...js.configs.recommended
];
```
### TypeScriptとJavaScriptで異なるパーサーを指定するには?
`files`プロパティで対象ファイルを絞り込み、それぞれの設定で`languageOptions.parser`を指定します。
```javascript
export default [
// JavaScript用
{
files: ['**/*.js'],
languageOptions: { ecmaVersion: 'latest' }
},
// TypeScript用
{
files: ['**/*.ts'],
languageOptions: { parser: tseslint.parser }
}
];
```
### 日本語コメントがエラーになるのはなぜ?
`spaced-comment`ルールが`// 日本語`のような形式を許可しないためです。
以下のオプションで解決できます。
```javascript
'spaced-comment': ['error', 'always', { markers: ['/'] }]
```
### GitHub Actionsでnpm ciが失敗するのはなぜ?
`package-lock.json`がリポジトリに含まれていない可能性があります。
`.gitignore`から`package-lock.json`を削除し、コミットしてください。
### StylelintでVueのSFCスタイルをLintするには?
`stylelint-config-standard-vue`をextendsに追加し、`postcss-html`をインストールします。
```javascript
export default {
extends: ['stylelint-config-standard', 'stylelint-config-standard-vue']
};
```
## まとめ
VitePressサイトへの**ESLint 9.x Flat Config**と**Stylelint**導入について解説しました。
Flat Config形式を活用することで、**TypeScript/JavaScript混在環境でも柔軟な設定が可能**です。
また、GitHub Actionsと組み合わせることで、**コード品質を自動的に維持できる仕組み**を構築できました。
特に印象的だったのは、TypeScriptとJavaScriptで別々のパーサーを適用する設定が、Flat Config形式のおかげでシンプルに記述できた点です。
これからLint環境を構築される方は、ぜひ**ESLint 9.x Flat Config形式**を試してみてください。

ESLint 9.x Flat ConfigとStylelintをVitePressに導入する完全ガイド
VitePressで構築した静的サイトにESLint 9.xとStylelintを導入しました。
ESLint 9.xから採用された新しいFlat Config形式を採用し、TypeScript/JavaScript/CSSのLint環境を整備しています。
また、GitHub ActionsでCI/CD自動Lintを実現し、コード品質の向上と一貫性のあるコードスタイルの維持を目指しました。
本記事では、導入から設定、つまづきポイントまで、実際のコードを交えて詳しく解説します。
こんな人におすすめ
この記事は、以下のような方におすすめです。
- VitePressやVue.jsプロジェクトにLint環境を導入したい方
- ESLint 9.xの新しいFlat Config形式を知りたい方
- TypeScriptとJavaScriptが混在するプロジェクトでLint設定に悩んでいる方
- GitHub Actionsで自動Lintを構築したい方
- StylelintでCSSの品質管理を始めたい方
目次
ESLint設定の全体像
今回構築したLint環境の構成を図で示します。
flowchart TD
subgraph ESLint
A[eslint.config.js] --> B[JavaScript Files]
A --> C[TypeScript Files]
A --> D[Cloudflare Functions]
B --> E[js.configs.recommended]
C --> F[tseslint.configs.recommended]
D --> G[Workers Globals]
end
subgraph Stylelint
H[.stylelintrc.js] --> I[CSS Files]
H --> J[Vue SFC]
end
subgraph CI/CD
K[GitHub Actions] --> L[ESLint]
K --> M[Stylelint]
K --> N[Tests]
end
ESLint 9.x Flat Configとは
ESLint 9.xから導入されたFlat Config形式(eslint.config.js)を使用しました。
従来の.eslintrc.js形式と比較して、以下のメリットがあります。
| 特徴 |
従来形式(.eslintrc.js) |
Flat Config(eslint.config.js) |
| 記述形式 |
JSON/YAML/JS |
JavaScript(ESM)のみ |
| ファイルタイプ別設定 |
overridesで記述 |
files配列で簡潔に |
| 共有設定 |
extendsで継承 |
スプレッド構文で合成 |
| TypeScript対応 |
別途設定が必要 |
ネイティブサポート向上 |
特に、filesプロパティでファイルタイプごとに異なる設定を適用できるため、TypeScriptとJavaScriptで別々のパーサーを使用する構成が実現しやすくなっています。
eslint.config.js(新規)
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import vue from 'eslint-plugin-vue';
import globals from 'globals';
export default [
// Global ignores
{
ignores: [
'node_modules/**',
'docs/.vitepress/dist/**',
'docs/.vitepress/cache/**',
'dist/**',
'coverage/**',
'.wrangler/**',
'build/**'
]
},
// Base JavaScript rules
js.configs.recommended,
// JavaScript files (.mjs, .js)
{
files: ['**/*.mjs', '**/*.js'],
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
globals: { ...globals.node }
},
rules: {
'spaced-comment': ['error', 'always', { markers: ['/'] }],
'no-console': 'off',
'no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
'no-prototype-builtins': 'off'
}
},
// TypeScript configuration
...tseslint.configs.recommended.map(config => ({
...config,
files: ['**/*.ts', '**/*.mts']
})),
// TypeScript specific overrides
{
files: ['**/*.ts', '**/*.mts'],
languageOptions: {
parser: tseslint.parser,
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
project: null
},
globals: {
...globals.node,
...globals.browser
}
},
rules: {
'spaced-comment': ['error', 'always', { markers: ['/'] }],
'no-console': 'off',
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/require-await': 'off',
'no-prototype-builtins': 'off'
}
},
// Cloudflare Pages Functions
{
files: ['functions/**/*.ts'],
languageOptions: {
globals: {
...globals.node,
fetch: 'readonly',
Request: 'readonly',
Response: 'readonly',
Headers: 'readonly'
}
},
rules: { '@typescript-eslint/no-explicit-any': 'off' }
}
];
TypeScript/JavaScript混在環境の設定
このプロジェクトでは、TypeScript(.ts, .mts)とJavaScript(.js, .mjs)が混在しています。
つまづいた点
最初はtseslint.configs.recommendedをグローバルに適用していましたが、これにより.jsファイルでも@typescript-eslintルールが適用されてエラーが発生しました。
解決策
filesプロパティで.ts/.mtsファイルのみにTypeScript設定を適用するように修正しました。
flowchart LR
A[ファイル検出] --> B{拡張子判定}
B -->|.ts / .mts| C[TypeScript Parser]
B -->|.js / .mjs| D[JavaScript Parser]
C --> E[tseslint.rules]
D --> F[js.configs.rules]
日本語コメントの保護
プロジェクトで日本語コメントを使用しているため、spaced-commentルールにmarkers: ['/']オプションを指定して、日本語コメントを許可しています。
これにより、// コメント形式の日本語コメントがエラーにならず、コードの可読性を維持できます。
Cloudflare Pages Functionsの対応
Cloudflare Workers環境では、fetch, Request, Response, Headersなどのグローバル変数が利用可能です。
これらをreadonlyとして設定することで、未使用変数警告を回避しています。
Stylelintの設定(VitePress対応)
StylelintでCSSのLint設定を作成しました。
VitePressのカスタムプロパティや疑似クラス/疑似要素に対応するため、一部のルールを無効化しています。
.stylelintrc.js(新規)
export default {
extends: [
'stylelint-config-standard',
'stylelint-config-standard-vue'
],
rules: {
// VitePress対応
'custom-property-pattern': null,
'alpha-value-notation': null,
'color-function-notation': null,
'selector-class-pattern': null,
'selector-id-pattern': null,
'declaration-block-no-shorthand-property-overrides': null,
'selector-pseudo-class-no-unknown': [true, { ignorePseudoClasses: ['global', 'deep', 'slotted'] }],
'selector-pseudo-element-no-unknown': [true, { ignorePseudoElements: ['v-deep', 'v-global', 'v-slotted'] }],
'font-family-name-quotes': null,
'keyframes-name-pattern': null,
'unit-allowed-list': null,
// 日本語コメント対応
'comment-empty-line-before': null,
'comment-whitespace-inside': null,
'declaration-empty-line-before': null,
// VitePressオーバーライド用
'declaration-no-important': null,
'no-duplicate-selectors': null,
'max-empty-lines': 2
},
ignoreFiles: [
'node_modules/**',
'docs/.vitepress/dist/**',
'coverage/**',
'**/*.min.css'
]
};
GitHub Actions CI/CDパイプライン
GitHub ActionsでCI/CDパイプラインを作成しました。
プッシュ時とPR時に自動的にLintが実行されます。
CI/CDフロー
flowchart LR
A[Push / PR] --> B[Checkout]
B --> C[Setup Node.js]
C --> D[npm ci]
D --> E[ESLint]
D --> F[Stylelint]
D --> G[Tests]
E --> H{全てPass?}
F --> H
G --> H
H -->|Yes| I[✅ Success]
H -->|No| J[❌ Fail]
.github/workflows/lint.yml(新規)
name: Lint
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run ESLint
run: npm run lint:js
- name: Run Stylelint
run: npm run lint:css
- name: Run tests
run: npm test
package.json(変更)
Lintスクリプトと依存パッケージを追加しました。
{
"scripts": {
+ "lint": "npm run lint:js && npm run lint:css",
+ "lint:fix": "npm run lint:js:fix && npm run lint:css:fix",
+ "lint:js": "eslint .",
+ "lint:js:fix": "eslint . --fix",
+ "lint:css": "stylelint \"**/*.css\"",
+ "lint:css:fix": "stylelint \"**/*.css\" --fix"
},
"devDependencies": {
+ "@eslint/js": "^9.39.2",
+ "eslint": "^9.39.2",
+ "eslint-plugin-vue": "^10.6.2",
+ "globals": "^17.0.0",
+ "postcss": "^8.5.6",
+ "postcss-html": "^1.8.0",
+ "stylelint": "^16.26.1",
+ "stylelint-config-standard": "^39.0.1",
+ "stylelint-config-standard-vue": "^1.0.0",
+ "typescript-eslint": "^8.52.0"
}
}
package-lock.jsonの重要性
GitHub Actionsのnpm cache機能を使用するには、package-lock.jsonがリポジトリに含まれている必要があります。
.gitignoreから除外すると、npm ci実行時に「Dependencies lock file is not found」エラーが発生します。
ロックファイルは依存関係の再現性を保証するため、バージョン管理に含めることが推奨されます。
.gitignore(変更)
# 依存関係
node_modules/
-package-lock.json
yarn.lock
pnpm-lock.yaml
つまづきポイントと解決策
Lint警告の修正(複数ファイル)
未使用のインポートと変数を修正しました。
docs/.vitepress/config.mts:
- import { loadEnv } from 'vite'
docs/.vitepress/theme/index.ts:
- import { useRouter } from 'vitepress'
docs/.vitepress/theme/language-persistence.ts:
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
if ((window as any).__VITEPRESS__?.router) {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
- (window as any).__VITEPRESS__.router.onAfterRouteChange?.((to: any) => {
+ (window as any).__VITEPRESS__.router.onAfterRouteChange?.((_to: any) => {
updateLanguageCookie();
});
}
functions/tests/middleware.test.ts:
- import { describe, it, expect, beforeEach, vi } from 'vitest';
+ import { describe, it, expect } from 'vitest';
- const acceptLanguage = 'en-US';
- const country = 'JP';
+ const _acceptLanguage = 'en-US';
+ const _country = 'JP';
scripts/generate-roadmap.js:
- for (const [key, status] of Object.entries(statuses)) {
+ for (const [_key, status] of Object.entries(statuses)) {
得られた効果
今回のLint導入によって、以下の効果が得られました。
定量的な効果
| 項目 |
導入前 |
導入後 |
| 未使用変数の検出 |
手動のみ |
自動検出(12件修正) |
| CIでの品質チェック |
なし |
プッシュ時自動実行 |
| コードスタイルの一貫性 |
個人依存 |
ルールベースで統一 |
定性的な効果
- レビュー負荷の軽減: スタイル指摘が自動化され、本質的なコードレビューに集中できるようになりました
- 新規参加者のオンボーディング: ルールが明文化されることで、チームメンバーがコードスタイルをすぐに理解できるようになりました
- 心理的安全性の向上: CIで自動チェックされるため、スタイル指摘が個人的なものではなくなりました
よくある質問(FAQ)
ESLint 9.x Flat Configで、従来のextendsは使えますか?
いいえ、Flat Configではextendsは使用できません。
代わりに、設定オブジェクトをスプレッド構文(...)で合成します。
// 従来の書き方(Flat Configでは使えない)
module.exports = {
extends: ['eslint:recommended']
};
// Flat Configでの書き方
import js from '@eslint/js';
export default [
...js.configs.recommended
];
TypeScriptとJavaScriptで異なるパーサーを指定するには?
filesプロパティで対象ファイルを絞り込み、それぞれの設定でlanguageOptions.parserを指定します。
export default [
// JavaScript用
{
files: ['**/*.js'],
languageOptions: { ecmaVersion: 'latest' }
},
// TypeScript用
{
files: ['**/*.ts'],
languageOptions: { parser: tseslint.parser }
}
];
日本語コメントがエラーになるのはなぜ?
spaced-commentルールが// 日本語のような形式を許可しないためです。
以下のオプションで解決できます。
'spaced-comment': ['error', 'always', { markers: ['/'] }]
GitHub Actionsでnpm ciが失敗するのはなぜ?
package-lock.jsonがリポジトリに含まれていない可能性があります。
.gitignoreからpackage-lock.jsonを削除し、コミットしてください。
StylelintでVueのSFCスタイルをLintするには?
stylelint-config-standard-vueをextendsに追加し、postcss-htmlをインストールします。
export default {
extends: ['stylelint-config-standard', 'stylelint-config-standard-vue']
};
まとめ
VitePressサイトへのESLint 9.x Flat ConfigとStylelint導入について解説しました。
Flat Config形式を活用することで、TypeScript/JavaScript混在環境でも柔軟な設定が可能です。
また、GitHub Actionsと組み合わせることで、コード品質を自動的に維持できる仕組みを構築できました。
特に印象的だったのは、TypeScriptとJavaScriptで別々のパーサーを適用する設定が、Flat Config形式のおかげでシンプルに記述できた点です。
これからLint環境を構築される方は、ぜひESLint 9.x Flat Config形式を試してみてください。