SCSS — немного практики, часть I
Статей про SASS ( SCSS ), Less на хабрахабре уже полно, но на мой взгляд не хватает такой, в которой было бы немного реальной практики. Я постараюсь восполнить этот пробел. Около года назад одна из SASS -статей меня «зацепила», и с тех пор я полюбил эту технологию настолько, что ручной набор обычного CSS кода представляется мне лишней тратой времени. Сия статья посвящается тем верстальщикам (или web-программистам), которые про SCSS ещё не слышали, или же ещё не пробовали в деле. Более опытным товарищам, полагаю, в ней ловить нечего.
Что такое SCSS
SCSS — «диалект» языка SASS. А что такое SASS? SASS это язык похожий на HAML (весьма лаконичный шаблонизатор), но предназначенный для упрощения создания CSS-кода. Проще говоря, SASS это такой язык, код которого специальной ruby-программой транслируется в обычный CSS код. Синтаксис этого языка очень гибок, он учитывает множество мелочей, которые так желанны в CSS. Более того, в нём есть даже логика (@if, each), математика (можно складывать как числа, строки, так и цвета). Возможно, некоторые возможности SCSS покажутся вам избыточными, но, на мой взгляд, лишними они не будут, останутся «про запас».
Отличие SCSS от SASS заключается в том, что SCSS больше похож на обычный CSS код. Пример SASS-кода:
$blue: #3bbfce $margin: 16px .content-navigation border-color: $blue color: darken($blue, 9%) .border padding: $margin / 2 margin: $margin / 2 border-color: $blue
И то же самое на SCSS:
$blue: #3bbfce; $margin: 16px; .content-navigation < border-color: $blue; color: darken($blue, 9%); >.border < padding: $margin / 2; margin: $margin / 2; border-color: $blue; >
Я выбрал SCSS в виду того, что он проще для восприятия коллегам с ним ещё не знакомым. Ещё стоило бы отметить что обычный CSS код вполне вписывается в SCSS синтаксис.
Установка и использование
Для начала нужно установить ruby. После чего нужно установить sass-gem ( gem install sass в консоли ). Если всё прошло гладко, то теперь вам доступна консольная программа sass . О всех нюансах её использования вы можете прочесть здесь ― sass —help . Я расскажу лишь о двух базовых возможностях:
—watch
Если запустить sass с ключом —watch , то программа будет следить за указанными вами файлами. В случае их изменения, она автоматически пересоберёт все необходимые css-файлы (не все вообще, а только связанные с изменёнными).
Предположим, что у вас есть следующая структура проекта:
-- css ---- scss ------ style.scss ---- style.css
Необходимо чтобы sass отслеживал все изменения в css/scss/* и результат сохранял в css/*.css . В таком случае запускаем sass так ― sass —watch css/scss:css/. . Т.е. sass —watch [что]:[куда] .
—update
Если вам нужно единожды обновить css-файлы, то в место —watch применяем —update . Никакой слежки проводится не будет, так же как и проверок на необходимость обновления.
Стоит отметить, что в отличии от Less , SASS не умеет компилировать свой код прямо в браузере. На мой взгляд, такой подход (компиляция на сервере или ПК-верстальщика) является единственно верным.
Практика
Итак, мы подошли к самому главному. Начнём с @import .
import
Изначально, до использования SCSS, весь CSS код движка, с которым мне по долгу службы приходится работать, находился в 1-ом огромном style.css файле. Моя IDE (Netbeans (кстати, вот плагин для подсветки синтаксиса)) работала с ним с существенными тормозами. Разбивать же его на множество файлов поменьше, и, при необходимости, склеивать их в 1 ― никто не хотел. SCSS решает этот вопрос автоматически.
Стоит отметить 1 нюанс. Если скормить sass не конкретный файл-источник, а директорию, то css файлы не будут генерироваться для файлов начинающихся с _ . Т.е. наличие файла style.scss приведёт к созданию style.css , а наличие файла _some.scss ― нет.
Итак, для того, чтобы включить содержимое файла _template.scss или template.scss пишем
@import "template"; // шаблоны
В конечном счёте, вместо 1-го большого style.css файла у меня получилось более сотни мелких scss -файлов. С первого взгляда может показаться, что такое количество слишком велико и приведёт к страшным мукам. Однако, нужный мне файл я нахожу сразу исходя из удобной структуры каталогов. К тому же, я полагаю, что благодаря кешированию такая «схема» более производительна.
@вложенность
Одна из самых желанных «фич» для CSS ― вложенность селекторов. Пример:
#some < border: 1px solid red; .some < background: white; >> /* => */ #some < border: 1px solid red; >#some .some
input < border: 1px solid gray; background: white; &[type=text] < color: black; >&.some_class < display: none; >> /* => */ input < border: 1px solid gray; background: white; >input[type=text] < color: black; >input.some_class
Символ & равносилен родительскому селектору. Допустим тег у нас имеет класс ie_7 , в случае если в качестве обозревателя у нас Internet Explorer 7 . Следующий код позволяет избавиться от всех «хаков» и спец.комментариев:
$IE_7: 'body.ie_7'; //. .some < display: inline-block; #& < zoom: 1; display: inline; >> /* => */ .some < display: inline-block; >body.ie_7 .some
$variables
Переменные ― удобная штука. Определяются они так:
$some: red;
Переменные ― не константы, их можно менять по ходу кода 🙂 Одна из первых моих мыслей вылилась в _const.scss файл, который заключает в себе все базовые цвета, размеры шрифтов и пр.
$link: #15157d; $link_bottom: $link; $input_font_size: 13px; $content_bg: #F1F1F1; $input_color: #4E4D4D; $input_color_placeholder: #959595; $text_color: black; .
Предполагается, что цвет ссылок на сайте ― $link .
a < color: $link; >span.link
Если в дальнейшем выяснится, что цвет ссылок изменился ― достаточно поменять 1 переменную (в случае CSS нужно было бы пройтись авто-заменой по файлам, возможно даже выборочно). Предположим, что внезапно выясняется, что в некотором модуле contacts , цвет ссылок другой. Есть, как минимум, два пути решения.
$contacts_link: orange; // код модуля с использованием $contacts_link вместо $link
$__link: $link; $link: orange; // код модуля $link: $__link;
Переменные у нас не типизированные, поэтому с равным успехом могут содержать строки, числа и цвета.
@математика
Разделим математику на 2 категории ― цвета и числа. Начнём с чисел. Простой пример:
.block
При желании можно и padding с border-ом задавать переменными. Всё зависит от сложности вёрстки.
.block < $count: 10; $margin_left: 5px; $all_width: 1000px; width: $all_width; .sub_element < width: ( $all_width / $count ) - $margin_left; margin: 0 0 0 $margin_left; >>
Хочу отметить, что подобного рода манипуляции применяются очень часто. Без них я как без ног.
А теперь цвета. Цвета можно складывать, перемножать:
.some < $color: #010203; color: $color; border-color: $color - #010101; &:hover < color: #010203 * 2; >> /* => */ .some < color: #010203; border-color: #000102; >.some:hover
Довольно удобная штука, когда лень подбирать цвета. Также доступны такие функции как opacify и transparentize (более подробно).
@строки
SASS умеет складывать строки, а также поддерживает конструкцию #<>
$image_dir: 'images/web/'; $page: 12; .some < background-image: url( $image_dir + 'pen.gif' ); &:before < content: "Страница #< $page >!"; > > /* => */ .some < background-image: url("images/web/pen.gif"); >.some:before
Полагаю, что наибольшее применение операциям над строками можно найти в @миксинах и переменных, указывающих пути к изображениям и пр.
Статья
В виду того, что статья получилась довольно объёмной, я решил разбить её на 2 части. В следующей статье я рассмотрю (синтаксис и область применения):
- @mixin ― пользовательские функции
- @if ― условия
- @each ― циклы
- Несколько дизайнов для одного сайта
- По желанию читателей
Ссылки
- Официальная страница язык
- Песочница
- Документация
Пишем CSS лучше и красивее

