Приветствую! В ходе своей профессиональной деятельности, каждый фронтенд-разработчик сталкивается с неотъемлемой частью разработки - инструментом ESLint. ESLint представляет собой мощный статический анализатор кода, призванный обнаруживать и устранять проблемы в вашем JavaScript коде.
Сегодня мы поговорим, о настройке shareable config. Мы рассмотрим, как это может помочь продуктовым командам или фрилансеру разработчику, а далее перейдем к настройке этой конфигурации.
Shareable Config: Когда это надо?
Представьте себе ситуацию, в которой у вас имеется несколько кроссфункциональных команд, занимающихся разработкой различных продуктов компании, но при этом использующих cхожий технологический стек. В таком контексте возникает необходимость в единых стандартах и подходах к написанию кода, чтобы обеспечить единый стиль разработки. В данном случае на помощь приходит инструмент ESLint.
После того как были согласованы наборы правил, назначены ответственные за их реализацию и настройку, начинается этап реализации в проектах. Однако, при возникновении необходимости внести изменения в конфигурацию ESLint, многократное редактирование всех проектов может быть трудозатратным и неэффективным. Именно в таких ситуациях на помощь приходит создание Shareable config для ESLint и его последующая публикация в репозитории пакетов, таких как npm или других пакетных реестрах
Преимущества создания и использования Shareable config:
Единое правило: Создавая Shareable config, вы устанавливаете единый набор правил для всех проектов. Это обеспечивает согласованный стиль кода и снижает вероятность возникновения ошибок, связанных с разнообразными конфигурациями.
Централизованное управление: Если вам необходимо внести изменения в правила ESLint, вы можете внести их в Shareable config, и эти изменения автоматически применятся ко всем проектам, использующим эту конфигурацию. Это значительно упрощает управление и поддержку кодовой базы.
Снижение затрат: Вместо того чтобы править конфигурации в каждом проекте, вы вносите изменения только в Shareable config и публикуете его. Это экономит время и уменьшает затраты на обслуживание.
Публичная доступность: Публикация Shareable config в пакетном реестре позволяет другим командам и разработчикам использовать вашу конфигурацию. Это способствует распространению фронтенд стандартов и позволяет другим внедрять их в свои проекты.
Инициализация конфигурации проекта
Давайте создадим папку eslint-config-test и создадим модуль с ограниченной областью действия. Используем команду npm init --scope=@test и пройдемся по шагам установки.
В итоге мы получим файл, на основе этого:
{ "name": "@test/eslint-config-test", "version": "1.0.0", "description": "ESLint Shareable Config", "main": "main.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [ "eslint", "share", "config" ], "author": "Kim Valentin", "license": "ISC" }
Здесь важно отметить @test - scope npm модуля, более подробно в документации
Сюда по степени необходимости можно добавить еще несколько опциональных свойств: "files", "repositry","bugs", "dependencies", "devDependencies", "peerDependencies" и другие. О каждом более подробно можно узнать в документации
Я добавил пару пакетов для работы конфига (их не нужно будет ставить в основном проекте, кроме peerDependencies):
"dependencies": { "@typescript-eslint/eslint-plugin": "^6.7.2", "@typescript-eslint/parser": "^6.7.2", "@vue/eslint-config-typescript": "^12.0.0", "eslint-config-airbnb-base": "^15.0.0", "eslint-plugin-import": "^2.28.1", "eslint-plugin-vue": "^9.17.0" }, "devDependencies": { "eslint": "^8.50.0", "typescript": "~5.2.2" }, "peerDependencies": { "eslint": ">= 8.50.0", "typescript": ">= 5.0.0" }
Создание модуля конфигурация
Здесь все достаточно просто мы создаем модуль для будущего использования с расширением .js. Например, у меня вышел такой модуль:
module.exports = { root: true, env: { es6: true, browser: true, node: true, }, extends: [ 'plugin:@typescript-eslint/recommended', 'plugin:vue/vue3-recommended', '@vue/eslint-config-typescript', 'airbnb-base', ], parserOptions: { parser: require.resolve('@typescript-eslint/parser'), extraFileExtensions: ['.vue'], ecmaVersion: 'latest', sourceType: "module", ecmaFeatures: { jsx: true, }, }, globals: { JSX: true, }, plugins: ['@typescript-eslint'], rules: { semi: ['error', 'never'], 'no-param-reassign': 'off', 'no-void': 'off', 'no-nested-ternary': 'off', 'max-classes-per-file': 'off', 'linebreak-style': 0, // ignore linebreak-style 'no-plusplus': 'off', 'max-len': ['error', { code: 255, ignoreComments: true, }], 'vue/block-order': ['error', { 'order': [ [ 'script', 'template' ], 'style' ] }], 'no-use-before-define': 'off', '@typescript-eslint/no-use-before-define': ['error', { ignoreTypeReferences: true }], 'no-underscore-dangle': 'off', 'no-shadow': 0, '@typescript-eslint/no-shadow': 0, 'new-cap': ['error', { newIsCap: false }], 'import/first': 'off', 'import/named': 'error', 'import/namespace': 'error', 'import/default': 'error', 'import/export': 'error', 'import/extensions': 'off', 'import/no-unresolved': 'off', 'import/no-extraneous-dependencies': 'off', 'import/prefer-default-export': 'off', // 'prefer-promise-reject-errors': 'off', quotes: ['warn', 'single', { avoidEscape: true }], // this rule, if on, would require explicit return type on the `render` function '@typescript-eslint/explicit-function-return-type': 'off', // in plain CommonJS modules, you can't use `import foo = require('foo')` to pass this rule, so it has to be disabled '@typescript-eslint/no-var-requires': 'off', // The core 'no-unused-vars' rules (in the eslint:recommended ruleset) // does not work with type definitions 'no-unused-vars': 'off', // allow debugger during development only 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', '@typescript-eslint/member-delimiter-style': ['error', { multiline: { delimiter: 'none', requireLast: true, }, singleline: { delimiter: 'comma', requireLast: false, }, multilineDetection: 'brackets', }], '@typescript-eslint/no-explicit-any': 'warn', }, }
Публикация пакета
Пару шагов и мы создали с вами наш конфиг. Далее мы можем опубликовать пакет в npm или package registry Gitlab. Настроить CI и использовать.
P.S. Если вы решили использовать package registry Gitlab, у вас будет несколько вариантов, либо настроить publishConfig в package.json и ssh ключ в CI. Либо использовать такую конструкцию:
"devDependencies": { "@test/eslint-config-test": "git+ssh://user@host/path/eslint-config-test#branch" }
Использование пакета
Необходимо на проекте установить нужные зависимости (peerDependencies). Далее можно создать файл .eslintrc.cjs если еще у вас его не было. И там использовать ваш пакет.
module.exports = { extends: [ '@test/eslint-config-test', ], }
Вы также можете указать дополнительные правила, которые перезапишут ваш конфиг, и будут применяться локально к текущему проекту.
Заключение
Пора подводить итоги, если вы раньше таскали ваш файл настроек и перекидывали с одного проекта на другой, то данная статья вам поможет. Всего немного вашего времени, и вы сделаете дополнительную автоматизацию, которая позволит модифицировать ваши правила для написания кода в едином месте.
Если вам интересно больше технического контента, немного лайва из жизни молодого тимлида, добро пожаловать в мой телеграмм канал
