13. TypeScript с Webpack
Webpack поддерживает TypeScript через два основных подхода: ts-loader (официальный) и babel-loader с @babel/preset-typescript. Каждый имеет свои преимущества, и выбор зависит от требований проекта.
Подход 1: ts-loader
Заголовок раздела «Подход 1: ts-loader»ts-loader вызывает TypeScript compiler (tsc) напрямую:
npm install --save-dev typescript ts-loadermodule: { rules: [{ test: /\\.tsx?$/, use: 'ts-loader', exclude: /node_modules/, }],},resolve: { extensions: ['.tsx', '.ts', '.js'],},Конфигурация tsconfig.json
Заголовок раздела «Конфигурация tsconfig.json»{ "compilerOptions": { "target": "ES2020", "module": "ESNext", "moduleResolution": "bundler", "strict": true, "jsx": "react-jsx", "outDir": "./dist", "baseUrl": ".", "paths": { "@/*": ["src/*"], "@components/*": ["src/components/*"] }, "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"]}ts-loader: transpileOnly режим
Заголовок раздела «ts-loader: transpileOnly режим»По умолчанию ts-loader выполняет полную проверку типов при каждой компиляции — это медленно. Для разработки используйте transpileOnly:
{ loader: 'ts-loader', options: { transpileOnly: true, // Только транспиляция, без проверки типов happyPackMode: true, // Для parallel-webpack experimentalWatchApi: true, },}Проверку типов перенесите в отдельный процесс:
npm install --save-dev fork-ts-checker-webpack-pluginconst ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
plugins: [ new ForkTsCheckerWebpackPlugin({ async: true, // Не блокировать сборку typescript: { diagnosticOptions: { semantic: true, syntactic: true, }, }, }),]Подход 2: babel-loader + @babel/preset-typescript
Заголовок раздела «Подход 2: babel-loader + @babel/preset-typescript»Babel просто удаляет TypeScript типы без проверки (только транспиляция):
npm install --save-dev @babel/preset-typescript babel-loader @babel/core @babel/preset-env{ test: /\\.tsx?$/, use: { loader: 'babel-loader', options: { presets: [ '@babel/preset-env', '@babel/preset-react', '@babel/preset-typescript', ], }, }, exclude: /node_modules/,}Ограничения babel + TypeScript
Заголовок раздела «Ограничения babel + TypeScript»Babel не поддерживает некоторые TypeScript возможности:
const enum— используйте обычныйenumилиdeclare const enumnamespace— используйтеmoduleexport =/import =— используйте ES импорты- Декораторы (experimental) — нужен
@babel/plugin-proposal-decorators
Сравнение подходов
Заголовок раздела «Сравнение подходов»| Характеристика | ts-loader | babel-loader + TS |
|---|---|---|
| Проверка типов | ✅ Полная | ❌ Отсутствует (нужен fork-ts-checker) |
| Скорость | Медленнее | Быстрее |
| Конфигурация | Проще | Гибче |
| Декораторы | Нативная поддержка | Нужен плагин |
const enum | ✅ | ❌ |
| React JSX | Нужен tsx | Нужен preset-react |
Path Aliases в Webpack
Заголовок раздела «Path Aliases в Webpack»Если в tsconfig.json настроены paths, нужно дублировать в resolve.alias:
// tsconfig.json{ "paths": { "@/*": ["src/*"], "@api/*": ["src/api/*"] }}
// webpack.config.jsconst path = require('path');
resolve: { alias: { '@': path.resolve(__dirname, 'src'), '@api': path.resolve(__dirname, 'src/api'), },}Или использовать tsconfig-paths-webpack-plugin:
npm install --save-dev tsconfig-paths-webpack-pluginconst TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
resolve: { plugins: [new TsconfigPathsPlugin()],}// Автоматически читает paths из tsconfig.json!Declaration files для Webpack
Заголовок раздела «Declaration files для Webpack»// typings/declarations.d.ts — типы для нетипизированных ресурсовdeclare module '*.svg' { const content: string; export default content; }declare module '*.png' { const content: string; export default content; }declare module '*.css' { const styles: Record<string, string>; export default styles; }declare module '*.module.css' { const styles: Record<string, string>; export default styles; }Ниже — интерактивный конструктор TypeScript + Webpack конфигурации.