Когда при разработке приложений приходилось браться за CSS, это была не самая радостная часть работы. Но ее ведь не избежать, верно? Сегодня порадовать пользователя дизайном приложения настолько важно, что без CSS — никак.
Когда проект только начинается, все идет хорошо. У вас всего пару селекторов: .title , input , #app — проще простого.
Но постепенно приложение разрастается, и заглядывать в CSS становится страшновато: во всех этих селекторах разобраться уже не так просто. Вы начинаете писать что-то вроде div#app .list li.item a , какие-то куски кода повторяются снова и снова, а всю свою писанину сваливаете в конец файла: вам уже плевать, потому что CSS — отстой. Итог — 500 строк CSS-кода, поддерживать который невозможно.
Это я, когда сражаюсь с CSS
Переведено в Alconost
Моя задача сегодня — научить вас писать CSS лучше. Я хочу, чтобы, взглянув на старые проекты, вы подумали: «О боги! Как можно было написать такое?»
А как же CSS-фреймворки? — спросите вы. Они ведь для этого и придуманы — писать хороший CSS-код.
Правильно. Но у них есть недостатки:
- Дизайн на выходе часто получается скучный.
- Бывает сложно сделать нужные настройки или выйти за рамки возможностей фреймворка.
- Чтобы пользоваться фреймворками, сначала нужно их изучить.
Примечание. Это статья не о том, как создавать красивые приложения, а о том, как писать поддерживаемый CSS-код и как его упорядочить.
SCSS
В примерах я буду использовать SCSS.
SCSS — это препроцессор CSS, по сути — надмножество CSS, которое добавляет некоторые классные возможности, например, переменные, вложенность, импорт и примеси («миксины»).
Далее я расскажу, какие возможности мы будем использовать здесь.
Переменные
В SCSS есть переменные, и основное их преимущество — повторное использование. Предположим, у вас есть палитра цветов для приложения, и основной цвет — синий.
Поэтому синий у вас везде: фон background-color кнопок, цвет color заголовков, ссылок. СИНИЙ — ПОВСЮДУ.
И вдруг синий вам разонравился. Новый фаворит — зеленый.
- Если вы не использовали переменные, придется изменять все строки, в которых стоит синий.
- А с переменными достаточно изменить значение одной из них.
// Объявление переменной $primary-color: #0099ff; // Ссылка на переменную h1
Вложенность
В SCSS можно использовать вложенность. Поэтому из фрагмента
h1 < font-size: 5rem; color: blue; >h1 span
можно сделать такой код:
Последнее читается лучше, правда? Вложенность позволяет меньше времени тратить на написание сложных селекторов.
Импорт и частичные файлы
Если нужно обеспечить поддерживаемость и удобочитаемость, хранить весь код в одном огромном файле — плохая идея. Если вы экспериментируете или пишете небольшое приложение, это еще терпимо, но на профессиональном уровне… даже не пытайтесь. К счастью для нас, SCSS решает эту проблему.
Мы можем создавать «частичные файлы» — у которых имя начинается с символа подчеркивания: _animations.scss, _base.scss, _variables.scss и так далее.
Для их импорта используется соответствующая директива: @import . Например, можно сделать так:
// _animations.scss @keyframes appear < 0% < opacity: 0; >100% < opacity: 1; >> // header.scss @import "animations"; h1
Вы могли подумать: «Ага! У него здесь ошибка! Нужно писать _animations.scss , а не animations ».
Не-а. SCSS достаточно умен, чтобы понять, что в этом случае речь идет о частичном файле.
Это все, что нам нужно знать о переменных, вложенности, частичных файлах и импорте. У SCSS есть и другие возможности — примеси, наследование и различные директивы ( @for , @if , …), но их я затрагивать здесь не буду.
Если вам интересно — почитайте документацию: она достаточно понятно и хорошо написана.
Упорядочивание CSS-кода: методология БЭМ
Я бесчисленное множество раз использовал общие названия для CSS-классов. Ну, вы знаете: .button .page-1 .page-2 .custom-input .
Часто мы понятия не имеем, какое имя выбрать — хотя именование это важная задача. Представьте, что вы начали писать приложение, а затем решили отложить это дело на несколько месяцев — или, что еще хуже, кто-то взял ваш проект на себя. Если не продумать именование в CSS-коде, будет сложно сходу понять, что имеется в виду в конкретной строчке.
БЭМ помогает решить эту проблему. БЭМ — это соглашение об именовании; расшифровывается как блок, элемент, модификатор.
Эта методология поможет структурировать код, сделать его более модульным и упростить повторное использование. Разберемся, что же значат «блок», «элемент» и «модификатор».
Блоки
Блок можно представить себе как компонент. Возьмем, к примеру, конструктор Lego.
Как из конструктора сделать простой дом? Понадобятся окно, крыша, дверь, пару стен — и всё. Как раз это и есть наши блоки — они несут смысл сами по себе.
Именование: название блока: .block
Примеры: .card, .form, .post, .user-navigation
Элементы
А как из кубиков конструктора сделать окно? Можно найти кубики, которые выглядят как части рамы, и собрать из них красивое окно. Это и будут наши элементы. Они представляют собой необходимые части блока, но вне блока сами по себе бесполезны.
Именование: название блока + __ + название элемента: .block__element
Примеры: .post__author, .post__date, .post__text
Модификаторы
Итак, мы сделали какое-то окно. Теперь нам понадобилось зеленое или, например, маленькое окно. Это будут наши модификаторы. Они представляют собой флаги на блоках и элементах, которые используются для изменения поведения, внешнего вида и т. д.
Именование: название блока ИЛИ элемента + — + название модификатора: .block__element—modifier, .block—modifier
Примеры: .post—important, .post__btn—disabled
Примечания
- БЭМ подразумевает именование классов и только классов. Не идентификаторов и не тегов — только классов.
- Блоки и элементы могут вкладываться в другие блоки и элементы, но они должны быть полностью независимыми. Обязательно независимыми. Поэтому не нужно добавлять кнопке поля, чтобы она была под заголовком, иначе она будет привязана к заголовку. Лучше использовать вспомогательные классы.
- Да, HTML-файл будет перегружен, но это не страшно: преимущества БЭМ перевешивают этот недостаток.
Пример
Небольшое упражнение для читателей. Походите по сайтам, на которых вы часто бываете, и подумайте, какие там могли бы быть блоки, элементы и модификаторы.
Например, такую картину я могу вообразить в магазине Google:

