Open11

Astroの環境構築について

YoshinokiYoshinoki

とりあえずESLint、Stylelint、Prettier、Markuplintは入れておきたい。

やりたい・できたら嬉しいこと

  • 保存時の自動lint,format,インポート
  • importの補完
  • importの自動整列
  • React用のESLint設定追加
  • import時のディレクトリのエイリアス指定
  • CSS変数の補完
  • CSSプロパティの並べ替え
  • アクセシビリティの静的チェック
  • TypeScriptのルール調整

めっちゃ余裕があればhusky,lint-stagedでコミット前のチェックまで対応したい

YoshinokiYoshinoki

開発サーバーの設定

astro.config.mjs
export default defineConfig({
+  server: {
+    host: true, // 外部からのアクセスを可能にする
+    open: true  // サーバー起動時にブラウザを開く
+  },
});
YoshinokiYoshinoki

Reactインテグレーションの追加

npx astro add react

サンプルコンポーネントを追加してみる

import { useState } from "react";

function Counter() {
  // useStateを使用して状態変数を宣言。初期値は0。
  const [count, setCount] = useState(0);

  // ボタンがクリックされたときにカウントを増やす関数
  const handleClick = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={handleClick}>Increase Count</button>
    </div>
  );
}

export default Counter;

clientディレクティブをつけると動く。

---
import SampleReactComponent from '../components/SampleReactComponent';
---

<SampleReactComponent client:load/>

https://docs.astro.build/ja/guides/integrations-guide/react/

YoshinokiYoshinoki

MDXインテグレーションの追加

npx astro add mdx

.mdxのサンプルページを追加してみる

src/pages/mdx-sample.mdx
import SampleReactComponent from "../../components/SampleReactComponent"

# Hello, MDX! This is a paragraph in your MDX file. You can write regular
Markdown here and also use JSX components.

## Here's a React component

---

<SampleReactComponent client:load />

---

https://docs.astro.build/ja/guides/markdown-content/
https://docs.astro.build/ja/guides/integrations-guide/mdx/

YoshinokiYoshinoki

ESLintと各種ESLintプラグインの追加
https://ota-meshi.github.io/eslint-plugin-astro/user-guide/

npm i -D  eslint @eslint/js eslint-plugin-astro  eslint-plugin-jsx-a11y typescript-eslint eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-import eslint-plugin-unused-imports eslint-config-prettier globals
eslint.config.mjs
import jsEslint from '@eslint/js';
import eslintConfigPrettier from 'eslint-config-prettier';
import astroEslint from 'eslint-plugin-astro';
import importPlugin from 'eslint-plugin-import';
import reactEslint from 'eslint-plugin-react';
import reactHooksEslint from 'eslint-plugin-react-hooks';
import unusedImports from 'eslint-plugin-unused-imports';
import globals from 'globals';
import tsEslint from 'typescript-eslint';

export default [
	jsEslint.configs.recommended,
	...tsEslint.configs.recommended,
	...astroEslint.configs['flat/recommended'],
	...astroEslint.configs['flat/jsx-a11y-recommended'],
	reactEslint.configs.flat['jsx-runtime'],
	{
		languageOptions: {
			globals: {
				...globals.browser, // ブラウザのグローバル変数を追加
			},
		},
		plugins: {
			'react-hooks': reactHooksEslint,
			'unused-imports': unusedImports,
			import: importPlugin,
		},
		rules: {
			...reactHooksEslint.configs.recommended.rules, // React Hooks のルールを追加
			'unused-imports/no-unused-imports': 'error', // 未使用の import をエラーにする
			// _ で始まる変数は未使用でもエラーにしない (https://typescript-eslint.io/rules/no-unused-vars/#benefits-over-typescript)
			'@typescript-eslint/no-unused-vars': [
				'error',
				{
					args: 'all',
					argsIgnorePattern: '^_',
					caughtErrors: 'all',
					caughtErrorsIgnorePattern: '^_',
					destructuredArrayIgnorePattern: '^_',
					varsIgnorePattern: '^_',
					ignoreRestSiblings: true,
				},
			],
			'react/jsx-sort-props': 'error', // props の順番をソートする
			// import の順序を設定する
			'import/order': [
				'error',
				{
					groups: ['builtin', 'external', 'internal', ['parent', 'sibling', 'index'], 'object', 'type'],
					'newlines-between': 'always',
					pathGroupsExcludedImportTypes: ['builtin'],
					pathGroups: [
						{
							pattern: '@/components/**',
							group: 'internal',
							position: 'before',
						},
					],
					alphabetize: {
						order: 'asc',
					},
				},
			],
		},
	},
	{
		ignores: ['.astro/', 'dist/'],
	},
	eslintConfigPrettier,
];

