14. React-проект на Webpack
Настройка React приложения с TypeScript и Webpack с нуля — важный навык. В этом уроке мы построим полный production-ready конфиг шаг за шагом, включая Hot Reloading, оптимизации и все необходимые инструменты.
Структура проекта
Заголовок раздела «Структура проекта»react-webpack-app/├── public/│ └── index.html├── src/│ ├── index.tsx ← Entry point│ ├── App.tsx│ ├── components/│ ├── hooks/│ ├── styles/│ │ └── global.css│ └── types/│ └── declarations.d.ts├── webpack/│ ├── webpack.common.js ← Общая конфигурация│ ├── webpack.dev.js ← Development│ └── webpack.prod.js ← Production├── .babelrc├── tsconfig.json└── package.jsonШаг 1: Установка зависимостей
Заголовок раздела «Шаг 1: Установка зависимостей»# Runtime зависимостиnpm install react react-dom
# TypeScriptnpm install --save-dev typescript @types/react @types/react-dom
# Webpacknpm install --save-dev webpack webpack-cli webpack-dev-server webpack-merge
# Babel (рекомендуем для React)npm install --save-dev babel-loader @babel/core @babel/preset-env \ @babel/preset-react @babel/preset-typescript
# Hot Reloadingnpm install --save-dev @pmmmwh/react-refresh-webpack-plugin react-refresh
# HTMLnpm install --save-dev html-webpack-plugin
# CSSnpm install --save-dev css-loader style-loader mini-css-extract-plugin \ css-minimizer-webpack-plugin
# TypeScript проверкаnpm install --save-dev fork-ts-checker-webpack-plugin
# Минификацияnpm install --save-dev terser-webpack-plugin
# Копирование ресурсовnpm install --save-dev copy-webpack-pluginШаг 2: .babelrc
Заголовок раздела «Шаг 2: .babelrc»{ "presets": [ ["@babel/preset-env", { "targets": { "browsers": ["> 1%", "last 2 versions"] }, "useBuiltIns": "usage", "corejs": 3 }], ["@babel/preset-react", { "runtime": "automatic" }], "@babel/preset-typescript" ], "plugins": []}Шаг 3: tsconfig.json
Заголовок раздела «Шаг 3: tsconfig.json»{ "compilerOptions": { "target": "ES2020", "module": "ESNext", "moduleResolution": "bundler", "strict": true, "jsx": "react-jsx", "baseUrl": ".", "paths": { "@/*": ["src/*"] }, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "skipLibCheck": true, "noEmit": true }, "include": ["src"]}Шаг 4: webpack.common.js
Заголовок раздела «Шаг 4: webpack.common.js»const path = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin');const ForkTsCheckerPlugin = require('fork-ts-checker-webpack-plugin');const CopyPlugin = require('copy-webpack-plugin');
module.exports = { entry: './src/index.tsx', resolve: { extensions: ['.tsx', '.ts', '.js'], alias: { '@': path.resolve(__dirname, '../src') }, }, module: { rules: [{ test: /\\.tsx?$/, use: { loader: 'babel-loader' }, exclude: /node_modules/, }], }, plugins: [ new HtmlWebpackPlugin({ template: './public/index.html' }), new ForkTsCheckerPlugin({ async: true }), new CopyPlugin({ patterns: [{ from: 'public/robots.txt' }] }), ], output: { path: path.resolve(__dirname, '../dist'), assetModuleFilename: 'assets/[hash:8][ext]', clean: true, },};Шаг 5: webpack.dev.js
Заголовок раздела «Шаг 5: webpack.dev.js»const { merge } = require('webpack-merge');const ReactRefreshPlugin = require('@pmmmwh/react-refresh-webpack-plugin');const common = require('./webpack.common');
module.exports = merge(common, { mode: 'development', devtool: 'eval-cheap-module-source-map', devServer: { port: 3000, hot: true, historyApiFallback: true, proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } }, }, module: { rules: [{ test: /\\.css$/, use: ['style-loader', 'css-loader'], }], }, plugins: [new ReactRefreshPlugin()],});Шаг 6: webpack.prod.js
Заголовок раздела «Шаг 6: webpack.prod.js»const { merge } = require('webpack-merge');const MiniCssExtractPlugin = require('mini-css-extract-plugin');const TerserPlugin = require('terser-webpack-plugin');const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');const common = require('./webpack.common');
module.exports = merge(common, { mode: 'production', devtool: 'source-map', output: { filename: '[name].[contenthash:8].js', chunkFilename: '[id].[contenthash:8].js', publicPath: '/', }, module: { rules: [{ test: /\\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader'], }], }, plugins: [ new MiniCssExtractPlugin({ filename: '[name].[contenthash:8].css' }), ], optimization: { minimize: true, minimizer: [new TerserPlugin({ terserOptions: { compress: { drop_console: true } } }), new CssMinimizerPlugin()], splitChunks: { chunks: 'all' }, runtimeChunk: 'single', },});Ниже — интерактивный scaffold генератор React проекта. Выберите опции и получите готовую структуру файлов.