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

5. Plugins: расширение функций

Если Loaders трансформируют отдельные файлы, то Plugins работают на уровне всего процесса сборки. Они могут вмешиваться в любую фазу работы Webpack: от инициализации до записи файлов. Плагины делают Webpack по-настоящему мощным инструментом.

Плагин — это объект с методом apply(compiler), который принимает компилятор и подписывается на его хуки:

class MyPlugin {
apply(compiler) {
compiler.hooks.done.tap('MyPlugin', (stats) => {
console.log('Build complete!', stats.toJson().time, 'ms');
});
}
}

В конфиге плагины передаются как инстансы:

plugins: [
new HtmlWebpackPlugin({ template: './public/index.html' }),
new MiniCssExtractPlugin({ filename: '[name].[contenthash].css' }),
new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('production') }),
]

Автоматически создаёт HTML файл и вставляет теги <script> и <link> для бандлов:

Окно терминала
npm install --save-dev html-webpack-plugin
new HtmlWebpackPlugin({
template: './public/index.html', // Шаблон
filename: 'index.html', // Имя выходного файла
title: 'My App', // Переменная для EJS шаблона
minify: {
collapseWhitespace: true,
removeComments: true,
},
chunks: ['main'], // Только определённые чанки
})

Выносит CSS в отдельные файлы вместо инжекции через <style>:

Окно терминала
npm install --save-dev mini-css-extract-plugin
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// В плагинах:
new MiniCssExtractPlugin({ filename: '[name].[contenthash:8].css' })
// В лоадерах — заменяет style-loader:
{ test: /\\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader'] }

Подставляет глобальные константы на этапе сборки:

new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
'process.env.API_URL': JSON.stringify('https://api.example.com'),
__DEV__: process.env.NODE_ENV !== 'production',
BUILD_TIMESTAMP: Date.now(),
})
// В коде:
if (__DEV__) { console.log('development mode'); }
// После сборки:
if (false) { console.log('development mode'); } // удалится при tree shaking

Копирует статические файлы в dist/:

Окно терминала
npm install --save-dev copy-webpack-plugin
new CopyWebpackPlugin({
patterns: [
{ from: 'public/robots.txt', to: 'robots.txt' },
{ from: 'public/icons', to: 'icons' },
{ from: 'src/locales', to: 'locales' },
],
})

Визуализирует размеры бандлов:

Окно терминала
npm install --save-dev webpack-bundle-analyzer
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
new BundleAnalyzerPlugin({
analyzerMode: 'static', // 'server' | 'static' | 'json' | 'disabled'
openAnalyzer: false,
reportFilename: 'bundle-report.html',
})

Автоматически загружает модули без явного импорта:

new webpack.ProvidePlugin({
React: 'react', // import React from 'react' везде автоматически
$: 'jquery', // jQuery доступен глобально
_: ['lodash', 'fp'], // Конкретный экспорт
})

Плагины выполняются на основе хуков компилятора, а не в порядке объявления. Однако некоторые плагины важно порядка придерживаться:

plugins: [
new MiniCssExtractPlugin(), // Должен быть раньше HtmlWebpackPlugin
new HtmlWebpackPlugin(), // Использует результат MiniCssExtractPlugin
new CopyWebpackPlugin({}),
]

Ниже — интерактивная демонстрация эффекта каждого плагина на результат сборки.