Децентрализованная конфигурация webpack или как упростить сборку проекта 02.02.2022 11:47
Довольно частая ситуация, когда с ростом проекта растёт и сложность его сборки. Широкий зоопарк технологий, сторонние компоненты, библиотеки, линтеры, серверный рендеринг и нюансы, связанные с конкретным проектом, — всё это в итоге приводит к тому, что конфигурация сборки достигает более тысячи строк.
Если провести аналогию с обычным кодом, то достижение таких объёмов в рамках одного модуля/класса/компонента/сущности становится сигналом, чтобы заняться декомпозицией и разделить ответственность по более мелким и независимым составляющим.
Но если говорить о конфигурации сборки, то такая декомпозиция скорее редкость, и в больших проектах часто можно встретить огромные webpack.config.js, модификация которых может доставить немало проблем и привести к ошибкам.
Если вам хочется сделать работу со сборкой проще и надёжнее при модификациях, то добро пожаловать под кат.
На старте мы имеем большой файл конфигурации webpack.config.js, в котором описана вся сборка. Примерно такой:
const path = require('path'); const webpack = require('webpack'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); const TerserPlugin = require('terser-webpack-plugin'); const CopyPlugin = require('copy-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = function (env) < env = env || <>; const isDev = !!env.development; const isProd = !!env.production; const config = < mode: isProd ? 'production' : 'development', devtool: 'source-map', entry: < app: [ './src/index.tsx' ], >, output: < filename: isDev ? 'js/[name].js' : 'js/[name]-[chunkhash:7].js', path: path.resolve(__dirname, '../dist/static/'), publicPath: '/' >, module: < rules: [ < test: /\.tsx?$/, use: [ < loader: 'thread-loader', options: < workers: require('os').cpus().length - 2, >, >, < loader: 'ts-loader', options: < configFile: path.resolve(__dirname, 'tsconfig.json'), happyPackMode: true, transpileOnly: true, onlyCompileBundledFiles: true, >> ], >, < test: /\.jsx?$/, use: [ < loader: 'babel-loader', options: < presets: ['@babel/preset-env'] >> ], >, < test: /\.css$/, use: [ < loader: MiniCssExtractPlugin.loader, options: < publicPath: './', >, >, 'css-loader', 'postcss-loader', ], >, < test: /\.scss/, use: [ < loader: MiniCssExtractPlugin.loader, options: < publicPath: './', >, >, < loader: 'css-loader', options: < importLoaders: 1, modules: < localIdentName: '[name]_[local]_[hash:base64:5]', >, sourceMap: true, >, >, < loader: 'postcss-loader', options: < sourceMap: true, >, >, 'sass-loader', ], >, < test: /\.(woff|woff2|eot|ttf)$/, use: 'file-loader?name=assets/fonts/[name].[hash].[ext]', >, < test: /\.svg$/, include: /src\/assets\/icons/, use: [ < loader: 'svg-sprite-loader', options: < symbolId: 'svg-icon-[name]', >, >, < loader: 'svgo-loader', options: < plugins: [ < removeTitle: true >, < removeUselessStrokeAndFill: true >, < removeComments: true >, < convertPathData: false >, ] >, >, ], >, < test: /\.svg$/, exclude: /src\/assets\/icons/, use: [ < loader: 'url-loader', options: < limit: 10, mimetype: 'image/png', name: '[name].[hash:base64:5].[ext]', >, >, < loader: 'svgo-loader', options: < plugins: [ < removeTitle: true >, < removeUselessStrokeAndFill: true >, < removeComments: true >, < convertPathData: false >, ] >, >, ], >, < test: /\.(png|jpg|gif)$/, use: 'url-loader?limit=10&mimetype=image/[ext]&name=images/[name].[hash:base64:5].[ext]', >, ], >, resolve: < extensions: ['.ts', '.tsx', '.js', '.jsx'], alias: < '@components': path.resolve(__dirname, '../src/components'), >, plugins: [new TsconfigPathsPlugin()] >, optimization: < splitChunks: < cacheGroups: < vendor: < test: (item) =>/node_modules\/.*/.test(item.userRequest), name: 'vendor', chunks: 'initial', enforce: true, >, icons: < test: (item) =>/(base\/)?src\/assets\/icons\/.*/.test(item.userRequest), name: 'icons', chunks: 'initial', enforce: true, >, > >, minimizer: [ new TerserPlugin(< parallel: true, terserOptions: < output: < comments: false, >, compress: < passes: 3, unused: true, dead_code: true, drop_debugger: true, conditionals: true, evaluate: true, sequences: true, booleans: true, >>, >), ], >, plugins: [ new MiniCssExtractPlugin(< filename: isDev ? 'css/[name].css' : 'css/[name]-[chunkhash:7].css' >), new CopyPlugin(< patterns: [ < from: './src/assets/static', to: './static' >, ], >), new webpack.DefinePlugin(< 'process.env.NODE_ENV': JSON.stringify(isDev ? (process.env.NODE_ENV || 'development') : 'production') >), new HtmlWebpackPlugin(< template: './src/index.html', >), ], stats: 'errors-only', >; if (isDev) < config.devServer = < contentBase: path.join(__dirname, '../dist'), port: 3000, compress: true, hot: true, historyApiFallback: true, disableHostCheck: true, proxy: [ < context: [], target: 'http://api.example.com', changeOrigin: true, secure: false, onProxyReq: (proxyReq) =>< proxyReq.setHeader('Origin', 'http://api.example.com'); >, cookieDomainRewrite: < '*': 'localhost' >, > ] >; > return config; >;
Этот пример что-то вроде «джентльменского набора» для простоты понимания. Он может быть чуть меньше при определённых условиях, но скорее всего будет ощутимо больше в зависимости от сложности самого проекта.
Для начала создадим директорию webpack и файл index.js в ней. И перенесём всё содержимое webpack.config.js в этот файл. В самом же webpack.config.js оставим только подключение этого нового файла:
module.exports = require('./webpack');
Это нужно, чтобы вся конфигурация была сосредоточена внутри директории webpack, и чтобы во всех последующих require не дублировать директорию webpack в пути.
Далее давайте договоримся так: под каждый элемент верхнего уровня объекта конфигурации мы создаём свою директорию и файл index.js, в каждом из которых описываем соответствующую часть конфигурации. Например entry/index.js:
module.exports = < app: [ './src/index.tsx' ], >;
Если требуется передавать дополнительные параметры (например isDev), то оборачиваем модуль в функцию, принимающую требуемые нам параметры. Например, output/index.js:
const path = require('path'); module.exports = (isDev) => (< filename: isDev ? 'js/[name].js' : 'js/[name]-[chunkhash:7].js', path: path.resolve(__dirname, '../../dist/static/'), publicPath: '/' >);
В главном файле webpack/index.js просто собираем их вместе:
module.exports = function (env) < env = env || <>; const isDev = !!env.development; const isProd = !!env.production; const config = < mode: isProd ? 'production' : 'development', devtool: 'source-map', entry: require('./entries'), output: require('./output')(isDev), module: require('./module'), resolve: require('./resolve'), optimization: require('./optimization'), plugins: require('./plugins')(isDev), stats: 'errors-only', >; if (isDev) < config.devServer = require('./dev-server'); >return config; >;
Внутри каждой из этих поддиректорий можно продолжать декомпозицию до степени, которая будет наиболее удобна для вас (без доведения до абсурда и разложения конфигурации на атомы, конечно).
Например, webpack/module/index.js может выглядеть так:
module.exports = < rules: [ require('./loaders/typescriptLoader'), require('./loaders/jsLoader'), require('./loaders/cssLoader'), require('./loaders/sassLoader'), require('./loaders/fontLoader'), require('./loaders/svgLoader'), require('./loaders/imageLoader'), ] >;
Для примера webpack/module/loaders/typescriptLoader.js будет таким:
module.exports = < test: /\.tsx?$/, use: [ < loader: 'thread-loader', options: < workers: require('os').cpus().length - 2, >, >, < loader: 'ts-loader', options: < configFile: path.resolve(__dirname, 'tsconfig.json'), happyPackMode: true, transpileOnly: true, onlyCompileBundledFiles: true, >> ], >;
Также не забываем, что при необходимости всегда можно обернуть любой из подмодулей конфигурации в функцию и передать туда необходимые опции.
Теперь остаётся только подключить его в webpack.config.js:
require('./webpack');
Кроме прочего, подход с вынесением в отдельные модули конфигураций для каждого лоадера, плагина, алиасов и так далее позволяет без лишнего дублирования собирать кастомные сборки, если того требуют поставленные задачи.
Например, один из распространённых случаев — отдельная сборка для серверного рендеринга. Для этого можно описать две различных сборки, каждая из которых будет содержать свою специфику, но в общих чертах будет выглядеть как webpack/index.js. Например, webpack/client.js и webpack/server.js для клиентской и серверной сборки соответственно.
А webpack/index.js в свою очередь берёт на себя роль «собирателя» этих сборок, то есть на основе тех или иных признаков решает, какую сборку (или все сразу) нужно запустить в тот или иной момент времени.
Например, он может это делать на основании параметров, переданных в команду запуска:
module.exports = function (env, options) < const buildParams = options.build.split(','); const builds = []; if (buildParams.includes('client')) < builds.push(require('./client')(env, options)); >if (buildParams.includes('server')) < builds.push(require('./server')(env, options)); >return builds; >;
В package.json для различных вариантов сборки можно добавить отдельные команды в секцию scripts:
Если команда разрабатывает одновременно несколько проектов с примерно одним стеком и сборкой, то можно вынести конфигурацию webpack в отдельный npm-пакет. Его можно хранить как в публичном npm registry, так и во внутреннем, если не хочется выносить вовне конфигурацию своей сборки.
Это даёт несколько приятных преимуществ:
- Избавление от дублирования конфигурации в разных проектах. При исправлении ошибок, оптимизации сборки и прочего все изменения будут касаться сразу всех проектов. Не придётся делать это руками для каждого.
- Обновление зависимостей, касающихся сборки, будет проходить централизовано и относиться сразу ко всем проектам.
- Сами зависимости будут спрятаны за фасадом нашего npm-модуля, что позволит визуально разгрузить package.json конечных проектов.
Всё, что потребуется для подключения сборки к конечному проекту, — проинсталлировать пакет с конфигурацией:
$ npm install my-best-webpack-config --save-dev
И подключить его в webpack.config.js:
require('my-best-webpack-config');
В том случае, если ваши проекты всё-таки имеют небольшие отличия в сборке, то их можно разрулить опциями в webpack.config.js:
const < getConfig >= require('my-best-webpack-config'); module.exports = getConfig(< option1: 'value1', option2: true, . >);
Предварительно проэкспортировав из модуля с конфигурацией функцию getConfig и обработав опции.
Также можно внести локальные изменения в сборку, расширив объект конфигурации:
const config = require('my-best-webpack-config'); module.exports = < . config, output: < . config.output, publicPath: '/static', >, >;
Или же скомбинировать передачу опций и расширение объекта конфигурации:
const < getConfig >= require('my-best-webpack-config'); const config = getConfig(< option1: 'value1', option2: true, . >); module.exports = < . config, output: < . config.output, publicPath: '/static', >, >;
Заключение
Мы рассмотрели подход, в котором монолитная конфигурация webpack разделяется на мелкие составляющие, а при необходимости из них комбинируются несколько кастомных конфигураций. Дополнительно, если есть потребность, конфигурацию можно вынести в отдельный npm-модуль и использовать на разных проектах.
Конечно, надо понимать, что это всего лишь набор вариантов решения одной конкретной проблемы, а не высеченное в камне руководство по составлению конфигурации webpack. Применять рекомендации можно частично, можно полностью, но нужно чётко понимать проблему перегруженности webpack-конфига. Поэтому для условного домашнего проекта такой подход может стать только усложнением.
Если у вас есть свои рецепты для упрощения больших и сложных сборок, то добро пожаловать в комментарии.
Как собрать проект на Webpack
Webpack — это сборщик модулей для JavaScript-приложений. Он позволяет разделять код на модули, которые затем могут быть импортированы и использованы в других частях приложения. Это полезно для структурирования кода, оптимизации производительности и поддержки сторонних библиотек.
Подробнее о Webpack мы писали в другой статье, а пока давайте создадим простой проект, который складывает два числа, а заодно научимся пользоваться Webpack.
Подготовка
Для начала установите Node.js с официального сайта https://nodejs.org, если у вас его ещё нет. Затем создайте новую папку для проекта и перейдите в нее с помощью командной строки или терминала. В нашем случае это папка two_numbers , но у вас может быть любая другая.
mkdir two_numbers cd two_numbers
Инициализация проекта
Находясь внутри папки, инициализируйте проект с помощью следующей команды:
npm init -y
Эта команда создаст файл package.json , который является основным файлом для управления зависимостями и настройками проекта на Node.js.
Параметр -y означает, что все вопросы, которые обычно задаются при создании файла package.json , будут пропущены, и будут использованы значения по умолчанию. В результате будет создан файл package.json с минимальными настройками, без дополнительного ввода со стороны пользователя.
Он выглядит примерно так:
< "name": "two_numbers", "version": "1.0.0", "description": "", "main": "index.js", "scripts": < "start": "webpack serve", "build": "webpack" >, "keywords": [], "author": "", "license": "ISC", "devDependencies": < "css-loader": "^6.7.3", "style-loader": "^3.3.2", "webpack": "^5.78.0", "webpack-cli": "^5.0.1", "webpack-dev-server": "^4.13.2" >>
Установка webpack, webpack-cli и webpack-dev-server
Установите webpack , webpack-cli и webpack-dev-server с помощью следующей команды:
npm install webpack webpack-cli webpack-dev-server --save-dev
Команда webpack-cli позволит запускать Webpack из терминала.
webpack-dev-server — это удобный сервер разработки с горячей перезагрузкой. Это означает, что при изменении файлов в вашем проекте сервер автоматически пересоберёт сборку и обновит страницу в браузере. Без этого пакета вам придется самостоятельно настраивать сервер разработки и обновлять страницу в браузере после каждого изменения в коде.
О ключе —save-dev мы уже писали в одной из статей журнала.
Установка css-loader и style-loader
Webpack по умолчанию обрабатывает только JavaScript-файлы, поэтому для корректной работы с другими типами файлов, такими как CSS или HTML, необходимы специальные загрузчики и плагины.
css-loader позволяет Webpack обрабатывать и импортировать CSS в JavaScript-файлы. Он интерпретирует @import и url() как import/require() и разрешает их. В результате, после обработки css-loader , ваш CSS будет представлен в виде строки в JavaScript-коде.
style-loader . Поскольку после обработки css-loader ваш CSS превратился в строку JavaScript, style-loader используется для внедрения этих стилей в DOM. style-loader добавляет тег внутри вашего HTML-файла, содержащий все стили, включенные в сборку.
Таким образом, чтобы импортировать CSS в наш проект, нам нужно установить style-loader и css-loader . Для этого выполните следующую команду:
npm install style-loader css-loader --save-dev
Установка html-webpack-plugin
html-webpack-plugin автоматически генерирует HTML-файл на основе шаблона, вставляет туда ссылки на ваши файлы (например, JavaScript и CSS), и сохраняет его в указанной директории (обычно в папке dist )
npm install html-webpack-plugin --save-dev
C подготовкой и установкой закончили, теперь переходим к структуре проекта и коду.
Структура проекта
Для удобства откройте папку с проектом прямо в VS Code через меню Файл→Открыть папку (File→Open Folder). В итоге слева будет находиться структура проекта и все файлы, а справа вы будете их редактировать.

В корне проекта создайте пустой файл webpack.config.js и добавьте туда следующий код базовой конфигурации проекта. Обратите внимание на поясняющие комментарии.
const path = require('path'); // Импортируем модуль "path" для работы с путями файлов const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = < entry: './src/index.js', // Точка входа для сборки проекта output: < filename: 'bundle.js', // Имя выходного файла сборки path: path.resolve(__dirname, 'dist'), // Путь для выходного файла сборки >, module: < rules: [ < test: /\.css$/, // Регулярное выражение для обработки файлов с расширением .css use: ['style-loader', 'css-loader'], // Загрузчики, используемые для обработки CSS-файлов >, ], >, plugins: [ new HtmlWebpackPlugin(< template: './src/index.html', >), ], devServer: < static: < directory: path.join(__dirname, 'dist'), // Каталог для статики >, open: true, // Автоматически открывать браузер >, mode: 'development', // Режим сборки >;
В файле package.json измените поле scripts на следующее:
"scripts": < "start": "webpack serve", "build": "webpack" >,
Это позволит запускать сервер разработки и сборку проекта с помощью кратких и удобных команд npm start и npm run build , вместо того чтобы вводить полные команды в терминал каждый раз.
Теперь создайте внутри проекта папку src , а в ней пустой файл index.js . В этом файле напишем основной код приложения, которое складывает два числа из текстовых полей.
function addNumbers() < const num1 = parseFloat(document.getElementById("number1").value); const num2 = parseFloat(document.getElementById("number2").value); const result = num1 + num2; document.getElementById("result").innerText = `Result: $`; > document.getElementById("calculate").addEventListener("click", addNumbers);
Теперь создайте в той же папке файл index.html и добавьте туда этот код:
Калькулятор сложения
В папке src создайте файл styles.css и добавьте следующий код:
body < display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; margin: 0; >input, button, p
Итоговая структура проекта после всех действий будет выглядеть так:

Теперь ваш проект готов к использованию. Для запуска сервера разработки выполните следующую команду в терминале:
npm start
Webpack автоматически откроет браузер, и вы увидите страницу с текстовыми полями для ввода чисел и кнопкой Add. Также после запуска сервера вы можете перейти по адресу localhost:8082 .
В открывшемся окне ведите два числа и нажмите кнопку Add для выполнения сложения. Результат будет отображаться под кнопкой. Готово!

Так зачем использовать Webpack
Webpack позволяет легко структурировать код, разделяя его на модули и импортируя их при необходимости. Если в дальнейшем вы решите добавить сторонние библиотеки или фреймворки, то Webpack поможет вам интегрировать их в ваш проект, минимизировать размер файла сборки и улучшить производительность. А с использованием webpack-dev-server вы получаете автоматическую перезагрузку страницы при изменении исходного кода, что ускоряет процесс разработки.
В этом примере мы использовали только базовые возможности Webpack, но с его помощью вы можете сделать гораздо больше, например, обрабатывать и минифицировать CSS, использовать различные загрузчики (loaders) и плагины для транспиляции и оптимизации кода.
Если хотите лучше разобраться в Webpack, записывайтесь на курс — там узнаете все подробности и научитесь использовать Webpack как профи.
Дальше
- Что такое Webpack
- Как копировать статические файлы с помощью Webpack
«Доктайп» — журнал о фронтенде. Читайте, слушайте и учитесь с нами.
Читать дальше

Dev Mode в Figma. Быстрый обзор бета-версии
Если вы читаете эту статью, Dev Mode в Figma наконец-то вышел в открытую бету. Быстренько рассказываем, что это такое, и как его включить и настроить.
Раньше верстальщикам была доступна только вкладка Inspect с базовой информацией о стилях конкретного элемента.
Некоторые разработчики не рекомендовали копировать стили оттуда, потому что всегда это работало с нюансами. Пока сложно сказать, насколько стили стали точнее, но работать стало определённо удобнее. Сами Adobe называют Figma новым пространством для разработчиков, с возможностями, которые помогают быстрее переводить дизайн в код. Давайте проверим.
- 10 августа 2023

Горячие клавиши Figma для быстрой работы
Figma — это инструмент для создания дизайна, который очень любят веб-разработчики. Одна из причин, почему Figma так популярна — это горячие клавиши. Они помогают работать быстрее и проще. Давайте рассмотрим самые важные из них.
Скрыть или показать интерфейс Фигмы (Ctrl + \ или ⌘ + \ для Mac)
Эта комбинация клавиш позволяет вам быстро убрать все лишнее с экрана, чтобы вы могли сосредоточиться на своем дизайне. Или, наоборот, показать все элементы интерфейса, если вам нужно что-то найти или изменить.
Быстрый поиск по меню (Ctrl + / или ⌘ + / для Mac)
Эта комбинация клавиш открывает поиск по меню. Это очень удобно, когда вы знаете, что вам нужно, но не помните, где это находится. Просто начните вводить то, что вы ищете, и Figma покажет вам нужный пункт меню. Если пользуетесь Spotlight или PowerToys, вам будет очень удобно.
А если не пользуетесь — попробуйте.
- 7 августа 2023

Старт в Figma для верстальщика
Figma — это онлайн-редактор графики для дизайнеров интерфейсов и веб-разработчиков. Это удобная, бесплатная альтернатива Photoshop.
Большое преимущество платформы — возможность работать прямо в браузере. При этом есть и десктопная версия. Расскажем, что надо знать верстальщику при работе с макетом в Figma.
- 2 августа 2023

Инструменты для работы со шрифтами
Работа со шрифтами и типографикой — важная часть вёрстки текста. Новые шрифты появляются очень часто, за этим сложно уследить. Существует множество инструментов, которые помогают находить нужные шрифты, управлять ими и улучшать внешний вид текста.
Рассмотрим несколько инструментов для работы со шрифтами, которые будут полезны при создании сайта.
- 29 июня 2023

10 горячих клавиш VS Code, которые ускорят вашу работу
Горячие клавиши — добро, польза и экономия времени. Давайте разберёмся, как с их помощью упростить себе жизнь в Visual Studio Code.
- 13 июня 2023

10 лучших тем для VS Code
VS Code — популярный редактор кода со множеством полезных инструментов. Сегодня мы поделимся с вами 10 темами, чтобы работать стало ещё приятнее. Выбирайте на свой вкус и цвет.
- 11 июня 2023

10 полезных плагинов VS Code для вёрстки
Visual Studio Code — один из самых популярных редакторов кода. Его удобно использовать, и у него есть множество полезных расширений, с помощью которых легко оптимизировать работу. Такие плагины помогают допускать меньше ошибок при написании кода, да и значительно сокращают время работы.
Чтобы установить расширения, перейдите во вкладку «Extensions» и в поиске найдите подходящие плагины.
- 9 июня 2023

17 полезных плагинов JavaScript в VS Code
Редактор кода Visual Studio Code помогает быстрее писать код, например, он подчёркивает ошибки красным цветом и показывает подсказки. Но работу можно сделать ещё приятнее, если установить нужное расширение.
Плагинов VS Code много. Здесь мы расскажем об одних из самых популярных — они пригодятся при работе с JavaScript.
- 6 июня 2023

Подборка микроанимаций для фронтенда с CodePen в 2023
⭐ Микроанимация — короткое взаимодействие, которое помогает пользователю лучше сориентироваться в интерфейсе и почувствовать совершенное действие.
Например, нажатие на кнопку лайка в социальных сетях или изменение фона, индикатор загрузки, и многое другое. Микроанимация используется везде, где есть интерфейс пользователя, а именно, веб-сайтах, мобильных приложениях, играх. На примерах с CodePen покажем, какими они бывают.
- 12 апреля 2023

Webpack: инструкция по применению
Webpack — это инструмент для сборки JavaScript-приложений, который также применяется для обработки статических файлов — изображений, шрифтов и других ресурсов. У Webpack множество функций, которые легко расширяются с помощью добавления плагинов.
Копирование статических файлов в каталог сборки — одна из таких функций. Выполнить эту задачу можно несколькими способами, наиболее простой — использование плагина CopyWebpackPlugin . Рассмотрим подробнее, как это делать.
CopyWebpackPlugin позволяет скопировать файлы из одного каталога в другой, сохраняя их иерархию. Для начала установите CopyWebpackPlugin в свой проект:
npm install copy-webpack-plugin --save-dev
После установки настройте конфигурацию Webpack, добавив новый экземпляр плагина в секцию plugins конфига. Пример:
const CopyWebpackPlugin = require('copy-webpack-plugin'); const path = require('path'); module.exports = < // ваша конфигурация Webpack здесь plugins: [ new CopyWebpackPlugin(< patterns: [ < from: path.resolve(__dirname, 'src/assets'), to: path.resolve(__dirname, 'dist/assets') >] >) ] >;
В плагине содержится массив объектов patterns . Каждый объект patterns указывает на исходный файл или каталог назначения, куда копировать файлы. В примере указано, что нужно скопировать все файлы из каталога src/assets в dist/assets во время сборки.
Теперь все статические файлы будут скопированы в каталог сборки при запуске команды npm run build или той, которую вы используете для запуска сборки.
Научитесь работать с webpack и сократите время на разработку, сборку и тестирование проекта.
Копирование нескольких файлов
Для копирования нескольких файлов с помощью плагина CopyWebpackPlugin добавляем каждый каталог или файл в отдельный объект-шаблон в массиве patterns .
Каждый объект-шаблон содержит свойство from , оно указывает путь к файлу или каталогу для копирования. Свойство to — это путь, по которому нужно скопировать файлы или каталоги.
const CopyWebpackPlugin = require('copy-webpack-plugin'); module.exports = < //ваша конфигурация Webpack здесь plugins: [ new CopyWebpackPlugin(< patterns: [ < from: 'src/images', to: 'dist/images' >, < from: 'src/index.html', to: 'dist' >, ], >), ], >;
В примере первый объект-шаблон копирует каталог images из src в dist/images , а второй — копирует файл index.html из src в dist . Добавляйте столько объектов-шаблонов, сколько нужно для копирования всех необходимых файлов и каталогов.
Для более детальной настройки копирования файлов существуют другие опции, доступные в CopyWebpackPlugin , их подробное описание можно прочитать в документации.
Другие способы
Кроме CopyWebpackPlugin , существуют и другие плагины и загрузчики, их также часто называют лоадерами, которые позволяют копировать статические файлы в каталог сборки.
Лоадер file-loader позволяет копировать статические файлы в указанную папку при сборке проекта. Чтобы использовать file-loader , установите его с помощью npm :
npm install file-loader --save-dev
Затем добавьте его в конфигурационный файл webpack.config.js :
module.exports = < // . ваша конфигурация webpack . module: < rules: [ < test: /\.(png|jpe?g|gif)$/i, use: [ < loader: 'file-loader', options: < name: '[name].[ext]', outputPath: 'images/', >, >, ], >, ], >, >;
В этом примере file-loader используется для копирования файлов изображений в каталог images внутри каталога сборки.
Лоадер url-loader работает аналогично file-loader , но может преобразовывать маленькие файлы в Data URL, вместо копирования их в каталог сборки. Это может быть полезно для уменьшения количества запросов к серверу.
Для использования url-loader необходимо его установить:
npm install url-loader --save-dev
Затем добавить в конфигурационный файл webpack.config.js :
module.exports = < module: < rules: [ < test: /\.(png|jpg|gif)$/i, use: [ < loader: 'url-loader', options: < limit: 8192, >, >, ], >, ], >, >;
Поместите файлы, которые хотите скопировать, в соответствующий каталог в вашем проекте, например, в папку src/images . Если размер файла меньше 8 кБ, он будет встроен в виде Data URL. При сборке проекта все файлы будут обработаны и скопированы.
Описанные лоадеры ещё используются в разработке, но рекомендуем ознакомиться с новой версией Webpack и её обновлениями.
- 30 марта 2023
Руководство по Webpack для начинающих
Разработка фронтенда перешла от традиционного к модульному подходу, при этом улучшился процесс инкапсуляции и усовершенствовалась структура кодовых баз. Инструментарий стал важной частью любого проекта, и сейчас существует множество возможных вариантов инструментов. Но браузер распознает только элементы, относящиеся к HTML, CSS и JavaScript. Поэтому в современных рабочих процессах важную роль играют пакеты модулей, а понимание инструментария остается ключевой частью любого проекта.
Webpack приобрел популярность за последние несколько лет благодаря своей гибкой конфигурации и масштабируемости, но некоторые разработчики считают процесс его настройки запутанным и сложным.
Что такое Webpack?
Webpack — это статический сборщик модулей. Его основная задача — пакетирование файлов JavaScript для использования в браузере, но он также способен преобразовывать, связывать и упаковывать практически любые ресурсы.
Webpack используется затем, чтобы собрать все зависимости, которые включают не только код, но и другие ресурсы, и создать граф зависимостей. Сборщик может работать только с JS-файлами, поэтому webpack должен предварительно обработать все остальные файлы и ресурсы, прежде чем они попадут в пакет.
Что такое граф зависимостей в Webpack?
Если какой-либо файл зависит от любого другого типа файлов, таких как JavaScript, CSS /SCSS, а также некодовых ресурсов, таких как изображения, SVG, веб-шрифты и т. д. в вашем приложении, то webpack рассматривает его как зависимость.
Когда webpack пакетирует приложение, он начинает с точки входа в файле webpack.config.js и рекурсивно строит граф зависимостей, который включает все зависимости, необходимые приложению. Он собирает их в один или несколько файлов в зависимости от потребностей, после чего они загружаются браузером.
Базовые понятия
Entry
Свойство entry указывает на начальную точку модуля. Webpack использует его для начала построения внутреннего графа зависимостей.
По умолчанию его значение — ./src/index.js , но вы можете указать другую (или несколько других) точку или точки входа, задав свойство entry в конфигурационном файле webpack.
Сначала создадим файл webpack.config.js в корневой папке и назначим одну точку входа как ./app/index.js .
Для добавления нескольких точек входа, вы можете назначить массив файлов в свойстве entry .
Output
Свойство output указывает webpack, куда помещать создаваемые им пакеты и как называть эти файлы. По умолчанию оно принимает значение ./dist/main.js в качестве основного выходного файла, а папка под названием ./dist предназначена для любого статического содержимого.
Вы можете настроить эту часть процесса, определив поле output в вашей конфигурации:
Загрузчики
Как следует из названия этого свойства, оно позволяет webpack обрабатывать любые типы файлов и преобразовывать их в валидные модули, которые используются приложением и добавляются в граф зависимостей. Учтите, что Webpack понимает только файлы javascript и JSON.
Работа загрузчиков начинается до или в начале генерации пакета на уровне отдельных файлов.
Загрузчики также могут преобразовывать файлы с другого языка (например, TypeScript) в JavaScript с помощью соответствующих загрузчиков или подгружать встроенные изображения в виде URL данных, а также позволяют напрямую импортировать файлы CSS в модули JavaScript.
На более высоком уровне Webpack располагает двумя свойствами — test и use.
- Свойство test указывает, какой файл или файлы необходимо обработать.
- Свойство use указывает webpack, какие загрузчики используются для преобразования файлов в валидные модули.
Перед применением загрузчиков в файле webpack.config.js необходимо установить их в качестве зависимостей в приложении:
npm install -D style-loader css-loader
Вот несколько популярных загрузчиков, которые можно использовать при создании фронтенд-приложений:
- babel-loader: этот пакет позволяет компилировать файлы JavaScript с помощью babel и webpack;
- ts-loader: загружает TypeScript 2.0+, как JavaScript;
- sass-loader: загружает и компилирует файлы SASS/SCSS;
- svg-url-loader: загрузчик webpack, который загружает SVG-файл в виде строки DataUrl с кодировкой utf-8.
Плагины
В то время как загрузчики выполняют роль преобразователей определенных типов модулей, плагины можно использовать для выполнения более широкого круга задач, таких как оптимизация пакета, управление ресурсами и внедрение переменных среды.
Плагины включаются в работу в конце или после генерации пакета на уровне пакета файлов, поэтому у них больше возможностей для контроля над пакетом.
Чтобы задействовать плагин, необходимо установить его в виде зависимости и использовать метод require() для его импорта и добавления в массив плагинов в конфигурационном файле webpack.
Вот несколько популярных плагинов, которые используются при создании фронтенд-приложений:
- eslint-webpack-plugin: этот плагин использует eslint для поиска и устранения проблем в коде JavaScript;
- webpack-bundle-analyzer: визуализация размера выходных файлов webpack с помощью интерактивной древовидной карты с возможностью масштабирования;
- clean-webpack-plugin: плагин webpack для удаления/очистки папки (папок) сборки;
- TerserWebpackPlugin: этот плагин использует terser для минификации/минимизации вашего JavaScript;
- purgecss-webpack-plugin: плагин для удаления неиспользуемых файлов CSS;
- uglifyjs-webpack-plugin: этот плагин использует uglify-js для минификации JavaScript.
Mode
Свойство mode принимает три значения: production , development и none . Вы можете включить встроенную оптимизацию webpack в зависимости от каждой отдельной среды.
- Введение в Webpack для новичков
- Как с нуля создать проект на React, используя Webpack 4 и Babel
- Разработка современных приложений с помощью WEBPACK
Что такое webpack?
Как разработчики JavaScript, мы знаем, что такое модули, но в webpack они немного отличаются и состоят из:
- Модулей ES — оператор import .
- Общих модулей JS — оператор require() .
- Модулей AMD — операторы define и require .
- Импортов CSS — оператор @import внутри любых файлов css/sass/less.
- URL изображений — url(…) или .
webpack объединяет все эти различные модули таким образом, что можно импортировать все в код JavaScript.
Должен ли я изучать webpack?
Сегодня большинство приложений строится с использованием React/Vue или другой библиотеки. Они предоставляют инструменты CLI (например, create-react-app, @vue/cli), которые абстрагируют большинство конфигураций и предоставляют значения по умолчанию. Но так как рано или поздно хочется внести в них коррективы, необходимо понимать принципы их работы.
Начнем
Мы создадим простое приложение, чтобы продемонстрировать работу webpack. Создадим новый каталог и инициализируем проект npm. Находясь во вновь созданном каталоге, введите:
npm init -y
Установим необходимые пакеты webpack:
npm install --save-dev webpack webpack-cli webpack-dev-server
Откроем package.json , удалим уже существующий скрипт test и добавим новый dev для запуска webpack в режиме разработки. Этот скрипт удобен, когда мы работаем локально. Файл пакета должен выглядеть примерно так:
Загрузчики webpack
Загрузчики в webpack — это сторонние расширения, которые имеют дело с другими расширениями файлов. Для webpack их доступно множество.
Перейдем к настройке загрузчиков в конфигурационном файле webpack. У них странный синтаксис. Мы используем ключ, называемый module , и он состоит из другого свойства, называемого rules , которое представляет собой массив загрузчиков. Для каждого файла, который мы хотим рассматривать как модуль, помещаем его как объект в массив rules . Каждый объект состоит из двух свойств: test определяет тип файла, а use — это массив, состоящий из загрузчиков. Обратите внимание, что загрузчики, определенные здесь в use , загружаются справа налево. Порядок важен при определении загрузчиков. Перед их использованием обратитесь к документации.
Общий синтаксис загрузчика в конфигурационном файле выглядит следующим образом:
Работа с SASS
Для работы с SASS (.scss) потребуются три загрузчика: sass-loader , css-loader и style-loader , а также дополнительный пакет sass , необходимый для Node. Здесь sass-loader используется для загрузки файлов SASS с импортом. Два их них установлены, доустановим остальные:
npm install --save-dev sass-loader sass
Создадим styles.scss в каталоге source и добавим в него эти строки или любые базовые стили:
Работа с современным JavaScript
webpack сам по себе не знает, как преобразовать современный JavaScript в совместимый код, который может работать в любом браузере, поэтому он использует Babel. Установим следующие пакеты: @babel/core , который фактически и является движком; babel-loader — загрузчик, необходимый для webpack; и @babel/preset-env для преобразования JavaScript в ES5. Установим зависимости:
npm install --save-dev @babel/core babel-loader @babel/preset-env
Далее надо настроить Babel, создав babel.config.json в корневом каталоге. Мы настраиваем Babel на использование preset-envm , установленного ранее:
Как это решить? Все просто. Добавим ключ optimization и свойство splitChunks :
Динамические импорты
Они используются для загрузки кода (в React и Vue, например) в зависимости от условия: на основе взаимодействия с пользователем либо изменения маршрута.
Для демонстрации добавим кнопку на страницу, которая по щелчку мыши извлекает список сообщений. Код для этой логики выборки присутствует в отдельном файле. Он импортируется динамически внутри index.js .
Вызовем API fetch отдельно в api.js в папке source . Здесь мы экспортируем функцию, которая делает запрос к общедоступному API и возвращает ответ:
0.main.js — это файл, который был загружен динамически. Для читаемого имени нужно добавить комментарий во время динамического импорта:
const getTodos = () => import(/* webpackChunkName: "postsAPI" */ './api')
Теперь, он загружает файл postsAPI.js , а не 0.main.js .
Еще любопытно?
Это краткое введение в webpack. Статья предназначена для начинающих разработчиков, которые хотят изучать webpack. В документации описано еще больше интересного.
Спасибо за чтение!
- Введение: 4 новейших операции JavaScript
- Сравниваем WebGL-фреймворки Three.js и Babylon.js
- Креативное программирование: методы и инструменты для JavaScript, Python и других языков