From 1376a20c90ecb27a565d556aa6c81262ecd87ff2 Mon Sep 17 00:00:00 2001 From: Ilia Mashkov Date: Wed, 19 Nov 2025 09:59:39 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D0=B0=D1=8F=20=D0=BA=D0=BE=D0=BD=D1=84=D0=B8=D0=B3=D1=83?= =?UTF-8?q?=D1=80=D0=B0=D1=86=D0=B8=D1=8F=20webpack=20=D1=81=20React=2019?= =?UTF-8?q?=20=D0=B8=20TypeScript=205?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Создана модульная архитектура webpack конфигурации в config/build/ - Настроены loader'ы: Babel, TypeScript, CSS/SCSS, File, SVGR - Добавлены плагины: HtmlWebpackPlugin, MiniCssExtractPlugin, ReactRefresh, BundleAnalyzer - Настроен dev-сервер с HMR и поддержкой SPA роутинга - Добавлена полная JSDoc документация на русском языке --- config/build/buildDevServer.ts | 30 ++++++++ config/build/buildLoaders.ts | 37 ++++++++++ config/build/buildPlugins.ts | 72 +++++++++++++++++++ config/build/buildResolvers.ts | 36 ++++++++++ config/build/buildWebpackConfig.ts | 60 ++++++++++++++++ config/build/loaders/buildBabelLoader.ts | 30 ++++++++ config/build/loaders/buildCssLoader.ts | 43 +++++++++++ config/build/loaders/buildFileLoader.ts | 27 +++++++ config/build/loaders/buildSvgrLoader.ts | 24 +++++++ config/build/loaders/buildTypescriptLoader.ts | 23 ++++++ config/build/types/config.ts | 54 ++++++++++++++ webpack.config.ts | 57 +++++++++++++++ 12 files changed, 493 insertions(+) create mode 100644 config/build/buildDevServer.ts create mode 100644 config/build/buildLoaders.ts create mode 100644 config/build/buildPlugins.ts create mode 100644 config/build/buildResolvers.ts create mode 100644 config/build/buildWebpackConfig.ts create mode 100644 config/build/loaders/buildBabelLoader.ts create mode 100644 config/build/loaders/buildCssLoader.ts create mode 100644 config/build/loaders/buildFileLoader.ts create mode 100644 config/build/loaders/buildSvgrLoader.ts create mode 100644 config/build/loaders/buildTypescriptLoader.ts create mode 100644 config/build/types/config.ts create mode 100644 webpack.config.ts diff --git a/config/build/buildDevServer.ts b/config/build/buildDevServer.ts new file mode 100644 index 0000000..db9e313 --- /dev/null +++ b/config/build/buildDevServer.ts @@ -0,0 +1,30 @@ +import { Configuration as DevServerConfiguration } from 'webpack-dev-server' + +import { BuildOptions } from './types/config' + +/** + * Конфигурация webpack-dev-server для режима разработки + * + * Настраивает локальный сервер разработки с поддержкой: + * - Hot Module Replacement (HMR) - горячая перезагрузка модулей + * - History API Fallback - поддержка клиентского роутинга (SPA) + * - Автоматическое открытие браузера + * + * @param {BuildOptions} options - Опции сборки + * @param {number} options.port - Порт для запуска сервера (по умолчанию 3000) + * @param {boolean} options.open - Автоматически открывать браузер при запуске + * @returns {DevServerConfiguration} Конфигурация webpack-dev-server + * + * @example + * // Запуск: pnpm dev + * // Сервер будет доступен на http://localhost:3000 + */ +export function buildDevServer(options: BuildOptions): DevServerConfiguration { + const { port, open } = options + return { + port, + open, + historyApiFallback: true, + hot: true, + } +} diff --git a/config/build/buildLoaders.ts b/config/build/buildLoaders.ts new file mode 100644 index 0000000..715bd74 --- /dev/null +++ b/config/build/buildLoaders.ts @@ -0,0 +1,37 @@ +import webpack from 'webpack' + +import { buildBabelLoader } from './loaders/buildBabelLoader' +import { buildCssLoader } from './loaders/buildCssLoader' +import { buildFileLoader } from './loaders/buildFileLoader' +import { buildSvgrLoader } from './loaders/buildSvgrLoader' +import { buildTypescriptLoader } from './loaders/buildTypescriptLoader' +import { BuildOptions } from './types/config' + +/** + * Собирает все webpack loaders в единый массив + * + * Порядок loaders важен! Webpack применяет их справа налево (снизу вверх). + * Текущий порядок: + * 1. fileLoader - обрабатывает изображения и шрифты + * 2. svgrLoader - преобразует SVG в React компоненты + * 3. babelLoader - транспилирует JS/JSX/TSX с React Refresh + * 4. typescriptLoader - компилирует TypeScript + * 5. cssLoader - обрабатывает CSS/SCSS с модулями + * + * @param {BuildOptions} options - Опции сборки + * @param {boolean} options.isDev - Флаг режима разработки + * @returns {webpack.RuleSetRule[]} Массив правил для webpack + */ +export function buildLoaders({ isDev }: BuildOptions): webpack.RuleSetRule[] { + const babelLoader = buildBabelLoader(isDev) + + const fileLoader = buildFileLoader() + + const svgrLoader = buildSvgrLoader() + + const typescriptLoader = buildTypescriptLoader() + + const cssLoader = buildCssLoader(isDev) + + return [fileLoader, svgrLoader, babelLoader, typescriptLoader, cssLoader] +} diff --git a/config/build/buildPlugins.ts b/config/build/buildPlugins.ts new file mode 100644 index 0000000..1859e37 --- /dev/null +++ b/config/build/buildPlugins.ts @@ -0,0 +1,72 @@ +import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin' +import HtmlWebpackPlugin from 'html-webpack-plugin' +import MiniCssExtractPlugin from 'mini-css-extract-plugin' +import webpack from 'webpack' +import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer' + +import { BuildOptions } from './types/config' + +/** + * Конфигурация webpack плагинов + * + * Собирает все необходимые плагины для сборки приложения. + * + * Плагины для всех режимов: + * - HtmlWebpackPlugin: генерирует HTML файл и автоматически подключает скрипты + * - MiniCssExtractPlugin: извлекает CSS в отдельные файлы с хешами для кеширования + * - ProgressPlugin: показывает прогресс сборки в консоли + * - DefinePlugin: определяет глобальные константы для использования в коде + * + * Плагины только для разработки: + * - BundleAnalyzerPlugin: анализирует размер бандла (не открывается автоматически) + * - ReactRefreshWebpackPlugin: обеспечивает быструю перезагрузку React компонентов + * - HotModuleReplacementPlugin: включает горячую замену модулей (HMR) + * + * @param {BuildOptions} options - Опции сборки + * @param {BuildPaths} options.paths - Пути проекта + * @param {boolean} options.isDev - Флаг режима разработки + * @param {string} options.apiUrl - URL API для глобальной переменной __API__ + * @param {string} options.project - Тип проекта для глобальной переменной __PROJECT__ + * @returns {webpack.WebpackPluginInstance[]} Массив плагинов webpack + * + * @example + * // Глобальные константы доступны в коде: + * if (__IS_DEV__) { + * console.log('Development mode') + * } + * + * fetch(__API__ + '/users') + */ +export function buildPlugins({ + paths, + isDev, + apiUrl, + project, +}: BuildOptions): webpack.WebpackPluginInstance[] { + const plugins = [ + new HtmlWebpackPlugin({ + template: paths.html, + }), + new MiniCssExtractPlugin({ + filename: 'css/[name].[contenthash:8].css', + chunkFilename: 'css/[name].[contenthash:8].css', + }), + new webpack.ProgressPlugin(), + new webpack.DefinePlugin({ + __IS_DEV__: JSON.stringify(isDev), + __API__: JSON.stringify(apiUrl), + __PROJECT__: JSON.stringify(project), + }), + ] + + if (isDev) { + plugins.push( + new BundleAnalyzerPlugin({ + openAnalyzer: false, + }) + ) + plugins.push(new ReactRefreshWebpackPlugin({ overlay: false })) + plugins.push(new webpack.HotModuleReplacementPlugin()) + } + return plugins +} diff --git a/config/build/buildResolvers.ts b/config/build/buildResolvers.ts new file mode 100644 index 0000000..e7a04d4 --- /dev/null +++ b/config/build/buildResolvers.ts @@ -0,0 +1,36 @@ +import webpack from 'webpack' + +import { BuildOptions } from './types/config' + +/** + * Конфигурация разрешения модулей для webpack + * + * Определяет, как webpack будет искать и разрешать импорты модулей. + * + * Настройки: + * - extensions: автоматически разрешает указанные расширения файлов + * - preferAbsolute: предпочитает абсолютные пути относительным + * - modules: директории для поиска модулей + * - mainFiles: имена файлов по умолчанию при импорте директории + * - alias: алиасы для упрощения импортов (можно расширить) + * + * @param {BuildOptions} options - Опции сборки + * @param {BuildPaths} options.paths - Пути проекта + * @returns {webpack.ResolveOptions} Конфигурация resolve для webpack + * + * @example + * // Благодаря extensions можно писать: + * import Component from './Component' // вместо './Component.tsx' + * + * // Благодаря mainFiles можно писать: + * import utils from './utils' // вместо './utils/index.ts' + */ +export function buildResolvers(options: BuildOptions): webpack.ResolveOptions { + return { + extensions: ['.tsx', '.ts', '.js'], + preferAbsolute: true, + modules: [options.paths.src, 'node_modules'], + mainFiles: ['index'], + alias: {}, + } +} diff --git a/config/build/buildWebpackConfig.ts b/config/build/buildWebpackConfig.ts new file mode 100644 index 0000000..55eab69 --- /dev/null +++ b/config/build/buildWebpackConfig.ts @@ -0,0 +1,60 @@ +import webpack from 'webpack' + +import { buildDevServer } from './buildDevServer' +import { buildLoaders } from './buildLoaders' +import { buildPlugins } from './buildPlugins' +import { buildResolvers } from './buildResolvers' +import { BuildOptions } from './types/config' + +/** + * Главная функция сборки конфигурации webpack + * + * Объединяет все модули конфигурации (loaders, plugins, resolvers, devServer) + * в единую конфигурацию webpack. + * + * Основные настройки: + * - mode: режим сборки (development/production) + * - entry: точка входа приложения (src/index.tsx) + * - output: настройки выходных файлов с хешами для кеширования + * - module.rules: правила обработки различных типов файлов + * - resolve: настройки разрешения модулей + * - plugins: плагины для расширения функциональности webpack + * - devtool: source maps для отладки (только в dev режиме) + * - devServer: настройки dev-сервера (только в dev режиме) + * + * @param {BuildOptions} options - Полные опции сборки + * @returns {webpack.Configuration} Готовая конфигурация webpack + * + * @example + * const config = buildWebpackConfig({ + * mode: 'development', + * paths: { entry: 'src/index.tsx', ... }, + * isDev: true, + * port: 3000, + * open: true, + * apiUrl: 'http://localhost:8000', + * project: 'frontend' + * }) + */ +export function buildWebpackConfig( + options: BuildOptions +): webpack.Configuration { + const { mode, paths, isDev } = options + return { + mode, + entry: paths.entry, + output: { + path: paths.build, + filename: '[name].[contenthash].js', + clean: true, + publicPath: '/', + }, + module: { + rules: buildLoaders(options), + }, + resolve: buildResolvers(options), + plugins: buildPlugins(options), + devtool: isDev ? 'inline-source-map' : undefined, + devServer: isDev ? buildDevServer(options) : undefined, + } +} diff --git a/config/build/loaders/buildBabelLoader.ts b/config/build/loaders/buildBabelLoader.ts new file mode 100644 index 0000000..dd437b1 --- /dev/null +++ b/config/build/loaders/buildBabelLoader.ts @@ -0,0 +1,30 @@ +/** + * Конфигурация Babel loader для webpack + * + * Обрабатывает файлы JavaScript, JSX и TSX с помощью Babel. + * В режиме разработки включает React Refresh для горячей перезагрузки компонентов. + * + * @param {boolean} isDev - Флаг режима разработки + * @returns {Object} Конфигурация babel-loader + * + * @example + * const babelLoader = buildBabelLoader(true) + * // Возвращает loader с React Refresh для разработки + */ +export function buildBabelLoader(isDev: boolean) { + const babelLoader = { + test: /\.(js|jsx|tsx)$/, + exclude: /node_modules/, + use: { + loader: 'babel-loader', + options: { + presets: ['@babel/preset-env'], + plugins: [isDev && require.resolve('react-refresh/babel')].filter( + Boolean + ), + }, + }, + } + + return babelLoader +} diff --git a/config/build/loaders/buildCssLoader.ts b/config/build/loaders/buildCssLoader.ts new file mode 100644 index 0000000..3d0cefb --- /dev/null +++ b/config/build/loaders/buildCssLoader.ts @@ -0,0 +1,43 @@ +import MiniCssExtractPlugin from 'mini-css-extract-plugin' + +/** + * Конфигурация CSS/SCSS loader для webpack + * + * Обрабатывает файлы .css, .scss и .sass с поддержкой CSS модулей. + * В режиме разработки использует style-loader для инъекции стилей в DOM. + * В режиме production использует MiniCssExtractPlugin для извлечения CSS в отдельные файлы. + * + * CSS модули автоматически включаются для файлов с паттерном *.module.* + * + * @param {boolean} isDev - Флаг режима разработки + * @returns {Object} Конфигурация css-loader с поддержкой SCSS и CSS модулей + * + * @example + * // Для файла Button.module.scss будут применены CSS модули + * // Для файла global.scss CSS модули не применяются + */ +export const buildCssLoader = (isDev: boolean) => { + const cssLoader = { + test: /\.s[ac]ss$/i, + use: [ + // Создает