Что такое Webpack
Мировое сообщество разработчиков стремится улучшить опыт пользователей и программистов в использовании и создании JavaScript приложений. Для этого было создано большое количество новых библиотек и фреймворков.
Со временем также появились шаблоны проектирования, которые дали разработчикам более мощный и простой способ написания больших приложений на JavaScript. Но с их внедрением проекты становились все более громоздкими. К тому же новой тенденцией стало написание инкапсулированных небольших фрагментов кода. Все это привело к тому, что в общем пакете приложений стало в 4–5 раз больше файлов.
Проблемой был не только общий размер приложения, но и огромный разрыв в том, какой код писали программисты и какой код могли распознать браузеры. Разработчикам пришлось использовать много вспомогательного кода, называемого polyfills, чтобы убедиться, что браузеры могут интерпретировать код в своих пакетах. Для решения этих проблем был создан Webpack. Он помогает объединять все части приложения и разом отправлять их в браузер. С помощью загрузчиков и плагинов Webpack может преобразовывать, сокращать и оптимизировать все типы файлов, прежде чем отправлять их в виде единого пакета. Он использует разные сервисы: JavaScript, HTML, CSS, шрифты, фото, а затем преобразует эти ресурсы в формат, удобный для использования в браузере.
Зачем нужен Webpack
Webpack просматривает пакет и создает граф зависимостей. Последний состоит из различных модулей, которые требуются приложению для нормальной работы. Затем в зависимости от этого графика создается новый пакет, в который входит минимальное количество требуемых файлов.
Есть четыре основных понятия, которые важны для понимания работы Webpack:
- вход,
- вывод,
- загрузчики,
- плагины.
Каждая настройка имеет одну или несколько точек входа. Они указывают, с чего начать построение графика зависимостей. Сервис обрабатывает модуль с первой точки и просматривает исходный код приложения в поисках других модулей, которые зависят от нее. Каждая прямая или косвенная зависимость фиксируется, обрабатывается и выводится в пакет:
const config = {
entry: './app/prosper.js'
};
module.exports = config;
В настройках можно указать только одну точку вывода. Свойство output config указывает Webpack, где размещать создаваемые пакеты и как их называть. Указать свойство output можно в файле настройки:
const config = {
entry: './app/prosper.js',
output: {
path: '/unicodeveloper/project/public/dist',
filename: 'app.bundle.js'
}
};
module.exports = config;
Сервис понимает только JavaScript и JSON. Загрузчики же помогают производить обработку других типов данных и преобразовывать их в допустимые модули, которые будут использоваться приложением и добавляться в график. Они имеют два свойства в конфигурации:
- свойство test — определяет, какой файл или файлы следует преобразовать;
- свойство use — указывает, какой загрузчик следует использовать для выполнения преобразования.
Плагины применяются для широкого спектра задач, которые не могут выполняться загрузчиками. Они нужны для оптимизации пакетов, минимизации нагрузки на сервер, внедрения скриптов, создания статистики.
Приведем пример:
const CompressionWebpackPlugin = require('compression-webpack-plugin');
const webpack = require('webpack');
const path = require('path');
const config = {
entry: './app/prosper.js',
output: {
path: '/unicodeveloper/project/public/dist',
filename: 'app.bundle.js'
},
module: {
rules: [
{ test: /\.(html)$/, use: 'html-loader' }
]
},
plugins: [
new CompressionWebpackPlugin({test: /\.js/})
]
};
module.exports = config;
В приведенном выше коде плагин CompressionWebpackPlugin сжимает все файлы JavaScript перед отправкой их в браузер. Также есть другие плагины — AggressiveSplittingPlugin, CommonsChunkPlugin, 18nWebpackPlugin.
Установка и настройка
Чтобы работать с Webpack, нужно установить Node.js. Перейдите на сайт этой программной платформы и поставьте последнюю версию на компьютер. Нужно также проверить, что менеджер пакетов npm работает.
Создайте новый каталог. Откройте терминал и запустите npm init, чтобы создать файл package.json внутри каталога. Затем добавьте Webpack в проект:
npm install webpack -D
Необходимо также установить Webpack CLI. Для этого нужна команда:
npm install --save-dev webpack-cli
После этого создайте папку js внутри каталога с двумя конфигурационными файлами: service.js и factory.js.
import './service.js';
console.log("This is a functioning service.");
Создайте файл webpack.config.js в корневом каталоге и добавьте в него код:
const path = require('path');
module.exports = {
entry: './js/factory.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
};
В приведенном выше коде есть точка входа factory.js. Этот конфигурационный файл побуждает Webpack начать обработку графа из этого файла. Он же зависит от service.js и выводит результат своей работы в bundle.js. Результат записывается в новый каталог dist.
Создайте файл index.html в корневом каталоге.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test Webpack</title>
</head>
<script type="text/javascript" src="dist/bundle.js"></script>
<body>
<h2> Testing Webpack.... </h2>
</body>
Перейдите к package.json. Добавьте webpack в раздел скриптов:
{
"name": "testwebpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^3.8.1"
}
}
Теперь можно просто запустить npm run build из терминала. Команда сама вызовет webpack.
Структура файла
Сделаем папку распространения. Позже эта папка будет использоваться для обслуживания приложения с локального или удаленного веб-сервера. Это позволит просматривать его в браузере или размещать на внешнем хостинг-сервере, что сделает приложение доступным для всех через HTTP. В этой папке будет все, что нужно для публикации проекта.
Для начала в командной строке создайте папку и HTML-файл в качестве точки входа в приложение из корневого каталога проекта:
mkdir dist
cd dist
touch index.html
Присвойте созданному файлу dist/index.html следующее содержимое:
<!DOCTYPE html>
<html>
<head>
<title>Hello Webpack</title>
</head>
<body>
<div>
<h1>Hello Webpack</h1>
</div>
</body>
</html>
Следующий шаг позволяет запустить работу именно с JavaScript:
console.log('Hello Webpack Project.');
Наиболее простой способ связать JavaScript с HTML-файлом:
<!DOCTYPE html>
<html>
<head>
<title>Hello Webpack</title>
</head>
<body>
<div>
<h1>Hello Webpack</h1>
</div>
<script src="../src/index.js"></script>
</body>
</html>
Но еще проще применить Webpack для создания одного пакета JavaScript из всего исходного кода в папке src/, он впоследствии будет автоматически помещен в папку dist/. Затем его можно использовать в HTML-файле точки входа следующим образом:
<!DOCTYPE html>
<html>
<head>
<title>Hello Webpack</title>
</head>
<body>
<div>
<h1>Hello Webpack</h1>
</div>
<script src="./bundle.js"></script>
</body>
</html>
Очистка кэша в Webpack
Webpack объединяет все файлы в каталог deployable/dist. Как только приложение развернули на сервере и пользователь начал посещать его, необходимо обратиться к серверу, чтобы получить доступ ко всем ресурсам приложения. Вот почему браузеры кэшируют ресурсы приложения. По сути, они сохраняют файлы или модули в каталоге /dist, чтобы при следующем обновлении или посещении браузера пользователю не пришлось извлекать знакомую информацию.
Можно запретить браузерам кэшировать пакеты для CSS или файлов, в которые были внесены изменения. Кэширование файлов браузером может вызвать проблему. Ведь если изменить данные, которые были кэшированы, браузер может не обновить их и предположить, что файл тот же. Так происходит только потому, что имя не изменилось.
Идея удаления кэша заключается в создании нового имени каждый раз, когда вносятся изменения. Webpack поставляется со встроенной функцией замены выходных данных в файле конфигурации Webpack. Подстановка [content hash] создаст уникальный хэш, основанный на том, изменилось содержимое ресурса или нет. Имя будет обновляться только тогда, когда изменение будет происходить. Добавление [content hash] к выходному объекту в конфигурационном файле будет выглядеть так:
//the output object in module.exports from the webpack.config.js file:
output: {
filename: "main.[contentHash].js",
path: path.resolve(__dirname, "dist")
},
Если используется пользовательская конфигурация webpack вместо шаблона или приложения Create React, нужно убедиться, что в имени файла есть суффикс для удаления кэша. Очистка кэша означает, что браузер пользователя загружает самую свежую версию приложения, если оно было обновлено, вместо того, чтобы использовать кэшированную версию. В простой настройке использовался бы только один выходной файл с фиксированным именем:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
plugins: [
new HtmlWebpackPlugin(),
],
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
}
HtmlWebpackPlugin применяется для управления файлом index.html. Он будет обрабатывать вставку тега <script> в index.html с именем пакета. В примере выше в один файл объединяются JavaScript с именем bundle.js.
Использование фиксированного имени файла для пакета проблематично, поскольку браузер будет кэшировать данные и использовать кэшированную версию, даже если файл изменился. Можно попробовать добавить суффикс к имени и менять его при каждом изменении кода:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
plugins: [
new HtmlWebpackPlugin(),
],
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist'),
},
}
Советы по работе
Следите за порядком в настройках. Разбейте настройки на более мелкие части, например: одну для загрузчиков, а другую для плагинов. Используйте инструмент под названием webpack-merge, чтобы собрать их все в одном месте. Не забывайте делать заметки в конфигурации, которые помогут пошагово воссоздать все этапы работы над проектом. Присвойте своим папкам и файлам четкие названия, чтобы знать, где и что находится.
Оптимизируйте производительность. Переключитесь в рабочий режим, чтобы сделать код менее громоздким. Включите сжатие, чтобы уменьшить размер файлов и ускорить их загрузку. Избавьтесь от неиспользуемого кода с помощью tree shaking. Для ускорения работы храните код для библиотек отдельно от основного. Используйте хэши в именах файлов (например, [name].[hash].js), чтобы браузерам не приходилось их перезагружать.
Проанализируйте сборку. Узнайте, что делает ваши файлы большими, с помощью инструмента webpack-bundle-analyzer. Следите за тем, сколько времени занимает сборка проекта и насколько велики файлы. Для этого пригодится плагин Speed Measure.
Не забывайте о кэше. Сохраняйте те части вашего сайта, которые не сильно меняются, например библиотеки или стили, чтобы в следующий раз они загружались быстрее. Используйте кэш-загрузчик, когда преобразования требуют много времени.
Разделяйте код. Разбейте код на части, основанные на разных компонентах сайта, а не просто на случайных фрагментах. Загружайте их только по мере необходимости с помощью динамического импорта. Разделяйте код только в том случае, если это действительно ускоряет загрузку сайта.
Webpack помогает разработчикам писать модульный и поддерживаемый код. Этот инструмент полезен им, ведь обеспечивает гибкость при настройке конфигураций для любого проекта.