Теперь ваша очередь. Проявите любопытство и подумайте, что можно было бы сделать лучше. И конечно, чтобы совершенствовать собственные навыки, нужно самостоятельно искать, экспериментировать и писать код.
Упорядочивание CSS-файлов: принцип «7–1»
Я вас еще не утомил? Отлично! Давайте разберемся, как же упорядочить CSS-файлы. Это здорово повысит эффективность работы и поможет мгновенно находить CSS-код, который нужно поправить.
Пришло время познакомиться с принципом «7–1».
Эти цифры ни о чем вам не говорят, да?
Но всё довольно просто. Нужно следовать двум правилам:
- Размещайте частичные файлы в 7 папках.
- Импортируйте их все в один файл main.scss , расположенный в корне. Вот и всё.
Семь папок:
- Папка base — шаблонный CSS-код, который вы пишете всякий раз, когда начинаете новый проект. Это могут быть правила верстки, анимации, вспомогательные классы (например, margin-right-large , text-center , …) и так далее.
- Папка components — все компоненты, используемые для формирования страниц: кнопки, формы, модули листания — «свайперы», всплывающие окна и т. д.
- Папка layout — для компоновки различных частей страницы, то есть шапки, подвала, навигации, разделов, собственной сетки и т. д.
- Папка pages — для страниц, которым нужен отдельный стиль, отличающийся от стандартного.
- Папка themes — для различных тем приложения (темный режим, администрирование и т. д.).
- Папка abstracts — все функции, переменные и примеси. Короче говоря, вспомогательные штуки.
- Папка vendors — внешние библиотеки, без которых не обходится, пожалуй, ни одно приложение. В папке vendors лежат файлы, которые от вас не зависят: файлы Font Awesome, Bootstrap и всё такое.
Основной файл
Сюда импортируются все частичные файлы.
@import abstracts/variables; @import abstracts/functions; @import base/reset; @import base/typography; @import base/utilities; @import components/button; @import components/form; @import components/user-navigation; @import layout/header; @import layout/footer; …
Да, выглядит немножко раздуто, признаю. Но эта архитектура придумана для крупных проектов — а для задач помельче есть другой вариант.
Во-первых, нам не понадобится папка vendors : весь внешний CSS-код будет в теге link , помещенном в заголовок. Также не нужна папка themes : скорее всего, у небольшого приложения будет всего одна тема. Наконец, не будет и стилей для конкретных страниц — поэтому убираем соответствующую папку. Итак, осталось четыре папки — отлично!
Теперь у нас два варианта:
- Если следовать принципу «7–1», нужно сохранить папки abstracts , components , layout и base .
- Если вам удобнее работать с большой папкой, в которой будут все частичные файлы и main.scss , получится что-то такое:
sass/ _animations.scss _base.scss _buttons.scss _header.scss … _variables.scss main.scss
Убедил! Как всё это применять? В смысле, браузеры же не поддерживают файлы scss , да?
Верно подмечено! На последнем этапе мы будем компилировать SCSS в CSS.
Из SCSS делаем CSS
Нам понадобятся Node.js и NPM (или Yarn).
Мы будем использовать пакет node-sass , который позволит компилировать файлы .scss в .css .
Интерфейс у него довольно простой:
node-sass [параметры]
- Параметр -w — следить за каталогом или файлом. Пакет node-sass будет ждать изменений в коде, а как только обнаружит их, сразу же скомпилирует соответствующий файл в CSS, что очень удобно при разработке.
- Параметр —output-style — как будет выглядеть выходной CSS-файл. Может принимать следующие значения: nested|expanded|compact|compressed . Мы будем использовать этот параметр при сборке CSS-файла.
Теперь мы знаем, какие инструменты будут использоваться. Остальное сделать еще проще:
- Создаем проект: mkdir my-app && cd my-app
- Инициализируем его: npm init
- Добавляем библиотеку node-sass : npm install node-sass —save-dev
- Создаем нужные папки, файлы index.html и main.scss :
touch index.html mkdir -p sass/ css cd sass && touch main.scss
- Добавляем в файл package.json такие сценарии:
- Добавляем ссылку на скомпилированный CSS-файл в тег head файла index.html:
My app My app
Вот и всё! Когда будете писать код, запустите npm run watch и откройте в браузере файл index.html . Чтобы уменьшить CSS, достаточно запустить npm run build .
Кое-что еще
Перезагрузка на лету
Чтобы работа лучше спорилась, можно добавить автоматическую перезагрузку локального файла index.html .
- Устанавливаем пакет live-server : npm install -g live-server
Примечание: это глобальный пакет. - Добавляем npm-run-all в зависимости проекта: npm install npm-run-all —save-dev — это позволит запускать несколько сценариев одновременно.
- Добавляем в package.json такие сценарии:
Теперь, если запустить npm run start , изменения будут отображаться сразу — без лишних движений с вашей стороны.
Автоматические префиксы
Мы настроили инструменты разработки — отлично! Теперь поговорим об инструментах сборки, в частности — об этом: Autoprefixer.
Этот инструмент (а точнее, плагин «postcss») анализирует CSS и добавляет к правилам CSS префиксы поставщиков, используя значения из Can I Use.
При создании веб-сайта могут использоваться новые функции, которые поддерживаются не во всех браузерах. Реализовать поддержку таких функций позволяют префиксы поставщиков.
Пример того, как оно будет выглядеть:
-webkit-animation-name: myAnimation; -moz-animation-name: myAnimation; -ms-animation-name: myAnimation;
Да-да, писать это вручную — утомительно. Облегчит нам жизнь инструмент для автоматического добавления префиксов, который сделает CSS-код совместимым с браузерами без дополнительных усилий.
Итак, чтобы собрать CSS:
- Компилируем все SCSS-файлы в один CSS-файл.
- Добавляем префиксы, используя Autoprefixer.
- Сжимаем CSS-файл.
- Добавляем две зависимости — postcss-cli и autoprefixer : npm install autoprefixer postcss-cli —save-dev
- Изменяем сценарий build и добавляем в package.json эти строки:
Теперь при запуске npm run build будут добавлены префиксы поставщиков, а сам CSS-код будет сжат. Просто магия!
А хотите еще немножко волшебства? Я поднял репозиторий — чтобы вы могли разобраться побыстрее?
Если вам интересно, как я применил эти навыки на странице своего портфолио, загляните в этот репозиторий и полюбуйтесь на результат. Надеюсь, эти примеры помогут лучше понять то, о чем шла речь в статье.
И… это всё на сегодня! Теперь вы умеете писать поддерживаемый модульный CSS-код с возможностью повторного использования.
О переводчике
Перевод статьи выполнен в Alconost.
Alconost занимается локализацией игр, приложений и сайтов на 68 языков. Переводчики-носители языка, лингвистическое тестирование, облачная платформа с API, непрерывная локализация, менеджеры проектов 24/7, любые форматы строковых ресурсов.
Мы также делаем рекламные и обучающие видеоролики — для сайтов, продающие, имиджевые, рекламные, обучающие, тизеры, эксплейнеры, трейлеры для Google Play и App Store.
- Блог компании Alconost
- Веб-разработка
- CSS
- Браузеры
Настройка Webpack 5 с нуля

