Кратко
СкопированоWebpack — это самый популярный сборщик в мире JS. Его функции легко расширяются с помощью сторонних пакетов, так что Webpack можно заставить делать практически что угодно. А если готового плагина не нашлось, благодаря мощному API можно написать решение под свой уникальный случай.
Базовое использование
СкопированоНа базовом уровне использовать Webpack довольно просто. Представим, что в нашем приложении есть файл application.js с функциями, необходимыми для работы:
function sayHello() { console.log('Hello!')}function sayBye() { console.log('Bye!')}// Экспортируем эти функции,// чтобы воспользоваться ими в другом месте:export { sayHello, sayBye }
function sayHello() { console.log('Hello!') } function sayBye() { console.log('Bye!') } // Экспортируем эти функции, // чтобы воспользоваться ими в другом месте: export { sayHello, sayBye }
Теперь создадим файл index.js, который будет использоваться как входная точка, и вызовем в нем функции приложения:
import { sayHello, sayBye } from './application'sayHello()sayBye()
import { sayHello, sayBye } from './application' sayHello() sayBye()
Настроим Webpack, чтобы он собирал единый файл с кодом приложения.
Для начала следует добавить Webpack в список зависимостей приложения:
npm install --dev webpack webpack-cli
npm install --dev webpack webpack-cli
webpack
— основная зависимость, в которой хранится весь код, нужный для работы бандлера.
webpack
— обёртка для запуска Webpack из командной строки, Command Line Interface.
Теперь достаточно создать простой конфигурационный файл webpack.config.js:
// path — встроенный в Node.js модульconst path = require('path')module.exports = { // Указываем путь до входной точки: entry: './src/index.js', // Описываем, куда следует поместить результат работы: output: { // Путь до директории (важно использовать path.resolve): path: path.resolve(__dirname, 'dist'), // Имя файла со сборкой: filename: 'bundle.js' }}
// path — встроенный в Node.js модуль const path = require('path') module.exports = { // Указываем путь до входной точки: entry: './src/index.js', // Описываем, куда следует поместить результат работы: output: { // Путь до директории (важно использовать path.resolve): path: path.resolve(__dirname, 'dist'), // Имя файла со сборкой: filename: 'bundle.js' } }
Почти готово, осталось только добавить скрипт для сборки в package.json и вызвать его:
{ "scripts": { "build": "webpack" }}
{ "scripts": { "build": "webpack" } }
npm run build
npm run build
После выполнения в директории dist окажется файл bundle.js, который уже можно подключать на страницу в браузере.
В корне проекта нужно создать папку src, а в ней файл index.html и подключить в него файл со сборкой:
<!DOCTYPE html><html> <head> ... </head> <body> ... <script src="./dist/bundle.js"></script> </body></html>
<!DOCTYPE html> <html> <head> ... </head> <body> ... <script src="./dist/bundle.js"></script> </body> </html>
Если открыть этот файл в браузере, то в консоли появится приветствие и прощание.
Отслеживание изменений в проекте
СкопированоЗаново запускать сборку после внесения каждой правки не очень удобно. Во-первых, придётся каждый раз писать команду в терминале. Во-вторых, полная сборка больших проектов может занимать десятки минут, и тратить столько времени каждый раз просто расточительно.
Для решения этой проблемы можно воспользоваться режимом инкрементальной сборки, когда Webpack отслеживает изменения файлов с исходным кодом и автоматически собирает те части, которые изменились.
Добавим новую команду в package.json:
{ "scripts": { "build": "webpack", "watch": "webpack --watch" }}
{ "scripts": { "build": "webpack", "watch": "webpack --watch" } }
Теперь достаточно открыть файл index.html в браузере и обновлять страницу после сохранения файлов с исходным кодом.
Для большего удобства можно воспользоваться пакетом webpack-dev-server.
Расширение
СкопированоWebpack — невероятно мощный инструмент, в первую очередь за счёт своей расширяемости. В базовом случае он только собирает несколько JS-файлов в один, но с помощью лоадеров и плагинов можно сильно изменить его функциональность.
Webpack начинает свою работу со входной точки — первого JS-файла. В нём он находит все импорты, по которым собирает файлы с исходным кодом проекта. Во всех найденных файлах снова ищет импорты, и так далее, пока импорты не закончатся. В итоге у Webpack оказывается список всех файлов проекта и информация, как эти файлы связаны. Затем в дело вступают плагины и лоадеры. Для каждого файла Webpack найдёт все подходящие по конфигурации лоадеры и обработает ими файл.
Плагины — это более глобальный способ изменить поведение сборщика. В процессе сборки Webpack будет вызывать специальную функцию в каждом плагине, передавая в неё текущий контекст сборки и API для изменения этого контекста.
Обратная сторона расширяемости Webpack — сложность его конфигурации. В больших проектах файл с настройками сборки может занимать тысячи строк. Часто такую конфигурацию разбивают на несколько файлов, чтобы её было проще читать.
Лоадеры
СкопированоЛоадер — это функция, которая принимает содержимое какого-то файла и должна вернуть изменённое содержимое.
Например, ts
превратит любой TypeScript-код в обыкновенный JavaScript-код.
Для Webpack написано огромное число лоадеров — для работы со стилями, с разными языками, для обработки изображений и для многого другого. Вот несколько, которые можно встретить почти в любом проекте:
style
— импортирует CSS-файлы и внедряет стили в DOM.- loader css
— позволяет работать с- loader @import
иurl
внутри CSS.( ) babel
— позволяет писать код на современном JS, но исполнять его даже в старых браузерах.- loader
Чтобы добавить новый лоадер, нужно расширить файл webpack.config.js:
module.exports = { // В этом массиве будут перечислены все применяемые лоадеры: module: { rules: [ { // Это правило будет применяться ко всем файлам, // имя которых подойдет под регулярное выражение: test: /\.css$/, // Список лоадеров, которые применятся к файлу: use: [ { loader: 'style-loader' }, { loader: 'css-loader', // Лоадеру можно передать параметры: options: { modules: true } } ] } ] }}
module.exports = { // В этом массиве будут перечислены все применяемые лоадеры: module: { rules: [ { // Это правило будет применяться ко всем файлам, // имя которых подойдет под регулярное выражение: test: /\.css$/, // Список лоадеров, которые применятся к файлу: use: [ { loader: 'style-loader' }, { loader: 'css-loader', // Лоадеру можно передать параметры: options: { modules: true } } ] } ] } }
Плагины
СкопированоПлагин — мощный способ расширить или изменить функциональность Webpack. Если лоадер ограничен только одной функцией (принимает содержимое файла и должен вернуть изменённое содержимое), то плагин может делать всё что угодно.
Для Webpack написано огромное количество плагинов — для работы со стилями, повышения удобства разработки и упрощения жизни инженеров, для автоматизации рутинных операций и много других. Вот несколько, которые можно встретить почти в любом проекте:
MiniCssExtract
— по умолчанию все стили, которые обработал Webpack, попадают в JS-файл и потом вставляются в тегPlugin <style>
. Этот плагин извлекает все стили в отдельный CSS-файл, который можно подключить к странице через тег<link>
.HotModuleReplacement
— позволяет делать изменения в коде и видеть изменения в браузере без полной перезагрузки страницы, это делает разработку более комфортной.Plugin CompressionWebpack
— сжимает все ресурсы, сгенерированные Webpack, чтобы передавать пользователям по сети меньший объём данных.Plugin
Чтобы добавить новый плагин в сборку, нужно расширить файл webpack.config.js:
// Webpack предоставляет несколько плагинов в основном пакете:const { ProgressPlugin } = require('webpack')module.exports = { plugins: [ // При сборке этот плагин будет отображать прогресс в консоли: new ProgressPlugin() ]}
// Webpack предоставляет несколько плагинов в основном пакете: const { ProgressPlugin } = require('webpack') module.exports = { plugins: [ // При сборке этот плагин будет отображать прогресс в консоли: new ProgressPlugin() ] }
На практике
Скопированосоветует Скопировано
📄 На практике не очень удобно вручную создавать HTML-файлы и подключать туда сборки, сгенерированные Webpack — ведь количество и имена файлов могут меняться в зависимости от сборки. Для автоматизации часто используют HtmlWebpackPlugin.
В первую очередь, нужно установить пакет с плагином в проект:
npm install --save-dev html-webpack-plugin
npm install --save-dev html-webpack-plugin
const { HtmlWebpackPlugin } = require('html-webpack-plugin')module.exports = { plugins: [new HtmlWebpackPlugin()]}
const { HtmlWebpackPlugin } = require('html-webpack-plugin') module.exports = { plugins: [new HtmlWebpackPlugin()] }
При сборке плагин сгенерирует пустой index.html в папку с собранным проектом и добавит туда ссылки на финальные JS- и CSS-файлы. При необходимости плагин можно кастомизировать.
💫 path — это встроенный в Node.js модуль для работы с путями. Чтобы не беспокоиться об особенностях разных операционных систем, лучше всегда при работе с путями в файловой системе использовать модуль path.
В нём есть несколько полезных для конфигурации Webpack функций:
path
— функция, которая принимает любое число сегментов пути и возвращает абсолютный путь. Работает так:. resolve
path.resolve('/foo/bar', './baz')// '/foo/bar/baz'path.resolve('/foo/bar', '/tmp/file/')// '/tmp/file'// Если текущая рабочая директория /home/user:path.resolve('www', 'static_files/png', '../gif/image.gif')// '/home/user/www/static_files/gif/image.gif'
path.resolve('/foo/bar', './baz') // '/foo/bar/baz' path.resolve('/foo/bar', '/tmp/file/') // '/tmp/file' // Если текущая рабочая директория /home/user: path.resolve('www', 'static_files/png', '../gif/image.gif') // '/home/user/www/static_files/gif/image.gif'
-
path
— строка разделителя путей в текущем окружении (. sep /
или\
). -
path
— функция, которая принимает строку с именем файла и возвращает расширение этого файла.. extname