Расширение «ESLint» для VS Code, часть 2 из 2

05.08.2022

Теги: IDEJavaScriptWeb-разработкаКонфигурацияНастройкаПлагинУстановкаФайл

ESLint и Prettier вместе, второй способ

Есть еще один способ заставить ESLint и Prettier работать вместе — это расширение «Prettier ESLint» от Rebecca Vest на основе модуля prettier-eslint. При форматировании Alt+Shift+F и сохранении Ctrl+S — сначала отрабатывает Prettier, а потом — исправление ошибок ESLint.

При этом не требуется установка расширений «Prettier» и «ESLint» для VS Code. Но если установить расширение «ESLint» — будет подсветка ошибок при печати кода. Правда, «ESLint» будет подсвечивать только «свои» ошибки — поэтому второй способ чуть хуже первого.

Давайте создадим новый проект и установим локально prettier и eslint:

$ npm intsall prettier --save-dev
$ npm intsall eslint --save-dev
{
    "devDependencies": {
        "eslint": "^8.21.0",
        "prettier": "^2.7.1"
    }
}

Отредактируем файл конфигурации settings.json — укажем defaultFormatter:

{
    ..........
    // По умолчанию форматирование запрещено
    "editor.formatOnSave": false, // форматировать код при сохранении файла
    "editor.formatOnPaste": false, // форматировать при вставке фрагмента кода
    "editor.codeActionsOnSave": [], // набор действий при сохранении файла
    "editor.defaultFormatter": null,
    // Разрешить или запретить расширения eslint и prettier
    "prettier.enable": true, // нужен рестарт vs code
    "eslint.enable": true,
    // Настройки форматирования javascript
    "eslint.format.enable": true, // запретить или разрешить форматирование
    "eslint.run": "onType", // запускать проверку кода по мере печати кода
    "eslint.probe": [ // какие файлы нужно проверять
        "javascript"
    ],
    "[javascript]": {
        "editor.formatOnSave": true,
        "editor.formatOnPaste": true,
        "editor.defaultFormatter": "rvest.vs-code-prettier-eslint"
    },
    ..........
}

Но здесь нужно помнить, что правила eslint не должны противоречить правилам prettier. Например, в наборе eslint:recommended нет правил, которые бы противоречили prettier — так что не будет проблем с перезаписью.

{
    "root": true,
    "env": {
        "browser": true,
        "es2021": true,
        "node": true
    },
    "extends": [
        "eslint:recommended"
    ],
    "parserOptions": {
        "ecmaVersion": "latest",
        "sourceType": "module"
    },
    "rules": {}
}
{
    "arrowParens": "avoid",
    "bracketSpacing": true,
    "endOfLine": "lf",
    "htmlWhitespaceSensitivity": "css",
    "insertPragma": false,
    "jsxBracketSameLine": false,
    "jsxSingleQuote": false,
    "printWidth": 80,
    "proseWrap": "preserve",
    "quoteProps": "as-needed",
    "requirePragma": false,
    "semi": true,
    "singleQuote": true,
    "tabWidth": 4,
    "trailingComma": "es5",
    "useTabs": false,
    "vueIndentScriptAndStyle": true,
    "embeddedLanguageFormatting": "auto"
}

Исходные коды здесь, директория eslint-prettier-together-two.

Теперь подключим правила Standard, где есть правила, которые противоречат правилам Prettier:

$ npm install eslint-config-standard eslint-plugin-promise eslint-plugin-import eslint-plugin-n --save-dev
{
    "devDependencies": {
        "eslint": "^8.21.0",
        "eslint-config-standard": "^17.0.0",
        "eslint-plugin-import": "^2.26.0",
        "eslint-plugin-n": "^15.2.4",
        "eslint-plugin-promise": "^6.0.0",
        "prettier": "^2.7.1"
    }
}
{
    "root": true,
    "env": {
        "browser": true,
        "es2021": true,
        "node": true
    },
    "extends": [
        "standard"
    ],
    "parserOptions": {
        "ecmaVersion": "latest",
        "sourceType": "module"
    },
    "rules": {}
}

