(материал без привязки к стэку react/redux/etc)
В сети есть миллионы туториалов, поэтому вы, вероятно, видели тысячи различных способов конфигурации файла Webpack. Каждый из них работает и может служить примером, хотя все они немного разные. Почему так? Сам Webpack развивается очень быстро, и многие загрузчики (лоадеры) и плагины должны идти с ним в ногу. Это основная причина, из-за чего конфиги так отличаются друг от друга: с различными комбинациями одних и тех же инструментов все может как работать, или не работать.
Позвольте мне выразить мое искреннее мнение: многие люди жалуются на Webpack и трудности в конфигурации. Во многих отношениях это так, хотя с моим опытом работы с gulp и grunt следует сказать, что вы сталкиваетесь с теми же проблемами несовместимости. Когда вы используете npm модули, несовместимости некоторых версий не избежать.
Webpack сейчас является самым популярным бандлером, у которого недавно произошли серьезные обновления. Они предполагают много нового: нулевую конфигурацию, разумные значения по умолчанию, улучшенную производительность, готовые инструменты оптимизации.
Если вы совершенно незнакомы с Webpack, для начала неплохо будет ознакомиться с документацией. У Webpack она довольно хорошая, с изложением в нескольких частях, поэтому в этом посте я быстро пробегу по основным понятиям.
Нулевая конфигурация: webpack 4 не требует конфигурационного файла, это одно из новшеств 4-ой версии. Настройка Webpack работает шаг за шагом, поэтому нет необходимости выполнять масштабную конфигурацию с самого начала.
Улучшенная производительность: webpack 4 — самая быстрая версия webpack.
Разумные значения по умолчанию: основные понятия webpack 4 — точка входа, точка выхода, загрузчики(лоадеры) и плагины. Я не буду подробно их описывать, только скажу, что между загрузчиками и плагинами очень расплывчатая разница. Все зависит от того, как автор реализовал библиотеку.
Это ваш .js файл. Вы, возможно, видели несколько конфигураций, в которые включены файлы .scss или .css. Это довольно серьезный хак и он может привести ко множеству неожиданных ошибок. Также иногда встречается вход с несколькими .js файлами. Хотя некоторые плагины позволяют это сделать, скажу, что так делать стоит только тогда, когда вы четко понимаете, зачем вам это нужно.
Это ваша build/ или dist/ или wateveryounameit/ папка, где будет размещен конечный .js файл. Это ваш окончательный результат, который в последсвии будет импортирован в index.html.
В основном компилируют или транспилируют ваш код, например, postcss-loader будет проводить ваши стили через разные плагины.
Играют жизненно важную роль в выводе кода в файлы.
Создайте новую директорию и зайдите в нее:
Инициализируем package.json:
Необходимо загрузить webpack v4 в качестве модуля и webpack-cli, чтобы запустить его с вашего терминала.
Убедитесь, что установлена именно 4 версия, если же нет, вы можете напрямую выбрать ее в вашем файле package.json. Далее откройте package.json и добавьте build-скрипт:
Скорее всего, вылезет предупреждение:
Вам необходимо отредактировать скрипт, чтобы в нем появился флаг режима:
Это значит, что webpack ищет папку .src/ с файлом index.js. Для Webpack 4 это действие по умолчанию, так как оно требует нулевой конфигурации.
Давайте создадим директорию с .js файлом, например, ./src/index.js и добавьте в него такой код:
Теперь запустите dev-скрипт:
Теперь у вас есть директория ./dist/main.js. Отлично, так как мы знаем, что код скомпилирован. Но что произошло?
Новый webpack не требует конфигурации, поэтому перед началом использования вам не нужно возиться с webpack.config.js. Из-за этого он вынужден действовать по умолчанию, и он будет искать папку ./src и в ней index.js и выводить в ./dist/main.js main.js — это ваш скомпилированный файл с зависимостями.
Наличие двух конфигурационных файлов — распространенная практика в webpack, особенно в крупных проектах. Обычно один файл используется для разработки, другой — для продакшена. В webpack есть два режима: продакшен и разработка. Это избавляет от необходимости иметь два файла (для средних по размеру проектов).
Если вы уделяете пристальное внимание нашей работе, то вы уже проверили файл main.js и убедились, что он остался неизменным.
В данном примере я буду использовать build-скрипт, поскольку он уже «из коробки» обеспечивает множество инструментов оптимизации и с этого момента способен свободно их использовать. Основное различие между скриптами build и dev в том, как они выводят файлы. Build создан для продакшен-кода. Dev создан для разработки: он поддерживает hot module replacement, webpack-dev-server и многие другие вещи, которые помогают разработчикам.
Вы легко можете переопределять значения по умолчанию в скриптах npm, просто используя флаги:
Такая запись перепишет опции по умолчанию без каких-либо других настроек.
В качестве упражнения попробуйте также флаги:
— флаг наблюдения (watch) для включения режима просмотра. Он будет следить за изменениями вашего файла и компилировать всякий раз при его изменении.
Современный JS-код в основном написан на ES6, а ES6 поддерживается не всеми браузерами. Поэтому вам необходимо транспилировать его. Transpile — волшебное слово для перевода ES6 в ES5. Для этого можно использовать babel — наиболее популярный инструмент для транспиляции. Разумеется, мы выполняем это не только для ES6, но и для многих инструментов JS, таких как TypeScript, React и т.д.
теперь у нас есть два варианта конфигурации babel-загрузчика:
— используя конфигурационный файл webpack.config.js;
— используя —module-bind в npm скриптах.
Технически вы многое можете сделать с новыми флагами, представленными в webpack, однако для простоты я бы предпочла webpack.config.js.
##Конфигурационный файл
Хотя Webpack рекламирует себя как платформа с нулевой конфигурацией, в основном он применяется к основным значениям по умолчанию, таким как точка входа и вывода.
На этом этапе мы создадим webpack.config.js со следующим содержимым:
Также теперь мы удалим флаги из наших npm-скриптов:
Теперь, когда мы запускаем npm run build
, он должен вывести нам хороший миниатюрный .js файл в ./dist/main.js. Если этого не происходит, попробуйте переустановить babel-загрузчик.
Наиболее распространенным паттерном webpack является его использование для компиляции приложения react. Хотя это в самом деле так, в этом туториале мы не будем зацикливаться на React-е, поскольку я хочу, чтобы структура была как можно более независимой от фреймворков. Вместо этого я покажу вам, как действовать и создавать конфигурации .html и .css.
##Импорт HTML и CSS
Для начала в нашей папке ./dist создадим небольшой файл index.html.
Как видите, здесь мы импортируем style.css. Давайте настроим его! Так как мы уже упомянули, для webpack у нас есть только одна точка входа. Так куда же мы поставим наш css?
Создаем style.css в нашей папке ./src:
Не забываем включить это в .js файл:
В webpack создайте новое правило для файлов css:
в терминале запустите:
Необходимо использовать ExtractTextPlugin для компиляции нашего css. Как видите, для .css. мы также добавили новое правило.
Краткое описание обычной работы правил:
**Нам необходимо использовать ExtractTextPlugin, потому что webpack по умолчанию понимает только формат .js. ExtractTextPlugin получает ваш .css и извлекает его в отдельный .css-файл в вашем каталоге ./dist.
**
Спойлер: в некоторых статьях вы найдете, что ExtractTextPlugin не работает с webpack 4, но у меня он работал
Webpack, начиная с 4 версии, имеет проблемы с этим плагином, поэтому вы можете столкнуться с определенной ошибкой.
Чтобы ее исправить, запустите:
Совет: «гуглите» вылезающие ошибки и ищите подобные вопросы в GitHub, или просто задайте свой вопрос на StackOverflow.
Затем ваш css код должен скомпилироваться в ./dist/style.css
На данном этапе dev-зависимости в моем package.json выглядят так:
Обратите внимание, что иная комбинация может не работать, поскольку даже обновление webpack-cli v2.0.12 до 2.0.13 может «сломать» ее. #justwebpackthings
Теперь ваш style.css должен выводиться в папку ./dist:
##Поддержка настройки SCSS
Очень часто разрабатываются веб-сайты с SASS и POSTCSS, они весьма полезны. Поэтому мы сперва включим поддержку SASS. Переименуем наш ./src/style.css и создадим другую папку для хранения файлов .scss. Теперь необходимо добавить поддержку форматирования .scss.
Замените style.scss на ./scss/main.scss в файле .js.
##Шаблон HTML
Теперь давайте создадим .html-шаблон файла. Добавьте файл index.html в *./src *с точно такой же структурой.
Чтобы использовать этот файл в качестве шаблона, нам понадобится html-плагин.
Добавьте его в ваш вэбпак-файл:
Теперь ваш файл из ./src/index.html стал шаблоном для конечного файла index.html.
Чтобы убедиться, что все работает, удалите все файлы из папки ./dist и саму папку. Затем запустите dev-скрипт
Вы увидите, что появилась папка ./dist, и в ней 3 файла: index.html, style.css, script.js.
##Кэширование и Хеширование
Одна из наиболее распространенных проблем в разработке — реализация кэширования. Очень важно понять, как это работает, ведь вы же хотите, чтобы у ваших пользователей всегда была последняя версия кода.
Поскольку этот пост затрагивает главным образом конфигурацию webpack — одним из самых популярных способов решения проблем кеширования является добавление хеш-номера в активные (находящиеся в разработке) файлы (asset), такие как style.css и script.js. Об этом можно почитать здесь. Хеширование необходимо, чтобы браузер «научился» запрашивать только измененные файлы.
Webpack 4 имеет встроенные функции, реализованные через chunkhash. Это можно сделать следующим образом:
В файл ./src/index.html добавьте:
С помощью такого синтексиса ваш шаблон «научится» использовать хэшированные файлы. Это новая «фича», реализованная после возникновения этой проблемы.
Мы будем использовать описанный там htmlWebpackPlugin.files.chunks.main.
Теперь в нашей папке ./dist есть файл index.html:
Далее, если мы ничего не изменим в файлах .js и .css и запустим:
Независимо от количества запусков, числа в хэшах должны быть идентичны друг другу в обоих файлах.
##Проблемы с хэшированием и их решения
Хотя у нас есть рабочий алгоритм, но он пока не идеален.
Что, если изменить код в файле .scss? Окей, меняем .scss и снова запускаем dev-скрипт. Теперь новый хэш файла не генерируется.
Что, если мы добавим новый файл console.log в наш .js-файл вот так:
Если вы снова запустите dev-скрипт, увидите, что в обоих файлах обновлен хэш-номер.
Эта известная проблема, и даже описан вопрос на StackOveflow.
##Как теперь это исправить?
Перепробовав немало плагинов, якобы решающих эту проблему, я, наконец, пришла к двум типам решений:
##Решение 1
Замените [chukhash] на простой [hash] в .css. Это было одно из решений проблемы. Это похоже на конфликт с webpack 4.3, в котором введена собственная переменная [contenthash]. Используйте плагин: webpack-md5-hash.
Теперь, когда вы вносите изменения в свой файл main.scss и запускаете скрипт dev, с новым хэшем должен быть сгенерирован только новый style.css.
Далее протестируем .js-файлы. Теперь оба файла меняют хэш.
##Решение 2
Все еще могут остаться некоторые конфликты, поэтому теперь попробуем подключить плагин mini-css-extract.
##Плагин Mini-CSS
Плагин Mini CSS предназначен для замены плагина extract-text и в дальнейшем для обеспечения лучшей совместимости.
Я реструктурировала свой webpack-файл, чтобы скомпилировать style.css с /mini-css-extract-plugin и у меня все работает.
Теперь, когда я редактирую main.scss, генерируется новый хеш для style.css. Также когда я редактирую css, меняются только хэши css, и когда я редактирую ./src/script.js, меняются только хэши script.js!
##Интегрирование PostCSS
Чтобы выходной файл .css был безупречным, мы можем добавить PostCSS.
PostCSS предоставляет вам autoprefixer, cssnano и другие приятные и удобные штуковины. Буду продвигать то, что использую регулярно. Нам понадобится postcss-загрузчик. Также по мере необходимости установим autoprefixer.
Спойлер: для рационального использования PostCSS вам не требуется webpack, есть довольно приличный плагин post-css-cli, который позволяет вам использовать его в npm-скрипте.
Создайте postcss.config.js, где вам требуюся соответствующие плагины, вставьте
Теперь наш webpack.config.js должен выглядеть так:
Пожалуйста, обратите внимание на порядок плагинов, которые мы используем для .scss
Загрузчик использует плагины от начала до конца. (справа-налево — прим.переводчика)
Вы можете протестировать autoprefixer, дополнив код в ваших .scss-файлы и проверив вывод. Существует также способ исправить выход, указав, какой браузер вы хотите поддерживать в файле .browserslistrc.
Я бы посоветовала вам https://www.postcss.parts/ для изучения плагинов, доступных для PostCSS, например:
— utilities
— cssnano
— style-lint
Я буду использовать cssnano для минимизации моего выходного файла и css-mqpacker для упорядочения медиа-запросов. Я также получила несколько подобных сообщений:
При желании можете попробовать cleancss.
##Контроль версий
Ваш package.json на этом этапе должен иметь следующую структуру:
Чтобы сохранить зависимости, для установки модулей рекомендую использовать **yarn вместо npm. Короче говоря, yarn жестко фиксирует версию пакета, и при переустановке модулей вы сможете избежать многих неожиданных несовместимостей.** (*Npm теперь тоже так умеет, тут я ошиблась)
##Очищаем ./dist
Мы можем попробовать импортировать clean-webpack-plugin, чтобы перед регенерацией файлов очистить нашу папку ./dist.
Теперь, когда у нас есть чистенькая и аккуратная конфигурация, мы будем «жечь»!
В этой статье я предоставила вам свой файл конфигурации и его пошаговую настройку. Примечание: поскольку к моменту, когда вы прочтете это, могут измениться многие npm зависимости, то одна и та же конфигурация у вас может не заработать! Прошу вас указать в комментариях ваши ошибки, чтобы после я могла их исправить. Сегодня 05.04.2018.
Автор оригинального поста — Margarita Obraztsova
Сегодня будем использовать parcel и IntelliJ IDEA Community Edition. Все инструменты бесплатные. Инициализация elm проекта…
На данном вебинаре мы знакомились с языком Elm проводя параллели между Elm и Redux, поэтому…
Richard Feldman рассказывает как масштабировать Elm приложение без боли. Показаны техники: extended records, подход narrow…
В данной заметке вы найдете конспект видео по Elm, которые я посмотрел в ноябре 2019.…
Итоги года 2019 // Max Frontend Покажи мне свой гитхаб, и я скажу работал ли…
Почему стоит изучать Elm? Потому что это интересный вызов, редкие (но вкусные) вакансии и хороший…
View Comments
Есть еще одна проблема, ответ на который, пришлось искать опытным путем:
Исходя из того стейтмента, что ExtractTextPlugin не работает с webpack 4, я заюзал MiniCssExtractPlugin.
После кучи других настроек и прикручивания различных лоадеров мне понадобился HotModuleReplacement, и поскольку он реализован уже в 4м вебпаке "из коробки" решил воспользоваться им.
После различных проб и ошибок, оказалось что MiniCssExtractPlugin не работает с ним (или я не понял как это сделать)
Вернулся к ExtractTextPlugin + еще один пакет. В общем виде все выгдядит так:
module.exports = {
module: {
rules: [{
test: /\.s?css$/,
use: ['css-hot-loader'].concat(ExtractTextPlugin.extract({
fallback: "style-loader",
use: ["css-loader", "postcss-loader", "sass-loader"]
}))
},
devServer: {
hot: true
},
plugins: [
new ExtractTextPlugin("styles.css"),
new webpack.HotModuleReplacementPlugin(),
]
}
Спасибо за статью.
У меня после определённого гугления получилось подружить MiniCssExtractPlugin с "коробочным" HMR (который не react-hot-reload),
через css-hot-loader, кому интересно, можно посмотреть тут:
https://github.com/v24dc/js-templates/tree/master/webpack-4-simple
Единственное но: возникла проблема с content hash, пришлось его отключить. Остальное по статье + webpack-dev-server.
спасибо, отличный материал :idea:
// "clean-webpack-plugin": "^3.0.0",
// "webpack": "^4.39.3",
у меня стало чистить dist только после этой корректировки
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
....
new CleanWebpackPlugin(), //без параметров (похоже он берет их из path)
...
источник: https://www.npmjs.com/package/clean-webpack-plugin
хотелось бы, чтобы вы добавили в статью настройку webpack-dev-server
насчёт кэширования и хэширования ничего не понял но аккуратно скопировал, работает.:idea:
также установка и затем комментирование ExtractTextPlugin заметно увеличивает время "дискуссии". и пагубно влияет (имхо) на неокрепший разум webpack-первопроходцев
Ещё немного занудства от меня:
...Загрузчик использует плагины от начала до конца. (справа-налево — прим.переводчика)
Означает ли это, что не смотря на то что мы читаем и пишем код слева-направо, то в цепочке вида
use: [ 'style-loader', MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader']
будет сначала выполняться 'sass-loader'?
тогда логичнее было бы написать с конца в начало, слева-направо. (имхо).
С хешированием разобрался. В общих словах, при постоянном изменении файла стилей и выкладывании страницы в общий доступ, в браузерах клиентов стили кэшируются (сохраняются в память браузера для ускорения загрузки сайта при следующем входе в него) и не обновляются при изменениях внутри файла стилей со стороны разработчика. У меня была такая история (я постоянно просил человека, который просматривал созданную мной страничку удалять историю просмотров браузера, объяснять как это делается, в общем нагружать человека дополнительными действиями) С хешироваными файлами этого можно избежать. Имя файла стилей каждый раз уникальное и кэш браузера таким образом псевдо-игнорируется.
С момента создания config пошли ошибки. Ничего не получилось
Вероятно, что-то из зависимостей уже изменилось. К сожалению, давно не проверял этот материал.