Astro v2の環境でESLint・Stylelintの導入を行う
Astro v2の環境でESLint・Stylelintを入れた際に少し躓いたので、対応したことを記載します。
結論
以下を実行・コードを記載して対応しました。
パッケージ追加したコマンド
yarn add -D @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint eslint-plugin-astro eslint-plugin-import postcss-html prettier prettier-plugin-astro stylelint-config-recess-order stylelint-declaration-block-no-ignored-properties stylelint-no-unsupported-browser-features stylelint-prettier stylelint-scss
今回追加したパッケージのバージョン
執筆時点(2023/2/19時点)での最新バージョンです。
- "astro": "^2.0.2",
- "@typescript-eslint/eslint-plugin": "^5.52.0",
- "@typescript-eslint/parser": "^5.52.0",
- "eslint": "^8.34.0",
- "eslint-plugin-astro": "^0.23.0",
- "eslint-plugin-import": "^2.27.5",
- "postcss-html": "^1.5.0",
- "prettier": "^2.8.3",
- "prettier-plugin-astro": "^0.8.0",
- "stylelint": "^15.1.0",
- "stylelint-config-recess-order": "^4.0.0",
- "stylelint-declaration-block-no-ignored-properties": "^2.7.0",
- "stylelint-no-unsupported-browser-features": "^6.1.0",
- "stylelint-prettier": "^2.0.0",
- "stylelint-scss": "^4.4.0",
ファイル群
.eslintrc.cjs
module.exports = {
ignorePatterns: ['*.d.ts'],
extends: ['eslint:recommended', 'plugin:import/typescript', 'plugin:astro/recommended'],
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
project: './tsconfig.json',
},
globals: {
astroHTML: true,
},
plugins: ['@typescript-eslint', 'import'],
rules: {
'@typescript-eslint/consistent-type-imports': [
2,
{
prefer: 'type-imports',
},
],
'import/order': [2, { alphabetize: { order: 'asc' } }],
},
overrides: [
{
// Define the configuration for `.astro` file.
files: ['*.astro'],
// Allows Astro components to be parsed.
parser: 'astro-eslint-parser',
// Parse the script in `.astro` as TypeScript by adding the following configuration.
// It's the setting you need when using TypeScript.
parserOptions: {
parser: '@typescript-eslint/parser',
extraFileExtensions: ['.astro'],
},
rules: {
// override/add rules settings here, such as:
'astro/no-set-html-directive': 'error',
},
},
{
files: ['*.ts'],
parser: '@typescript-eslint/parser',
},
],
}
.prettierrc
{
"semi": false,
"arrowParens": "always",
"printWidth": 120,
"tabWidth": 2,
"useTabs": false,
"singleQuote": true,
"proseWrap": "preserve"
}
stylelint.config.cjs
module.exports = {
// add your custom config here
// https://stylelint.io/user-guide/configuration
customSyntax: 'postcss-html',
plugins: [
'stylelint-scss',
'stylelint-declaration-block-no-ignored-properties',
'stylelint-no-unsupported-browser-features',
'stylelint-prettier',
],
extends: ['stylelint-config-recess-order'],
rules: {
'prettier/prettier': true,
'plugin/declaration-block-no-ignored-properties': true,
'plugin/no-unsupported-browser-features': [
true,
{
severity: 'warning',
},
],
'font-family-no-missing-generic-family-keyword': true,
'declaration-block-no-shorthand-property-overrides': true,
'selector-pseudo-element-colon-notation': 'double',
},
}
コマンド
{
scripts: {
"format": "prettier --write **/*.{css,scss,ts,tsx,astro}",
"lint:js": "eslint \"./src/**/*.{js,jsx,ts,tsx,astro}\" --fix --ignore-path .gitignore",
"lint:style": "stylelint \"./src/**/*.{css,scss,astro}\" --fix --ignore-path .gitignore",
}
}
今回設定した内容について
1. Prettierの追加
Prettierの追加については、公式のドキュメントでのやり方で問題なく行うことができました。
2. ESLintの追加
2-1. 公式の導入方法に基づいて追加をしてみる
公式の通り以下のパッケージを追加し、.eslintrc.js
のファイルでコマンドを実行してみる
対応したこと
パッケージ追加
$ yarn add -D eslint eslint-plugin-astro @typescript-eslint/parser
module.exports = {
extends: [
"plugin:astro/recommended",
],
overrides: [
{
// Define the configuration for `.astro` file.
files: ["*.astro"],
// Allows Astro components to be parsed.
parser: "astro-eslint-parser",
// Parse the script in `.astro` as TypeScript by adding the following configuration.
// It's the setting you need when using TypeScript.
parserOptions: {
parser: "@typescript-eslint/parser",
extraFileExtensions: [".astro"],
},
rules: {
// override/add rules settings here, such as:
// "astro/no-set-html-directive": "error"
},
},
],
}
エラー内容
$ eslint "./src/**/*.{js,jsx,ts,tsx,astro}" --fix --ignore-path .gitignore
Oops! Something went wrong! :(
ESLint: 8.34.0
Error [ERR_REQUIRE_ESM]: require() of ES Module /.eslintrc.js from /node_modules/@eslint/eslintrc/dist/eslintrc.cjs not supported.
.eslintrc.js is treated as an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which declares all .js files in that package scope as ES modules.
Instead rename .eslintrc.js to end in .cjs, change the requiring code to use dynamic import() which is available in all CommonJS modules, or change "type": "module" to "type": "commonjs" in /package.json to treat all .js files as CommonJS (using .mjs for all ES modules instead).
at module.exports [as default] (/node_modules/import-fresh/index.js:32:59)
at loadJSConfigFile (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2562:47)
at loadConfigFile (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2646:20)
at ConfigArrayFactory.loadInDirectory (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2856:34)
at CascadingConfigArrayFactory._loadConfigInAncestors (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3848:46)
at CascadingConfigArrayFactory._loadConfigInAncestors (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3867:20)
at CascadingConfigArrayFactory.getConfigArrayForFile (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3769:18)
at FileEnumerator._iterateFilesRecursive (/node_modules/eslint/lib/cli-engine/file-enumerator.js:448:49)
at _iterateFilesRecursive.next (<anonymous>)
at FileEnumerator.iterateFiles (/node_modules/eslint/lib/cli-engine/file-enumerator.js:299:49)
at iterateFiles.next (<anonymous>)
at CLIEngine.executeOnFiles (/node_modules/eslint/lib/cli-engine/cli-engine.js:786:48)
at ESLint.lintFiles (/node_modules/eslint/lib/eslint/eslint.js:551:23)
at Object.execute (/node_modules/eslint/lib/cli.js:417:36)
at async main (/node_modules/eslint/bin/eslint.js:135:24)
error Command failed with exit code 2.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
.eslintrc.cjs
に変更して再度実行してみる
2-2. 「2-1」でのエラー内容が以下のため、.eslintrc.js
から.eslintrc.cjs
に変更して、再度Lintの実行をしてみる。
Error [ERR_REQUIRE_ESM]: require() of ES Module /.eslintrc.js from /node_modules/@eslint/eslintrc/dist/eslintrc.cjs not supported.
.eslintrc.js is treated as an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which declares all .js files in that package scope as ES modules.
Instead rename .eslintrc.js to end in .cjs, change the requiring code to use dynamic import() which is available in all CommonJS modules, or change "type": "module" to "type": "commonjs" in /package.json to treat all .js files as CommonJS (using .mjs for all ES modules instead).
変更した結果以下のようになったため、これでESLintを使用することができるようになりました。
$ eslint "./src/**/*.{js,jsx,ts,tsx,astro}" --fix --ignore-path .gitignore
✨ Done in 2.52s.
2-3. TypeScriptでのエラーが出るため、TSファイルの設定を行う
独自の型定義ファイルやTSファイルがある場合Lintがエラーになってしまうため、TypeScriptファイルでもLintが実行されるようにします。
TSファイル
declare module 'astro-imagetools/components'
export const hello = (name: string): string => {
return `Hello,${name}!`
}
エラー内容
$ eslint "./src/**/*.{js,jsx,ts,tsx,astro}" --fix --ignore-path .gitignore
/src/astro-imagetools.d.ts
1:9 error Parsing error: Unexpected token module
/src/utils/hello.ts
1:27 error Parsing error: Unexpected token :
対応したこと
.ts
ファイルについては、以下を参考に@typescript-eslint/parser
を追加。
module.exports = {
overrides: [
{
files: ['*.ts'],
parser: '@typescript-eslint/parser',
},
]
}
.d.ts
については、特に確認したい内容もなかったため、ignorePatterns
にてESLintのルールを無視するようにしました。
module.export = {
ignorePatterns: ['*.d.ts'],
}
上記の設定を行うことでLintが通るようになりました。
$ eslint "./src/**/*.{js,jsx,ts,tsx,astro}" --fix --ignore-path .gitignore
✨ Done in 2.30s.
2-4. ESLintのルール・パッケージの一部を追加
consistent-type-imports
のESLintルールとeslint-plugin-import
のパッケージも追加しました。
詳しい導入方法については過去に記載していますので、こちらをご覧ください。
3. Stylelintの追加
StylelintについてもESLintと同様、stylelint.config.js
だとESLintと同様のエラーが出たため、stylelint.config.cjs
で実行させたところ、問題なくうごきました。
3-1. 基本ルールの追加
$ yarn add -D stylelint stylelint-prettier stylelint-scss
module.exports = {
plugins: [
'stylelint-scss',
'stylelint-prettier',
],
rules: {
'prettier/prettier': true,
'font-family-no-missing-generic-family-keyword': true,
'declaration-block-no-shorthand-property-overrides': true,
'selector-pseudo-element-colon-notation': 'double',
},
}
追加しているルール
CssSyntaxError
のエラーが出るため、修正
3-2. 「3-1」で追加したLintルールで以下のエラーが出るため、customSyntax
のパッケージを追加
エラー内容・該当のファイル
$ stylelint './src/**/*.{css,scss,astro}' --fix --ignore-path .gitignore
/src/styles/style.scss: you should use the "customSyntax" option when linting something other than CSS
/src/pages/index.astro: you should use the "customSyntax" option when linting something other than CSS
src/pages/index.astro
2:10 ✖ Unknown word CssSyntaxError
src/styles/style.scss
2:1 ✖ Unknown word CssSyntaxError
src/pages/index.astro
---
import { SITE_TITLE, SITE_DESCRIPTION } from '~/consts'
import Layout from '~/layouts.astro'
import { hello } from '~/utils/hello'
---
<p>ページ情報</p>
<!-- その他HTMLの情報 -->
src/styles/style.scss
@forward 'setup';
// @forward 'check';
対応したこと
postcss-html
のパッケージをインストールして、customSyntax
にpostcss-html
を記載。
$ yarn add -D postcss-html
module.exports = {
customSyntax: 'postcss-html',
}
上記の設定を行うことでLintが通るようになりました。
$ stylelint './src/**/*.{css,scss,astro}' --fix --ignore-path .gitignore
✨ Done in 0.66s.
3-3. カスタムルールの追加
「3-2」まででStylelintを動かすことはできたため、一部パッケージやルールを追加していきます。
$ yarn add -D stylelint-config-recess-order stylelint-declaration-block-no-ignored-properties stylelint-no-unsupported-browser-features
今回追加したstylelint.config.cjs
module.exports = {
plugins: [
'stylelint-declaration-block-no-ignored-properties',
'stylelint-no-unsupported-browser-features',
],
extends: ['stylelint-config-recess-order'],
rules: {
'plugin/declaration-block-no-ignored-properties': true,
'plugin/no-unsupported-browser-features': [
true,
{
severity: 'warning',
},
],
},
}
全体のstylelint.config.cjs
module.exports = {
customSyntax: 'postcss-html',
plugins: [
'stylelint-scss',
'stylelint-declaration-block-no-ignored-properties',
'stylelint-no-unsupported-browser-features',
'stylelint-prettier',
],
extends: ['stylelint-config-recess-order'],
rules: {
'prettier/prettier': true,
'plugin/declaration-block-no-ignored-properties': true,
'plugin/no-unsupported-browser-features': [
true,
{
severity: 'warning',
},
],
'font-family-no-missing-generic-family-keyword': true,
'declaration-block-no-shorthand-property-overrides': true,
'selector-pseudo-element-colon-notation': 'double',
},
}
今回参考にしたもの
Discussion