И сразу увидим много сообщений от ESLint, связанных с форматированием. Давайте запретим все правила Standard, которые противрочат Prettier.

$ npm install eslint-config-prettier --save-dev
{
    "devDependencies": {
        "eslint": "^8.21.0",
        "eslint-config-prettier": "^8.5.0",
        "eslint-config-standard": "^17.0.0",
        "eslint-plugin-import": "^2.26.0",
        "eslint-plugin-n": "^15.2.4",
        "eslint-plugin-promise": "^6.0.0",
        "prettier": "^2.7.1"
    }
}
{
    "root": true,
    "env": {
        "browser": true,
        "es2021": true,
        "node": true
    },
    "extends": [
        "standard",
        "prettier"
    ],
    "parserOptions": {
        "ecmaVersion": "latest",
        "sourceType": "module"
    },
    "rules": {}
}

Исходные коды здесь, директория eslint-prettier-standard-two.

ESLint и Prettier для React приложения

Мы рассмотрели два способа подружить ESLint и Prettier. И для этих двух способов добавили использование набора правил Standard. Теперь добавим еще наборы правил, которые потребуются при разработке React приложения. Начнем со второго проекта, где мы использовали расширение «Prettier ESLint» от Rebecca Vest на основе модуля prettier-eslint.

ESLint и Prettier (второй способ) для React приложения

1. Настройка

Нам потребуется установить два модуля и отредактировать .eslintrc.json:

$ npm install eslint-plugin-react eslint-plugin-react-hooks --save-dev
{
    "devDependencies": {
        "eslint": "^8.21.0",
        "eslint-config-prettier": "^8.5.0",
        "eslint-config-standard": "^17.0.0",
        "eslint-plugin-import": "^2.26.0",
        "eslint-plugin-n": "^15.2.4",
        "eslint-plugin-promise": "^6.0.0",
        "eslint-plugin-react": "^7.30.1",
        "eslint-plugin-react-hooks": "^4.6.0",
        "prettier": "^2.7.1"
    }
}
{
    "root": true,
    "env": {
        "browser": true,
        "es2021": true,
        "node": true
    },
    "extends": [
        "standard",
        "plugin:react/recommended",
        "plugin:react/jsx-runtime",
        "plugin:react-hooks/recommended",
        "prettier"
    ],
    "parserOptions": {
        "ecmaFeatures": {
            "jsx": true
        },
        "ecmaVersion": "latest",
        "sourceType": "module"
    },
    "plugins": [
        "react",
        "react-hooks"
    ],
    "rules": {}
}

2. Проверка

Чтобы проверить конфигурацию — развернем React приложение:

$ npm install react react-dom --save-prod
{
    "devDependencies": {
        "eslint": "^8.21.0",
        "eslint-config-prettier": "^8.5.0",
        "eslint-config-standard": "^17.0.0",
        "eslint-plugin-import": "^2.26.0",
        "eslint-plugin-n": "^15.2.4",
        "eslint-plugin-promise": "^6.0.0",
        "eslint-plugin-react": "^7.30.1",
        "eslint-plugin-react-hooks": "^4.6.0",
        "prettier": "^2.7.1"
    },
    "dependencies": {
        "react": "^18.2.0",
        "react-dom": "^18.2.0"
    }
}

Babel нужен для транспиляции ES6+ в ES5 и для обработки jsx-кода:

$ npm install @babel/core @babel/preset-env @babel/preset-react --save-dev
{
    "devDependencies": {
        "@babel/core": "^7.18.10",
        "@babel/preset-env": "^7.18.10",
        "@babel/preset-react": "^7.18.6",
        "eslint": "^8.21.0",
        "eslint-config-prettier": "^8.5.0",
        "eslint-config-standard": "^17.0.0",
        "eslint-plugin-import": "^2.26.0",
        "eslint-plugin-n": "^15.2.4",
        "eslint-plugin-promise": "^6.0.0",
        "eslint-plugin-react": "^7.30.1",
        "eslint-plugin-react-hooks": "^4.6.0",
        "prettier": "^2.7.1"
    },
    "dependencies": {
        "react": "^18.2.0",
        "react-dom": "^18.2.0"
    }
}