Если вы раньше использовали вебпак 4, вот некоторые отличия от 5 версии:
- команда «webpack-dev-server» теперь выглядит как «webpack-serve»
- отдельная установка file-loader, raw-loader и url-loader больше не требуется, вы можете использовать встроенные загрузчики ресурсов (asset modules)
- полифилы для Node.js больше не поддерживаются, поэтому если, например, вы получили ошибку для stream, необходимо добавить пакет «stream-browserify» в качестве зависимости и < stream: «stream-browserify» >в качестве алиаса в настройки вебпака
Что такое вебпак?
По большей части, сайты больше не пишутся на чистом HTML с небольшим количеством JavaScript — часто они создаются только с помощью JavaScript. Поэтому возникает необходимость в сборке, минификации и транспиляции кода. Вот где вебпак приходит на помощь.
Вебпак — это сборщик модулей. Он служит для упаковки кода для использования браузером. Он позволяет использовать последние возможности JavaScript с помощью Babel или использовать TypeScript и компилировать его в кроссбраузерный минифицированный код. Он также позволяет импортировать статические ресурсы в JavaScript.
Для разработчиков вебпак также предоставляет сервер для разработки, который умеет обновлять модули и стили на лету при сохранении файла. Инструменты командной строки, такие как «vue create» и «react-create-app» используют вебпак за сценой, но вы легко можете создать собственную настройку вебпака для указанных фреймворков.
Вебпак также умеет делать много других вещей, но данная статья посвящена основам его настройки и использования.
Установка
Создаем директорию проекта и инициализируем его:
mkdir webpack-tutorial cd !$ // или cd webpack-tutorial yarn init -yp // создает стандартный приватный файл "package.json" // или npm init -y
Устанавливаем webpack и webpack-cli в качестве зависимостей для разработки:
yarn add -D webpack webpack-cli // или npm i -D webpack webpack-cli
- webpack — сборщик модулей и ресурсов
- webpack-cli — интерфейс командной строки для вебпака
console.log("Как интересно!")
Отлично, у нас имеется Node.js-проект с установленными основными пакетами и файл «index.js». Займемся настройкой вебпака.
Базовая настройка
Приступим к настройке сборщика. Создаем файл «webpack.config.js» в корневой директории проекта.
Точка входа
Прежде всего, необходимо определить точку входа приложения, т.е. то, какие файлы вебпак будет компилировать. В приведенном примере мы определяем точку входа как «src/index.js»:
// webpack.config.js const path = require('path') module.exports = < entry: < main: path.resolve(__dirname, './src/index.js'), >, >
Точка выхода
Точка выхода — это директория, в которую помещаются скомпилированные вебпаком файлы. Установим точку выхода как «dist». Префикс «[name]» соответствует названию файла в src:
// webpack.config.js module.exports = < // . output: < path: path.resolve(__dirname, './dist'), filename: '[name].bundle.js', >, >
Минимальная настройка для сборки проекта готова. Добавляем скрипт «build» в файл «package.json», запускающий команду «webpack»:
// package.json "scripts":
yarn build // или npm run build
asset main.bundle.js 19 bytes [emitted] [minimized] (name: main) ./src/index.js 18 bytes [built] [code generated] webpack 5.1.0 compiled successfully in 152 mss
В директории «dist» создается файл «index.bundle.js». Файл не изменился, но мы успешно осуществили сборку проекта.
Плагины
Интерфейс плагинов делает вебпак очень гибким. Плагины используются как самим вебпаком, так и сторонними расширениями. Некоторые плагины используются почти в каждом проекте.
Плагин создания HTML на основе шаблона
У нас есть готовая сборка, но она бесполезна без разметки, которая загрузит сборку в качестве скрипта. Поскольку мы хотим, чтобы такой HTML-файл генерировался автоматически, используем html-webpack-plugin.
- html-webpack-plugin — создает HTML-файл на основе шаблона
yarn add -D html-webpack-plugin
Создаем файл «template.html» в директории «src». Мы можем добавить в шаблон переменные и другую информацию. Добавим переменную «title», в остальном шаблон будет выглядеть как обычный HTML-файл с контейнером с идентификатором «root»:
Добавляем в настройки вебпака свойство «plugins», где определяем плагин, название выходного файла (index.html) и шаблон:
// webpack.config.js const path = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') module.exports = < // . plugins: [ new HtmlWebpackPlugin(< title: 'webpack Boilerplate', template: path.resolve(__dirname, './src/template.html'), // шаблон filename: 'index.html', // название выходного файла >), ], >
Запускаем сборку. Директория «dist» теперь содержит файл «index.html» с подключенным в нем скриптом. Круто! Если вы откроете этот файл в браузере, то увидите сообщение «Как интересно!» в консоли.
Добавим немного контента в DOM. Изменим содержимое файла «index.js» и перезапустим сборку.
// index.js // создаем элемент заголовка const heading = document.createElement('h1') heading.textContent = 'Как интересно!' // добавляем заголовок в DOM const root = document.querySelector('#root') root.append(heading)
Перейдите в директорию «dist» и запустите сервер (для этого необходимо глобально установить http-server: yarn global add http-server или npm i -g http-server).
http-server
В открывшейся вкладке браузера вы должны увидеть заголовок, гласящий «Как интересно!». Также обратите внимание на уменьшение размера файла.
Очистка
Установим clean-webpack-plugin, очищающий директорию «dist» при каждой сборке проекта. Это позволяет автоматически удалять старые файлы, ставшие ненужными.
- clean-webpack-plugin — удаляет/очищает директорию сборки проекта
// webpack.config.js const HtmlWebpackPlugin = require('html=webpack-plugin') const < CleanWebpackPlugin >= require('clean-webpack-plugin') module.exports = < // . plugins: [ // . new CleanWebpackPlugin(), ], >
Модули и загрузчики
Вебпак использует загрузчики для разбора файлов, загружаемых с помощью модулей. Это могут быть JavaScript-файлы, статические ресурсы, такие как изображения или стили и компиляторы, такие как TypeScript и Babel. Вебпак 5 имеет несколько встроенных загрузчиков ресурсов.
В нашем проекте имеется HTML-файл, который загружает некоторый скрипт, но больше он ничего не делает. Давайте подумаем, чего мы хотим от сборщика?
- Компиляция новейших возможностей JavaScript в код, совместимый со всеми или большинством браузеров
- Импорт стилей и преобразование SCSS в CSS
- Импорт изображений и шрифтов
- Настройка React или Vue (опционально)
Babel (JavaScript)
Babel — это инструмент, позволящий использовать будущий JavaScript сегодня.
Мы собираемся определить правило, согласно которому все файлы с расширением «js» в проекте (кроме файлов, содержащихся в директории «node_modules») будут транспилироваться с помощью babel-loader. Для работы Babel требуется несколько зависимостей:
- babel-loader — транспиляция файлов с помощью Babel и вебпака
- @babel/core — транспиляция ES2015+ в обратно совместимый JavaScript
- @babel/preset-env — полезные стандартные настройки Babel
- @babel/plugin-proposal-class-properties — пример кастомной конфигурации Babel (установка свойств экземпляров в теле класса, а не в его конструкторе)
yarn add -D babel-loader @babel/core @babel/preset-env @babel/plugin-proposal-class-properties
// webpack.config.js module.exports = < // . module: < rules: [ // JavaScript < test: /\.js$/, exclude: /node_modules/, use: ['babel-loader'], >, ], > >
Если вы настраиваете TypeScript-проект, то вместо babel-loader следует использовать typescript-loader для всех JavaScript-файлов, нуждающихся в транспиляции. Вы проверяете файлы с расширением «ts» и используете ts-loader.
Итак, Babel настроен, но плагин еще нет. Вы можете убедиться в этом, добавив следующий код в начало index.js:
// index.js // создание свойства класса без конструктора class Game < name = 'Violin Charades' >const myGame = new Game() // создаем параграф const p = document.createElement('p') p.textContent = `I like $.` // создаем элемент заголовка const heading = document.createElement('h1') heading.textContent = 'Как интересно!' // добавляем параграф и заголовок в DOM const root = document.querySelector('#root') root.append(heading, p)
ERROR in ./src/index.js Module build failed (from ./node_modules/babel-loader/lib/index.js): SyntaxError: /Users/you/webpack-tutorial/src/index.js: Support for the experimental syntax 'classProperties' isn't currently enabled (3:8): 1 | // Create a class property without a constructor 2 | class Game < >3 | name = 'Violin Charades' | ^ 4 | >
Для того, чтобы это исправить, создаем файл «.babelrc» в корне проекта:
// .babelrc < "presets": ["@babel/preset-env"], "plugins": ["@babel/plugin-proposal-class-properties"] >
Запускаем сборку с помощью yarn build. Теперь все работает.
Изображения
Мы хотим импортировать изображения в JavaScript-файл, но JavaScript не умеет этого делать. Чтобы убедиться в этом, создаем директорию «src/images», помещаем туда изображение и пытаемся импортировать его в файле «index.js»:
// index.js import example from './images/example.png' // .
При запуске сборки будет выброшено исключение:
ERROR in ./src/images/example.png 1:0 Module parse failed: Unexpected character '�' (1:0) You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
Как отмечалось ранее, вебпак обладает некоторыми встроенными загрузчиками для работы со статическими файлами. Для изображений следует использовать тип «asset/resource». Обратите внимание, что речь идет именно о типе (type), а не о загрузчике (loader):
// webpack.config.js module.exports = < // . module: < rules: [ // изображения < test: /\.(?:ico|gif|png|jpg|jpeg)$/i, type: 'asset/resource', >, ], >, >
В директории «dist» появляется новый файл.
Шрифты и другие встраиваемые данные
Вебпак также имеет встроенный модуль для обработки некоторых встраеваемых данных, таких как шрифты и SVG. Для этого достаточно указать тип «asset/inline»:
// index.js import example from './images/example.svg' // .
// webpack.config.js module.exports = < // . module: < rules: [ // шрифты и SVG < test: /\.(woff(2)?|eot|ttf|otf|svg|)$/, type: 'asset/inline', >, ], >, >
Стили
Использование загрузчиков стилей является необходимым условием использования строк наподобие «import ‘file.css’» в скрипте.
Многие люди используют CSS-in-JS, стилизованные компоненты (styled components) и другие инструменты, позволяющие использовать стили в JavaScript.
Порой мы можем ограничиться загрузкой одного CSS-файла. Но, возможно, вы хотите использовать PostCSS, позволяющий использовать последние возможности CSS в браузере. Или вы хотите использовать препроцессор Sass.
Я хочу использовать все три — писать код на Sass, обрабатывать его с помощью PostCSS и компилировать в CSS.
- sass-loader — загружает SCSS и компилирует его в CSS
- node-sass — Node Sass
- postcss-loader — обработка CSS с помощью PostCSS
- postcss-preset-env — полезные настройки PostCSS
- css-loader — загрузка стилей
- style-loader — применение стилей к элементам DOM
yarn add -D sass-loader postcss-loader css-loader style-loader postcss-preset-env node-sass
Как и для Babel, для PostCSS требуется отдельный файл настроек:
// postcss.config.js module.exports = < plugins: < 'postcss-preset-env': < browsers: 'last 2 versions', >, >, >
Для проверки работоспособности названных инструментов создадим файл «src/styles/main.scss», содержащий переменные Sass и пример использования PostCSS (lch):
// src/styles/main.css $font-size: 1rem; $font-color: lch(53 105 40); html
Импортируем этот файл в index.js и добавляем 4 загрузчика. Загрузчики используются вебпаком справа налево, так что последним должен быть sass-loader, затем PostCSS, затем CSS и, наконец, style-loader, который применяет скомпилированные стили к элементам DOM:
// index.js import './styles/main.css' // .
// webpack.config.js module.exports = < // . module: < rules: [ // CSS, PostCSS, Sass < test: /\.(scss|css)$/, use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'], >, ], >, >
После сборки вы заметите, что Sass и PostCSS применились к DOM.
Обратите внимание, что мы установили настройки для режима разработки. Для продакшна следует использовать MiniCssExtractPlugin вместо style-loader, который экспортирует минифицированный CSS.
Разработка
Каждый раз набирать команду yarn build (npm run build) при необходимости повторной сборки проекта может быть утомительным. Чем больше проект, тем дольше он будет собираться. Поэтому необходимо иметь два файла настроек вебпака:
- Настройки для продакшна, включающие минификацию, оптимизацию и удаление всех карт ресурсов (source maps)
- Настройки для разработки, включая запуск сервера, обновление при каждом изменении и карты ресурсов
Для этого необходимо установить webpack-dev-server.
- webpack-dev-server — это сервер для разработки
yarn add -D webpack-dev-server
В целях демонстрации принципов использования сервера для разработки мы можем определить соответствующие настройки в файле «webpack.config.js». На практике лучше иметь два файла настроек: один с mode: production и другой с mode: development. В специально подготовленной для вас webpack 5 boilerplate я использую webpack-merge для получения базовых настроек в виде одного файла, а специальные требования содержатся в файлах «webpack.prod.js» и «webpack.dev.js».
// webpack.config.js const webpack = require('webpack') module.exports = < // . mode: 'development', devServer: < historyApiFallback: true, contentBase: path.resolve(__dirname, './dist'), open: true, compress: true, hot: true, port: 8080, >, plugins: [ // . // применять изменения только при горячей перезагрузке new webpack.HotModuleReplacementPlugin(), ], >
Мы добавили mode: development и свойство «devServer». В данном свойстве содержится несколько стандартных настроек — номер порта (8080), автоматическое открытие браузера, использование hot-module-replacement, для которого нужен webpack.HotModuleReplacement(). Это позволит модулям обновляться без полной перезагрузки страницы, т.е. если изменятся отдельные стили, только они будут обновлены, вам не потребуется перезагружать JavaScript, что очень сильно ускоряет разработку.
Для запуска сервера используется команда «webpack serve»:
// package.json "scripts":
yarn start
После запуска этой команды браузер откроется по адресу localhost:8080. Теперь вы можете изменять Sass и JavaScript и они будут обновляться на лету.
Заключение
Надеюсь, данная статья помогла вам начать знакомство с вебпаком. Для облегчения решения ваших повседневных задач мной разработан webpack 5 boilerplate с Babel, Sass, PostCss, оптимизацией для продакшна и сервером для разработки. Взяв его за основу, вы легко сможете настроить вебпак для работы с React, Vue или TypeScript.
- Веб-разработка
- JavaScript
- Программирование
Автоматическая компиляция SASS в CSS
Поначалу для компиляции sass-файлов в css я использовал сторонние программы, вроде Koala. Через какое-то время она стала жутко тормозить и грузить комп и чем больше отслеживаемых файлов, тем больше эти тормоза. После этого я попробовал поработать через Grunt, но там не очень удобно добавлять каталоги, да и когда их много для отслеживания, тоже возникает большая нагрузка.
В итоге я поменял сам подход к sass-компиляции. Вместо того, чтобы отслеживать сразу кучу каталогов и файлов, достаточно отслеживать только те, с которым идет работа прямо сейчас.
В Sass уже встроена поддержка отслеживания файлов (watch), поэтому можно легко ей воспользоваться.
Важно! Сейчас команда Sass поддерживает только компилятор Dart Sass. Старые версии, основанные на Ruby, не поддерживают многие новые возможности Sass.
В каталог шаблона assets размещается файл sass-watch.bat такого содержания:
sass --watch sass:css --style=compressed
Пути указываются относительно этого файла. В данном случае это будет так:
- assets/sass/ — каталог, где находятся scss-файлы
- assets/css/ — каталог, куда помещаются скомпилированные css-файлы
Если не нужно создавать map-файл, то добавьте параметр —no-source-map .
Теперь, когда нужно включить компиляцию, достаточно запустить этот bat-файл, который запустит Sass в режиме watch. После того, как работа завершена, окно можно закрыть.
В некоторых случаях нужно просто выполнить компиляцию файлов без режима watch. В этом случае можно сделать sass-compile.bat :
sass --update sass:css --style=compressed
Теперь пару слов о самих sass/scss-файлах. Если имя файла начинается с символа подчеркивания («_»), то такой файл не компилируется (но отслеживается!). Таким образом без символа подчеркивания нужно оставить только тот файл, который следует скомпилировать. Обычно это style.scss из которого получится style.css.
