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') }),]Популярные плагины
Заголовок раздела «Популярные плагины»HtmlWebpackPlugin
Заголовок раздела «HtmlWebpackPlugin»Автоматически создаёт HTML файл и вставляет теги <script> и <link> для бандлов:
npm install --save-dev html-webpack-pluginnew HtmlWebpackPlugin({ template: './public/index.html', // Шаблон filename: 'index.html', // Имя выходного файла title: 'My App', // Переменная для EJS шаблона minify: { collapseWhitespace: true, removeComments: true, }, chunks: ['main'], // Только определённые чанки})MiniCssExtractPlugin
Заголовок раздела «MiniCssExtractPlugin»Выносит CSS в отдельные файлы вместо инжекции через <style>:
npm install --save-dev mini-css-extract-pluginconst MiniCssExtractPlugin = require('mini-css-extract-plugin');
// В плагинах:new MiniCssExtractPlugin({ filename: '[name].[contenthash:8].css' })
// В лоадерах — заменяет style-loader:{ test: /\\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader'] }DefinePlugin (встроен в Webpack)
Заголовок раздела «DefinePlugin (встроен в Webpack)»Подставляет глобальные константы на этапе сборки:
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 shakingCopyWebpackPlugin
Заголовок раздела «CopyWebpackPlugin»Копирует статические файлы в dist/:
npm install --save-dev copy-webpack-pluginnew CopyWebpackPlugin({ patterns: [ { from: 'public/robots.txt', to: 'robots.txt' }, { from: 'public/icons', to: 'icons' }, { from: 'src/locales', to: 'locales' }, ],})BundleAnalyzerPlugin
Заголовок раздела «BundleAnalyzerPlugin»Визуализирует размеры бандлов:
npm install --save-dev webpack-bundle-analyzerconst { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
new BundleAnalyzerPlugin({ analyzerMode: 'static', // 'server' | 'static' | 'json' | 'disabled' openAnalyzer: false, reportFilename: 'bundle-report.html',})ProvidePlugin (встроен в Webpack)
Заголовок раздела «ProvidePlugin (встроен в Webpack)»Автоматически загружает модули без явного импорта:
new webpack.ProvidePlugin({ React: 'react', // import React from 'react' везде автоматически $: 'jquery', // jQuery доступен глобально _: ['lodash', 'fp'], // Конкретный экспорт})Порядок выполнения плагинов
Заголовок раздела «Порядок выполнения плагинов»Плагины выполняются на основе хуков компилятора, а не в порядке объявления. Однако некоторые плагины важно порядка придерживаться:
plugins: [ new MiniCssExtractPlugin(), // Должен быть раньше HtmlWebpackPlugin new HtmlWebpackPlugin(), // Использует результат MiniCssExtractPlugin new CopyWebpackPlugin({}),]Ниже — интерактивная демонстрация эффекта каждого плагина на результат сборки.