Создаем файл конфигурации Babel, это .babelrc:

{
    "presets": [
        "@babel/preset-env",
        ["@babel/preset-react", {"runtime": "automatic"}]
    ]
}

Для сборки React проекта установим и настроим webpack:

$ npm install webpack webpack-cli webpack-dev-server --save-dev
$ npm install babel-loader css-loader style-loader html-webpack-plugin --save-dev
{
    "devDependencies": {
        "@babel/core": "^7.18.10",
        "@babel/preset-env": "^7.18.10",
        "@babel/preset-react": "^7.18.6",
        "babel-loader": "^8.2.5",
        "css-loader": "^6.7.1",
        "eslint": "^8.21.0",
        "eslint-config-standard": "^17.0.0",
        "eslint-plugin-import": "^2.26.0",
        "eslint-plugin-n": "^15.2.4",
        "eslint-plugin-promise": "^6.0.0",
        "eslint-plugin-react": "^7.30.1",
        "eslint-plugin-react-hooks": "^4.6.0",
        "html-webpack-plugin": "^5.5.0",
        "prettier": "^2.7.1",
        "style-loader": "^3.3.1",
        "webpack": "^5.74.0",
        "webpack-cli": "^4.10.0",
        "webpack-dev-server": "^4.9.3"
    },
    "dependencies": {
        "react": "^18.2.0",
        "react-dom": "^18.2.0"
    }
}

Создадим файл конфигурации, это webpack.config.js (см. здесь):

const path = require('path');
const HtmlWebPackPlugin = require('html-webpack-plugin');

module.exports = {
    mode: 'development',
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: 'bundle.js',
    },
    module: {
        rules: [
            {
                test: /\.(png|jpe?g|gif|webp|svg)$/i, // изображение
                type: 'asset/resource',
                generator: {
                    filename: '[hash][ext][query]',
                },
            },
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                },
            },
            {
                test: /\.css$/,
                use: [
                    {
                        loader: 'style-loader',
                    },
                    {
                        loader: 'css-loader',
                    },
                ],
            },
        ],
    },
    plugins: [
        new HtmlWebPackPlugin({
            template: path.resolve(__dirname, 'public/index.html'), // файл шаблона
            filename: 'index.html', // выходной файл
        }),
    ],
};

Добавим в package.json секцию scripts:

