iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
🔧

Next.js 15 + ESLint 9 + Prettier + VSCode Initial Setup

に公開

I always forget this, so I'm recording it here.

Next.js

https://nextjs.org/docs/app/getting-started/installation

I want to use import aliases, so I changed that specific option from the default to Yes.
I also want to use Turbopack, so I left it at the default Yes.

$ npx create-next-app@latest sample-app
✔ Would you like to use TypeScript? … No / Yes
✔ Which linter would you like to use? › ESLint
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like your code inside a `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to use Turbopack? (recommended) … No / Yes
✔ Would you like to customize the import alias (`@/*` by default)? … No / Yes
✔ What import alias would you like configured? … @/*

Prettier

https://nextjs.org/docs/app/api-reference/config/eslint#with-prettier

npm install --save-dev eslint-config-prettier prettier

Add prettier to eslint.config.mjs.

const eslintConfig = [
  ...compat.extends(
    "next/core-web-vitals",
    "next/typescript",
    "prettier"
  ),

Add the format command to scripts in package.json.

package.json
  "scripts": {
    "format": "prettier --write ."

ESLint

I still don't quite understand the configuration.
Using strict-type-checked and stylistic-type-checked.
Maybe a slightly more relaxed set of rules would be fine.

$ npm install -D typescript-eslint
import { fileURLToPath } from "url";
import { dirname } from "path";
import tseslint from "typescript-eslint";
import { FlatCompat } from "@eslint/eslintrc";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const compat = new FlatCompat({
  baseDirectory: __dirname,
});

const withTs = (configs) =>
  configs.map((c) => ({
    ...c,
    files: ["**/*.ts", "**/*.tsx"],
    languageOptions: {
      ...(c.languageOptions ?? {}),
      parser: tseslint.parser,
      parserOptions: {
        project: ["./tsconfig.json"],
        tsconfigRootDir: __dirname,
      },
    },
  }));

export default [
  ...compat.extends("next/core-web-vitals", "next/typescript"),
  ...withTs(tseslint.configs.strictTypeChecked),
  ...withTs(tseslint.configs.stylisticTypeChecked),
  ...compat.extends("prettier"),
  {
    ignores: [
      "node_modules/**",
      ".next/**",
      "out/**",
      "build/**",
      "next-env.d.ts",
      "eslint.config.mjs",
    ],
  },
];

VSCode

Configure the recommended extensions.

.vscode/extensions.json
{
  "recommendations": [
    "dbaeumer.vscode-eslint",
    "esbenp.prettier-vscode"
  ]
}

Format on save and prioritize import aliases during import completion.

.vscode/settings.json
{
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit"
  },
  "typescript.preferences.importModuleSpecifier": "non-relative",
  "typescript.preferences.importModuleSpecifierEnding": "auto"
}

Discussion