https://zenn.dev/hisho/articles/23c39e18282687
これ良いかもと思ったけど、ちょっとtoo muchなので今回はスルー。でも嫌いじゃない

YoshinokiYoshinoki

prettier追加

npm i -D prettier prettier-plugin-astro
.prettierrc.mjs
/** @type {import("prettier").Config} */
export default {
	printWidth: 100,
	tabWidth: 2,
	semi: true,
	trailingComma: 'all',
	singleQuote: true,
	arrowParens: 'always',
	useTabs: true,
	plugins: ['prettier-plugin-astro'],
	overrides: [
		{
			files: '*.astro',
			options: {
				parser: 'astro',
			},
		},
	],
};
.prettierignore
node_modules/
.astro/
dist/
package-lock.json
YoshinokiYoshinoki
.vscode/extensions.json
{
  "recommendations": [
    "astro-build.astro-vscode", // Astro
    "dbaeumer.vscode-eslint", // ESLint
    "esbenp.prettier-vscode", // Prettier
    "yusukehirao.vscode-markuplint" // Markuplint
  ]
}
.vscode/settings.json
{
	"editor.codeActionsOnSave": {
		"source.fixAll.eslint": "explicit",
		"source.addMissingImports": "explicit"
	},
	"editor.defaultFormatter": "esbenp.prettier-vscode",
	"editor.formatOnSave": true,
	"editor.formatOnPaste": true,
	"files.insertFinalNewline": true,
	"files.trimTrailingWhitespace": true,
	"[markdown]": {
		"files.trimTrailingWhitespace": false
	},
	"prettier.documentSelectors": ["**/*.astro"],
	"eslint.validate": ["javascript", "javascriptreact", "astro", "typescript", "typescriptreact", "markdown", "mdx"],
	"eslint.options": {
		"overrideConfigFile": "eslint.config.mjs"
	},
	"javascript.preferences.importModuleSpecifier": "non-relative",
	"typescript.preferences.importModuleSpecifier": "non-relative",
	"mdx.server.enable": true,
	"markuplint.enable": true
}
YoshinokiYoshinoki

Markuplintを追加
対話コマンドの中でAstroとReactを選択

npx markuplint --init

✔ Which do you use template engines? · React (JSX), Astro
✔ May I install them automatically? (y/N) · true
✔ Do you customize rules? (y/N) · false
✔ Does it import the recommended config? (y/N) · true

https://markuplint.dev/ja/

.markuplintrc
{
	"specs": {
		"\\.tsx?$": "@markuplint/react-spec"
	},
	"parser": {
		"\\.tsx?$": "@markuplint/jsx-parser",
		"\\.astro$": "@markuplint/astro-parser"
	},
	"extends": [
		"markuplint:recommended"
	]
}
YoshinokiYoshinoki

Stylelint追加

npm init stylelint stylelint-config-standard stylelint-config-html stylelint-config-recess-order postcss-html autoprefixer

https://stylelint.io/user-guide/get-started

.stylelintrc.mjs
export default {
	extends: [
		'stylelint-config-standard',
		'stylelint-config-html/astro',
		'stylelint-config-recess-order',
	],
};
postcss.config.mjs
import autoprefixer from 'autoprefixer';

export default {
	plugins: [autoprefixer],
};