- PVSM.RU - https://www.pvsm.ru -
Сразу хочу оговорится, что данная статья не предназначена для тех, у кого разработка frontend основная деятельность. Целевая аудитория: разработчики backend которым понадобилось срочно прикрутить web UI или просто интересуются новыми областями, ну и возможно fullstack разработчики.
Итак, перейдем к проблеме. Вспоминается статья [1], а также, на просторах Хабара было еще несколько подобных. Представлены они все как шуточные, но как говорится «в каждой шутке есть доля правды», а тут даже и не доля… Но вот в чем вопрос, а действительно ли нужно все это?
Вопрос который я хотел бы поднять, преимущественно о сборке. Именно на этом этапе js-сообщество предлагает неимоверное количество инструментов, необходимость которых совсем не очевидна. Например, сообществом предлагается различные варианты работы с модулями, что имело смысл в свое время, но на данный момент спецификация на import [2]/export [3] поддерживается всеми современными браузерами, и даже недобраузером edge. В силу, оговорённой в начале, задачи, необходимости поддерживать что-либо более старое у нас и нету, так что мы смело останавливаемся на спецификации. А вот то что действительно будет нам необходимо, так это какая либо работа с зависимостями.
Сделаю небольшое отступление, чтобы объяснить выбор технологий, которые будут использоваться в примере для самого frontend’а. Чтобы не копаться в бесчисленном многообразие фреймворков, пойдем от замечательного стандарта [4]. Итак, все становится достаточно просто, виртуального DOM'а там нет, вебкомпоненты есть. На этом можно было бы закончить, но еще js. Если мы решим отделаться чистым [5] js – то придется как-то решать инфраструктурные задачи, избавляться от бойлерплет кода и т.д. Иными словами – городить свой велосипед… Чтобы этого не делать, хотелось бы взять что-нибудь, где все уже сделано и достаточно качественно. Соответственно выбор мой пал на Polymer [6] – фреймворк от Google, которые и пропихнули вебкомпоненты в стандарт.
Чтож, вернемся к сборке. Многие из вас (во всяком случае Java разработчики) привыкли к таким инструментом как maven и gradle, и наверняка успели выяснить, что они прекрасно справляются и с манипуляциями над ресурсами (у maven это конечно немного хуже, но вот у gradle — проблем нет собрать вообще все что угодно). Сообщество же frontend нам предлагает брать npm, для которого нужна nodeJs, но этого не хватит, еще и webpack сверху. А в них еще придется разбираться и ставить каждому разработчику. Эм… Хотелось бы просто выкачать репозиторий, сделать gradlew build и начать работать, так что давайте уж остановимся на привычном gradle.
Совсем без npm мы конечно обойтись не сможем, как минимум, нам нужен репозиторий откуда брать js библиотеки и npm это предоставляет, а вот утилита не обязательна. Можно найти несколько хороших решений вроде этого [7], но они всегда качают nodeJs, и запускают npm таски. Вариант, но мне бы хотелось бы минимизоровать общение с npm до взаимодействия с репозиторием и только. Как решиние было написать свой плагин для gradle. Хоть и писать плагины для gradle достаточно просто, в силу широкого разнообразия возможностей указания версий для npm репозитория, задача несколько усложняется. Благо на это есть понятная документация [8].
Итак, напишим gradle скрипт для загрузки зависимостей. Используется kotlin dsl по той причине, что переписать на groovy dsl достаточно тривиально, а вот наоборот пришлось бы потратить время, если не было ранее опыта.
repositories {
mavenLocal()
jcenter()
}
dependencies {
classpath("com.github.artfable.gradle:gradle-npm-repository-plugin:0.0.3")
}
apply(plugin = "artfable.npm")
configure<GradleNpmRepositoryExtension> {
output = "$projectDir/src/libs/"
dependencies = mapOf(
Pair("@polymer/polymer", "3.0.5"),
Pair("@polymer/app-layout", "3.0.1"),
Pair("@polymer/paper-toolbar", "3.0.1"),
Pair("@polymer/paper-icon-button", "3.0.1"),
Pair("@polymer/iron-icons", "3.0.1"),
Pair("@webcomponents/webcomponentsjs", "2.1.3")
)
}
Данный плагин [9] добавит нам таск npmLoad. Чтобы позволить IDE красиво сгрупировать, определим его в группу
tasks["npmLoad"].group = "frontend"
Отлично, можно попробовать написать код для нашего frontend. Встроенный сервер Intellij по умолчанию скажет вам что Method Not Allowed на попытку подключить скрипты через import. Чтобы это избежать – поставьте чекбокс allow using requests. (в последних версиях работает и без этого).
Попробуем теперь запустить, и… Все равно ничего не заработало. Отвалились зависимости внутри компонентов полимера. Дело в том, что многие js библиотеки пушут импорты с расчетом на какой-нибудь транспилер вроде babel. Такой import выглядит например так:
import '@polymer/polymer/polymer-legacy.js';
Что не правильно, так как для браузера путь должен начинаться только с ‘/’, ‘./’ или ‘../’. Кроме того, в таком виде его нельзя брать ни как относительный, ни как абсолютный, так как здесь идет расчет на начало из корня директории с библиотеками. Следовательно такие пути надо исправить, ну и чтобы не делать это самим – можно взять заготовленный плагин [10].
В зависимости
classpath("com.github.artfable.gradle:gradle-js-import-fix-plugin:0.0.1")
apply(plugin = "artfable.js.import.fix")
configure<GradleJsImportFixExtension> {
directory = "$projectDir/src/libs"
}
Добавится task jsImportFix который приведет все импорты в порядок.
Вот так просто, и без необходимости разбираться с горой новый инструментов, можно собрать фронт. Но давайте еще рассмотрим вопрос со стилями. Откровенно говоря, веб-компоненты позволяют избавится от бойлерплейта, а переменные в css, которые уже в стандарте – открывают множество возможностей, так что необходимости в таких вещах как sass уже больше нет. Но вдруг, например вам очень приглянулся bootstrap [11] и захотелось сделать дизайн на его основе.
Найти какой-нибудь плагин для сборки на этот счет не проблема, в основном, все они за основу берут libsass [12] и есть обертка на java — jsass [13]. Единственная проблема у всех (во всяком случае на момент когда я рассматривал их) в дуплицирование зависимых файлов.
Пример:
Файл a:
@import “b”;
@import “c”;
Файлы _b и _c:
@import “d”;
В результате мы получим в основном файле 2 одинаковых блока из файла _c. Можно достаточно просто исправить, если дописать импортер [14] к jsass, api позволяет. Собственно поэтому я опять со своим решением и здесь [15] (если подобных требований нет, то лучше воспользоваться другим решением).
Добавим в список npm зависимостей
Pair("bootstrap", "4.1.3")
Зависимость на плагин
classpath("com.github.artfable.gradle:gradle-sass-plugin:0.0.1")
apply(plugin = "artfable.sass")
configure<GradleLibsassPluginExtension> {
group(delegateClosureOf<GradleLibsassPluginGroup> {
sourceDir = "src/sass"
outputDir = "src/css"
} as Closure<Any>)
}
tasks.create("processResources")
Фейковый таск processResources придется создать, если не подключён java-plugin (а он нам здесь и не нужен). Это конечно недоработка, потом обязательно исправлю.
Обратите внимание на то, что полученный css файл нужно подключать не в head, так как внутри компонента он тогда не будет виден, а непосредственно в шаблон самого компонента.
Последним шагом можно немного изменить скрипт, чтобы получить привычную директорию build, с готовым проектом что можно деплоить на прод.
Полный код [16] выложил на github (наверно придется потом мигрировать на gitlab...).
Основная идея надеюсь понятно, а дальше можно добавлять достаточно просто абсолютно все что угодно.
Автор: artfable
Источник [17]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/307442
Ссылки в тексте:
[1] статья: https://habr.com/ru/post/312022
[2] import: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
[3] export: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export
[4] стандарта: https://spec.whatwg.org/
[5] чистым: https://www.ecma-international.org/ecma-262/8.0/
[6] Polymer: https://www.polymer-project.org/
[7] этого: https://github.com/srs/gradle-node-plugin
[8] документация: https://docs.npmjs.com/misc/semver
[9] плагин: https://github.com/artfable/gradle-npm-repository-plugin
[10] плагин: https://github.com/artfable/gradle-js-import-fix-plugin
[11] bootstrap: https://getbootstrap.com/
[12] libsass: http://sass-lang.com/libsass
[13] jsass: https://github.com/bit3/jsass
[14] импортер: https://jsass.readthedocs.io/en/latest/importers.html
[15] здесь: https://github.com/artfable/gradle-sass-plugin
[16] Полный код: https://github.com/artfable/frontend-demo
[17] Источник: https://habr.com/ru/post/438584/?utm_source=habrahabr&utm_medium=rss&utm_campaign=438584
Нажмите здесь для печати.