{
    "scripts": {
        "start": "webpack serve --open",
        "build": "webpack build",
        "watch": "webpack watch"
    },
    ..........

Соберем проект в директорию build и запустим Live Server, чтобы он обслуживал эту директорию (см. здесь):

$ npm run build

Исходные коды здесь, директория eslint-prettier-react-two.

ESLint и Prettier (первый способ) для React приложения

Этот способ использовать ESLint и Prettier вместе заключается в использовании пакета eslint-plugin-prettier, который позволяет запускать Prettier как правило ESLint. В первой часты мы настроили ESLint на использование набора правил Standard, осталось добавить наборы для работы с React приложением. Здесь все будет по аналогии со вторым способом, отличия незначительные.

1. Настройка

Нам потребуется установить два модуля и отредактировать .eslintrc.json:

$ npm install eslint-plugin-react eslint-plugin-react-hooks --save-dev
{
    "devDependencies": {
        "eslint": "^8.21.0",
        "eslint-config-prettier": "^8.5.0",
        "eslint-config-standard": "^17.0.0",
        "eslint-plugin-import": "^2.26.0",
        "eslint-plugin-n": "^15.2.4",
        "eslint-plugin-prettier": "^4.2.1",
        "eslint-plugin-promise": "^6.0.0",
        "eslint-plugin-react": "^7.30.1",
        "eslint-plugin-react-hooks": "^4.6.0",
        "prettier": "^2.7.1",
    }
}
{
    "root": true,
    "env": {
        "browser": true,
        "es2021": true,
        "node": true
    },
    "extends": [
        "standard",
        "plugin:react/recommended",
        "plugin:react/jsx-runtime",
        "plugin:react-hooks/recommended",
        "plugin:prettier/recommended"
    ],
    "parserOptions": {
        "ecmaFeatures": {
            "jsx": true
        },
        "ecmaVersion": "latest",
        "sourceType": "module"
    },
    "plugins": [
        "react",
        "react-hooks"
    ],
    "rules": {}
}

2. Проверка

Чтобы проверить конфигурацию — развернем React приложение:

$ npm install react react-dom --save-prod
{
    "devDependencies": {
        "eslint": "^8.21.0",
        "eslint-config-prettier": "^8.5.0",
        "eslint-config-standard": "^17.0.0",
        "eslint-plugin-import": "^2.26.0",
        "eslint-plugin-n": "^15.2.4",
        "eslint-plugin-prettier": "^4.2.1",
        "eslint-plugin-promise": "^6.0.0",
        "eslint-plugin-react": "^7.30.1",
        "eslint-plugin-react-hooks": "^4.6.0",
        "prettier": "^2.7.1",
    },
    "dependencies": {
        "react": "^18.2.0",
        "react-dom": "^18.2.0"
    }
}

Babel нужен для транспиляции ES6+ в ES5 и для обработки jsx-кода:

$ npm install @babel/core @babel/preset-env @babel/preset-react --save-dev
{
    "devDependencies": {
        "@babel/core": "^7.18.10",
        "@babel/preset-env": "^7.18.10",
        "@babel/preset-react": "^7.18.6",
        "eslint": "^8.21.0",
        "eslint-config-prettier": "^8.5.0",
        "eslint-config-standard": "^17.0.0",
        "eslint-plugin-import": "^2.26.0",
        "eslint-plugin-n": "^15.2.4",
        "eslint-plugin-prettier": "^4.2.1",
        "eslint-plugin-promise": "^6.0.0",
        "eslint-plugin-react": "^7.30.1",
        "eslint-plugin-react-hooks": "^4.6.0",
        "prettier": "^2.7.1",
    },
    "dependencies": {
        "react": "^18.2.0",
        "react-dom": "^18.2.0"
    }
}

Создаем файл конфигурации Babel, это .babelrc:

{
    "presets": [
        "@babel/preset-env",
        ["@babel/preset-react", {"runtime": "automatic"}]
    ]
}

Для сборки React проекта установим и настроим webpack:

$ npm install webpack webpack-cli webpack-dev-server --save-dev
$ npm install babel-loader css-loader style-loader html-webpack-plugin --save-dev
{
    "devDependencies": {
        "@babel/core": "^7.18.10",
        "@babel/preset-env": "^7.18.10",
        "@babel/preset-react": "^7.18.6",
        "babel-loader": "^8.2.5",
        "css-loader": "^6.7.1",
        "eslint": "^8.21.0",
        "eslint-config-prettier": "^8.5.0",
        "eslint-config-standard": "^17.0.0",
        "eslint-plugin-import": "^2.26.0",
        "eslint-plugin-n": "^15.2.4",
        "eslint-plugin-prettier": "^4.2.1",
        "eslint-plugin-promise": "^6.0.0",
        "eslint-plugin-react": "^7.30.1",
        "eslint-plugin-react-hooks": "^4.6.0",
        "html-webpack-plugin": "^5.5.0",
        "prettier": "^2.7.1",
        "style-loader": "^3.3.1",
        "webpack": "^5.74.0",
        "webpack-cli": "^4.10.0",
        "webpack-dev-server": "^4.9.3"
    },
    "dependencies": {
        "react": "^18.2.0",
        "react-dom": "^18.2.0"
    }
}

Создадим файл конфигурации, это webpack.config.js (см. здесь):

const path = require('path');
const HtmlWebPackPlugin = require('html-webpack-plugin');

module.exports = {
    mode: 'development',
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: 'bundle.js',
    },
    module: {
        rules: [
            {
                test: /\.(png|jpe?g|gif|webp|svg)$/i, // изображение
                type: 'asset/resource',
                generator: {
                    filename: '[hash][ext][query]',
                },
            },
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                },
            },
            {
                test: /\.css$/,
                use: [
                    {
                        loader: 'style-loader',
                    },
                    {
                        loader: 'css-loader',
                    },
                ],
            },
        ],
    },
    plugins: [
        new HtmlWebPackPlugin({
            template: path.resolve(__dirname, 'public/index.html'), // файл шаблона
            filename: 'index.html', // выходной файл
        }),
    ],
};

