Перейти к содержимому

13. TypeScript с Webpack

Webpack поддерживает TypeScript через два основных подхода: ts-loader (официальный) и babel-loader с @babel/preset-typescript. Каждый имеет свои преимущества, и выбор зависит от требований проекта.

ts-loader вызывает TypeScript compiler (tsc) напрямую:

Окно терминала
npm install --save-dev typescript ts-loader
webpack.config.js
module: {
rules: [{
test: /\\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
}],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
{
"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:

{
loader: 'ts-loader',
options: {
transpileOnly: true, // Только транспиляция, без проверки типов
happyPackMode: true, // Для parallel-webpack
experimentalWatchApi: true,
},
}

Проверку типов перенесите в отдельный процесс:

Окно терминала
npm install --save-dev fork-ts-checker-webpack-plugin
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
plugins: [
new ForkTsCheckerWebpackPlugin({
async: true, // Не блокировать сборку
typescript: {
diagnosticOptions: {
semantic: true,
syntactic: true,
},
},
}),
]

Babel просто удаляет TypeScript типы без проверки (только транспиляция):

Окно терминала
npm install --save-dev @babel/preset-typescript babel-loader @babel/core @babel/preset-env
webpack.config.js
{
test: /\\.tsx?$/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react',
'@babel/preset-typescript',
],
},
},
exclude: /node_modules/,
}

Babel не поддерживает некоторые TypeScript возможности:

  • const enum — используйте обычный enum или declare const enum
  • namespace — используйте module
  • export = / import = — используйте ES импорты
  • Декораторы (experimental) — нужен @babel/plugin-proposal-decorators
Характеристикаts-loaderbabel-loader + TS
Проверка типов✅ Полная❌ Отсутствует (нужен fork-ts-checker)
СкоростьМедленнееБыстрее
КонфигурацияПрощеГибче
ДекораторыНативная поддержкаНужен плагин
const enum
React JSXНужен tsxНужен preset-react

Если в tsconfig.json настроены paths, нужно дублировать в resolve.alias:

// tsconfig.json
{
"paths": {
"@/*": ["src/*"],
"@api/*": ["src/api/*"]
}
}
// webpack.config.js
const 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-plugin
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
resolve: {
plugins: [new TsconfigPathsPlugin()],
}
// Автоматически читает paths из tsconfig.json!
// 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 конфигурации.