Merge pull request #1 from e7f3/fixes/configs-tweaks

Правки в инструменты сборки и конфиги линтеров
This commit is contained in:
Ilia Mashkov
2025-11-19 19:08:01 +03:00
committed by GitHub
6 changed files with 210 additions and 190 deletions

View File

@@ -63,6 +63,7 @@ export function buildPlugins({
plugins.push( plugins.push(
new BundleAnalyzerPlugin({ new BundleAnalyzerPlugin({
openAnalyzer: false, openAnalyzer: false,
analyzerMode: 'static',
}) })
) )
plugins.push(new ReactRefreshWebpackPlugin({ overlay: false })) plugins.push(new ReactRefreshWebpackPlugin({ overlay: false }))

View File

@@ -31,6 +31,8 @@ export function buildResolvers(options: BuildOptions): webpack.ResolveOptions {
preferAbsolute: true, preferAbsolute: true,
modules: [options.paths.src, 'node_modules'], modules: [options.paths.src, 'node_modules'],
mainFiles: ['index'], mainFiles: ['index'],
alias: {}, alias: {
'@': options.paths.src,
},
} }
} }

View File

@@ -18,7 +18,7 @@ import MiniCssExtractPlugin from 'mini-css-extract-plugin'
*/ */
export const buildCssLoader = (isDev: boolean) => { export const buildCssLoader = (isDev: boolean) => {
const cssLoader = { const cssLoader = {
test: /\.s[ac]ss$/i, test: /\.(s[ac]ss|css)$/i,
use: [ use: [
// Создает <style> теги из JS строк (dev) или извлекает в файлы (prod) // Создает <style> теги из JS строк (dev) или извлекает в файлы (prod)
isDev ? 'style-loader' : MiniCssExtractPlugin.loader, isDev ? 'style-loader' : MiniCssExtractPlugin.loader,
@@ -28,6 +28,7 @@ export const buildCssLoader = (isDev: boolean) => {
options: { options: {
modules: { modules: {
auto: /\.module\..*$/, auto: /\.module\..*$/,
namedExport: false,
localIdentName: isDev localIdentName: isDev
? '[path][name]__[local]--[hash:base64:5]' ? '[path][name]__[local]--[hash:base64:5]'
: '[hash:base64:8]', : '[hash:base64:8]',

View File

@@ -41,213 +41,225 @@ import globals from 'globals'
import tseslint from 'typescript-eslint' import tseslint from 'typescript-eslint'
export default [ export default [
/** /**
* Базовые конфигурации * Базовые конфигурации
*/ */
js.configs.recommended, js.configs.recommended,
...tseslint.configs.recommended, ...tseslint.configs.recommended,
prettierConfig, prettierConfig,
/** /**
* Глобальные исключения (не проверяются линтером) * Глобальные исключения (не проверяются линтером)
*/ */
{ {
ignores: [ ignores: [
'dist/**', 'dist/**',
'node_modules/**', 'node_modules/**',
'.fttemplates/**', '.fttemplates/**',
'*.config.js', '*.config.js',
'*.config.mjs', '*.config.mjs',
'*.config.ts', '*.config.ts',
], ],
},
/**
* Основная конфигурация для всех файлов
*/
{
files: ['**/*.{js,mjs,cjs,ts,tsx}'],
plugins: {
react: reactPlugin,
'react-hooks': reactHooksPlugin,
'jsx-a11y': jsxA11yPlugin,
import: importPlugin,
jest: jestPlugin,
prettier: prettierPlugin,
}, },
languageOptions: {
ecmaVersion: 'latest', /**
sourceType: 'module', * Основная конфигурация для всех файлов
parser: tseslint.parser, */
parserOptions: { {
ecmaFeatures: { files: ['**/*.{js,mjs,cjs,ts,tsx}'],
jsx: true, plugins: {
react: reactPlugin,
'react-hooks': reactHooksPlugin,
'jsx-a11y': jsxA11yPlugin,
import: importPlugin,
jest: jestPlugin,
prettier: prettierPlugin,
}, },
}, languageOptions: {
globals: { ecmaVersion: 'latest',
...globals.browser, sourceType: 'module',
...globals.es2021, parser: tseslint.parser,
...globals.jest, parserOptions: {
__IS_DEV__: 'readonly', ecmaFeatures: {
__API__: 'readonly', jsx: true,
__PROJECT__: 'readonly', },
},
},
settings: {
react: {
version: 'detect',
},
'import/resolver': {
typescript: true,
node: true,
},
},
rules: {
/**
* Правила для импортов
*/
/** Упорядочивание импортов по группам с алфавитной сортировкой */
'import/order': [
'error',
{
groups: [
['external', 'builtin'],
'internal',
['sibling', 'parent'],
'index',
],
pathGroups: [
{
pattern: '@react',
group: 'external',
position: 'before',
}, },
{ globals: {
pattern: '@src/**', ...globals.browser,
group: 'internal', ...globals.es2021,
...globals.jest,
__IS_DEV__: 'readonly',
__API__: 'readonly',
__PROJECT__: 'readonly',
}, },
],
pathGroupsExcludedImportTypes: ['internal', 'react'],
'newlines-between': 'always',
alphabetize: {
order: 'asc',
caseInsensitive: true,
},
}, },
], settings: {
'import/no-unresolved': 'off', react: {
'import/no-extraneous-dependencies': 'off', version: 'detect',
'import/extensions': 'off', },
'import/prefer-default-export': 'off', 'import/resolver': {
'import/no-import-module-exports': 'off', typescript: true,
node: true,
/** },
* Правила для React
*/
/** Определение компонентов через стрелочные функции или function declaration */
'react/function-component-definition': [
2,
{
namedComponents: ['arrow-function', 'function-declaration'],
unnamedComponents: ['arrow-function', 'function-expression'],
}, },
], rules: {
'react/jsx-filename-extension': [ /**
2, * Правила для импортов
{ extensions: ['.tsx', '.jsx', '.js'] }, */
],
'react/require-default-props': 'off',
'react/jsx-props-no-spreading': 'warn',
'react/display-name': 'off',
'react/jsx-no-useless-fragment': [2, { allowExpressions: true }],
/** Не нужен с новым JSX transform */
'react/react-in-jsx-scope': 'off',
/** /** Упорядочивание импортов по группам с алфавитной сортировкой */
* Правила для React Hooks 'import/order': [
*/ 'error',
{
groups: [
['external', 'builtin'],
'internal',
['sibling', 'parent'],
'index',
'type',
],
pathGroups: [
{
pattern: '@react',
group: 'external',
position: 'before',
},
{
pattern: '@/**',
group: 'internal',
},
],
pathGroupsExcludedImportTypes: ['type'],
'newlines-between': 'always',
distinctGroup: false,
alphabetize: {
order: 'asc',
caseInsensitive: true,
},
},
],
'import/no-unresolved': 'off',
'import/no-extraneous-dependencies': 'off',
'import/extensions': 'off',
'import/prefer-default-export': 'off',
'import/no-import-module-exports': 'off',
/** Проверка правил хуков */ /**
'react-hooks/rules-of-hooks': 'error', * Правила для React
/** Проверка зависимостей эффектов */ */
'react-hooks/exhaustive-deps': 'error',
/** /** Определение компонентов через стрелочные функции или function declaration */
* Правила доступности (A11y) 'react/function-component-definition': [
*/ 2,
{
namedComponents: ['arrow-function', 'function-declaration'],
unnamedComponents: ['arrow-function', 'function-expression'],
},
],
'react/jsx-filename-extension': [
2,
{ extensions: ['.tsx', '.jsx', '.js'] },
],
'react/require-default-props': 'off',
'react/jsx-props-no-spreading': 'warn',
'react/display-name': 'off',
'react/jsx-no-useless-fragment': [2, { allowExpressions: true }],
/** Не нужен с новым JSX transform */
'react/react-in-jsx-scope': 'off',
'jsx-a11y/click-events-have-key-events': 'warn', /**
'jsx-a11y/no-static-element-interactions': 'warn', * Правила для React Hooks
*/
/** /** Проверка правил хуков */
* Правила для TypeScript 'react-hooks/rules-of-hooks': 'error',
*/ /** Проверка зависимостей эффектов */
'react-hooks/exhaustive-deps': 'error',
'@typescript-eslint/no-shadow': 'warn', /**
'@typescript-eslint/no-unused-vars': 'warn', * Правила доступности (A11y)
'@typescript-eslint/no-var-requires': 'warn', */
'@typescript-eslint/no-use-before-define': ['error', { enums: false }],
'@typescript-eslint/naming-convention': 'warn',
'@typescript-eslint/ban-ts-comment': 'warn',
/** 'jsx-a11y/click-events-have-key-events': 'warn',
* Общие правила JavaScript/TypeScript 'jsx-a11y/no-static-element-interactions': 'warn',
*/
/** Точки с запятой контролируются Prettier */ /**
semi: 'off', * Правила для TypeScript
'jsx-quotes': ['error', 'prefer-single'], */
'no-shadow': 'off',
'no-unused-vars': 'off', '@typescript-eslint/no-shadow': 'warn',
'no-underscore-dangle': 'off', '@typescript-eslint/no-unused-vars': 'warn',
'no-use-before-define': 'off', '@typescript-eslint/no-var-requires': 'warn',
'no-param-reassign': ['warn', { props: false }], '@typescript-eslint/no-use-before-define': ['error', { enums: false }],
'max-len': [ '@typescript-eslint/naming-convention': [
2, 'warn',
{ {
ignoreComments: true, selector: 'function',
ignoreUrls: true, format: ['camelCase', 'PascalCase'],
code: 140, },
ignorePattern: '^(import\\s.+\\sfrom\\s.+|\\} from)', {
selector: 'variable',
format: ['camelCase', 'UPPER_CASE', 'PascalCase'],
},
],
'@typescript-eslint/ban-ts-comment': 'warn',
/**
* Общие правила JavaScript/TypeScript
*/
/** Точки с запятой контролируются Prettier */
semi: 'off',
'jsx-quotes': ['error', 'prefer-single'],
'no-shadow': 'off',
'no-unused-vars': 'off',
'no-underscore-dangle': 'off',
'no-use-before-define': 'off',
'no-param-reassign': ['warn', { props: false }],
'max-len': [
2,
{
ignoreComments: true,
ignoreUrls: true,
code: 140,
ignorePattern: '^(import\\s.+\\sfrom\\s.+|\\} from)',
},
],
/**
* Правила форматирования (Prettier)
*/
'prettier/prettier': [
'error',
{
semi: false,
singleQuote: true,
jsxSingleQuote: true,
trailingComma: 'es5',
},
],
}, },
],
/**
* Правила форматирования (Prettier)
*/
'prettier/prettier': [
'error',
{
semi: false,
singleQuote: true,
jsxSingleQuote: true,
trailingComma: 'es5',
},
],
}, },
},
/** /**
* Переопределение правил для JavaScript файлов * Переопределение правил для JavaScript файлов
*/ */
{ {
files: ['**/*.js'], files: ['**/*.js'],
rules: { rules: {
'consistent-return': 'off', 'consistent-return': 'off',
'@typescript-eslint/no-var-requires': 'off', '@typescript-eslint/no-var-requires': 'off',
},
}, },
},
/** /**
* Переопределение правил для тестов и сторибуков * Переопределение правил для тестов и сторибуков
*/ */
{ {
files: ['**/src/**/*.{test,stories}.{ts,tsx}'], files: ['**/src/**/*.{test,stories}.{ts,tsx}'],
rules: { rules: {
'max-len': 'off', 'max-len': 'off',
},
}, },
},
] ]

View File

@@ -52,5 +52,6 @@ module.exports = {
'order/order': selectorOrdering, 'order/order': selectorOrdering,
'order/properties-order': propertyOrdering, 'order/properties-order': propertyOrdering,
'declaration-empty-line-before': null, 'declaration-empty-line-before': null,
'no-descending-specificity': null, // Отключаем из-за конфликта с order/order
}, },
} }

View File

@@ -11,6 +11,9 @@
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"@/*": [
"./src/*"
],
"*": [ "*": [
"./src/*" "./src/*"
] ]