Добавим в package.json секцию scripts:

{
    "scripts": {
        "start": "webpack serve --open",
        "build": "webpack build",
        "watch": "webpack watch"
    },
    ..........

Соберем проект в директорию build и запустим Live Server, чтобы он обслуживал эту директорию (см. здесь):

$ npm run build

Исходные коды здесь, директория eslint-prettier-react-one.

Встроенные форматтеры

Не для всех файлов с кодом нужно использовать внешний форматтер, потому что у VS Code есть несколько встроенных. И зачастую они ничем не хуже внешних, а порой даже лучше. Так что для одних файлов можно использовать встроенные средства форматирования, а для других — использовать внешний форматтер.

{
    /*
     * ОБЩИЕ НАСТРОЙКИ
     */

    "editor.fontSize": 12,
    "files.encoding": "utf8", // кодировка файлов
    "files.eol": "\n", // концы строк как в linux
    "files.insertFinalNewline": true, // пустая строка в конце файла
    "files.trimTrailingWhitespace": true, // удалять пробелы в конце строк
    "editor.insertSpaces": true, // заменять табуляцию на пробелы
    "editor.tabSize": 4, // табуляция заменяется 4 пробелами
    "editor.renderWhitespace": "all", // показывать символы пробелов

    "workbench.colorCustomizations": { // волнистая линия
        "editorWarning.foreground": "#FF9933",
        "editorError.foreground": "#FF0000",
        "editorInfo.foreground": "#00AA00",
    },

    /*
     * ФОРМАТИРОВАНИЕ
     */

    // По умолчанию форматирование кода запрещено
    "editor.formatOnSave": false, // форматировать код при сохранении файла
    "editor.formatOnPaste": false, // форматировать при вставке фрагмента кода
    "editor.codeActionsOnSave": [], // набор действий при сохранении файла
    "editor.defaultFormatter": null,
    // Разрешить или запретить расширения eslint и prettier
    "prettier.enable": true, // нужен рестарт vs code
    "eslint.enable": true,
    // Настройки форматирования javascript
    "eslint.format.enable": true, // запретить или разрешить форматирование
    "eslint.run": "onType", // запускать проверку кода по мере печати кода
    "eslint.probe": [ // какие файлы нужно проверять
        "javascript"
    ],
    "eslint.rules.customizations": [
        // для проблем форматирования кода уровень info
        {"rule": "prettier/prettier", "severity": "info"}
    ],
    "[javascript]": {
        "editor.formatOnPaste": true,
        "editor.formatOnSave": true,
        "editor.defaultFormatter": "dbaeumer.vscode-eslint"
    },
    // Настройки форматирования css
    "css.format.enable": true,
    "css.validate": true,
    "css.format.newlineBetweenRules": false,
    "css.format.newlineBetweenSelectors": false,
    "css.lint.duplicateProperties": "warning",
    "css.format.spaceAroundSelectorSeparator": true,
    "[css]": {
        "editor.formatOnSave": true,
        "editor.formatOnPaste": true,
        "editor.defaultFormatter": "vscode.css-language-features"
    },
    // Настройки форматирования json
    "json.format.enable": true,
    "json.validate.enable": true,
    "[json]": {
        "editor.formatOnSave": true,
        "editor.formatOnPaste": true,
        "editor.defaultFormatter": "vscode.json-language-features"
    },
    "[jsonc]": {
        "editor.defaultFormatter": "vscode.json-language-features"
    },
    // Настройки форматирования html
    "html.format.enable": true, // разрешить форматирование html-кода
    "html.format.wrapLineLength": 100, // максимальная длина сроки до переносана новую
    "html.format.unformatted": null, // эти теги не форматировать (см.ссылку в подсказке)
    "html.format.contentUnformatted": "pre,code,textarea", // контент этих тегов не форматировать
    "html.format.extraLiners": "", // пустая строка перед этими тегами
    "html.format.preserveNewLines": false, // сохранять или нет пустые строки
    "html.format.maxPreserveNewLines": null, // сколько пустых строк сохранять
    "html.format.indentInnerHtml": false, // отступ <head> и <body> относительно <html>
    "html.format.wrapAttributes": "preserve-aligned", // перенос и выравнивание атрибутов
    "html.format.wrapAttributesIndentSize": null, // размер отступа при переносе и выравнивании атр.
    "html.validate.scripts": true, // проверять js-скрипты внутри html-кода
    "html.validate.styles": true, // проверять css-стили внутри html-кода
    "[html]": {
        "editor.formatOnSave": true,
        "editor.formatOnPaste": true,
        "editor.defaultFormatter": "vscode.html-language-features"
    },
    // Настройки форматирования markdown
    "[markdown]": {
        "editor.formatOnSave": true,
        "editor.formatOnPaste": true,
        "editor.defaultFormatter": "vscode.markdown-language-features"
    },

    /*
     * РАСШИРЕНИЯ
     */

    // Расширение Render Line Endings, показывает символы CR LF
    "code-eol.newlineCharacter": "↓",
    "code-eol.crlfCharacter": "←↓",
    "code-eol.highlightNonDefault": true,
    // Расширение Live Server, простой веб-сервер для разработки
    "liveServer.settings.root": "/build",
    "liveServer.settings.host": "localhost",
    "liveServer.settings.fullReload": false,
    "liveServer.settings.port": 5555,
    "liveServer.settings.donotShowInfoMsg": true,
    "liveServer.settings.donotVerifyTags": true,
    // Расширение Prettier для форматирования кода
    "prettier.arrowParens": "avoid", // скобки вокруг единственного параметра стрелочной функции
    "prettier.bracketSpacing": true, // пробелы между скобками в литералах объектов
    "prettier.endOfLine": "lf", // окончания строк
    "prettier.htmlWhitespaceSensitivity": "css", // форматирование html с учетом пробелов
    "prettier.insertPragma": false, // вставлять спец.комментарий в начало файла
    "prettier.jsxBracketSameLine": false, // где будет завершающий > многострочного jsx-элемента
    "prettier.jsxSingleQuote": false, // использовать в jsx одинарные кавычки вместо двойных
    "prettier.printWidth": 100, // на какой позиции выполнять перенос строки при печати
    "prettier.proseWrap": "preserve", // как обрабатывать markdown файлы
    "prettier.quoteProps": "as-needed", // свойства объекта в кавычках или без кавычек
    "prettier.requirePragma": false, // форматировать только файлы со спец.комментарием в начале
    "prettier.semi": true, // точка с запятой в конце операторов
    "prettier.singleQuote": true, // использовать одинарные кавычки вместо двойных
    "prettier.tabWidth": 4, // заменять табуляцию на 4 пробела
    "prettier.trailingComma": "es5", // конечные запятые в объектах и массивах
    "prettier.useTabs": false, // делать отступы с помощью табуляции
    "prettier.vueIndentScriptAndStyle": false, // отступ внутри <script> и <style> в vue файлах
    "prettier.embeddedLanguageFormatting": "auto" // форматировать встроенный код
}

Поиск: IDE • JavaScript • Web-разработка • Конфигурация • Настройка • Плагин • Установка • Файл • ESLint • Prettier

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.