День добрый, читатели !
В этой статье спешу вам рассказать (хоть и с опозданием) о том что такое WebJars на примере приложения в Play Framework
В практически любом веб-приложении нельзя обойтись без сторонних javascript-библиотек. Самый простой способ добавить их: скачать и добавить в проект, а также добавить файл в git-репозиторий. Решение годное, но лично для меня наличие в проекте какой-либо статики малость раздражает. Есть другой метод: указывать ссылку на внешний
Ближе к делу
У нас есть веб-приложение, написанное на java-based языке и нам нужно добавить в него пару javascript библиотек, именно для такого случая нам идеально подойдут WebJars
WebJars — набор библиотек, каждая из которых содержит в себе JS библиотеку и/или CSS модули
Полный список библиотек можно посмотреть здесь. У каждой из них есть несколько версий которые соответствуют версии js-библиотеки. Все WebJars доступны на Maven репозитории
В данном примере я опишу, как WebJars в приложение Play Framework. Описания добавления WebJars в другие фреймворки можно найти здесь
Приступаем
Для того, чтобы добавить WebJar достаточно добавить новую зависимость в проект
К примеру
libraryDependencies ++= Seq(
cache,
ws,
"org.webjars" %% "webjars-play" % "2.3.0-2",
"org.webjars" % "requirejs" % "2.1.14-3",
"org.webjars" % "requirejs-domready" % "2.0.1-2",
"org.webjars" % "jquery" % "2.1.1",
"org.webjars" % "bootstrap" % "3.2.0-2"
)
Если вы скомпилируете проект, вы можете обнаружить новую папку web-modules в директории target/web. В ней как раз и содержаться добавленные в проект js и css файлы.
Обращаться к ним из view можно по старинке @routes.Assets.at(«lib/requirejs/require.js»), но для этого нужно знать полный путь. Другой более кошерный способ использовать готовые контроллеры WebJars. Для этого добавим в conf/routes новый маршрут специально для WebJars
GET /lib/*file controllers.WebJarAssets.at(file)
А для обращения к ним из view мы можем использовать еще метод от WebJars WebJarAssets.locate. Указанный метод сам ищет необходимый файл в каталоге с WebJars. В итоге получаем:
<link rel="stylesheet" href="@routes.WebJarAssets.at(WebJarAssets.locate("bootstrap.min.css"))">
Что на html странице будет выглядеть как
<link rel="stylesheet" href="/lib/bootstrap/3.2.0-2/css/bootstrap.min.css">
Удобно не правда ли? Но это еще не все
RequireJS
Наверняка вы уже слышали о прелестях этого замечательного js-фреймворка, поэтому не буду распинаться на эту тему
WebJars содержит в себе механизм для более удобной интеграции с RequireJS. Если вы зайдете в каталог target/web/web-modules/main/webjars/lib/jquery, то обнаружите файл webjars-requirejs.js c содержимым
/*global requirejs */
// Ensure any request for this webjar brings in jQuery.
requirejs.config({
paths: { "jquery": webjars.path("jquery", "jquery") },
shim: { "jquery": { "exports": "$" } }
});
В каждом WebJar есть файл с конфигом для RequireJS. Чтобы получить общий конфиг создадим новый view с именем requireJsConfig
@Html(org.webjars.RequireJS.getSetupJavaScript(routes.WebJarAssets.at("").url))
Добавим новый экшн в контроллер Application
import play.api.cache.Cached
import views._
import play.api.Play.current
def requireJsConfig = Cached("require_js_config") {
Action {
Ok(html.requireJsConfig()).as("application/javascript")
}
}
Результат выполнения мы кэшируем, поскольку его содержимое не будет меняться только при добавлении/удалении используемых в проекте WebJars. Также результат мы помечаем как application/javascript, чтобы явно указать в содержимое является javascript'ом
Добавляем новый маршрут
GET /files/config.js controllers.Application.requireJsConfig
Забавы ради url прописываем как у статического js-файла
Проверяем что получилось, в браузере переходим по url localhost:9000/files/config.js
var webjars = {
versions: {"requirejs-domready":"2.0.1","requirejs":"2.1.14-3","bootstrap":"3.2.0-2","jquery":"2.1.1"},
path: function(webJarId, path) {
console.error('The webjars.path() method of getting a WebJar path has been deprecated. The RequireJS config in the ' + webJarId + ' WebJar may need to be updated. Please file an issue: http://github.com/webjars/' + webJarId + '/issues/new');
return ['/lib/' + webJarId + '/' + webjars.versions[webJarId] + '/' + path];
}
};
var require = {
callback: function() {
// Deprecated WebJars RequireJS plugin loader
define('webjars', function() {
return {
load: function(name, req, onload, config) {
if (name.indexOf('.js') >= 0) {
console.warn('Detected a legacy file name (' + name + ') as the thing to load. Loading via file name is no longer supported so the .js will be dropped in an effort to resolve the module name instead.');
name = name.replace('.js', '');
}
console.error('The webjars plugin loader (e.g. webjars!' + name + ') has been deprecated. The RequireJS config in the ' + name + ' WebJar may need to be updated. Please file an issue: http://github.com/webjars/webjars/issues/new');
req([name], function() {;
onload();
});
}
}
});
// All of the WebJar configs
requirejs.config({"paths":{"requirejs-domready":["/lib/requirejs-domready/2.0.1/domReady","domReady"]}})
requirejs.config({"paths":{}})
requirejs.config({"paths":{"bootstrap":["/lib/bootstrap/3.2.0-2/js/bootstrap","js/bootstrap"],"bootstrap-css":["/lib/bootstrap/3.2.0-2/css/bootstrap","css/bootstrap"]},"shim":{"bootstrap":["jquery"]}})
requirejs.config({"paths":{"jquery":["/lib/jquery/2.1.1/jquery","jquery"]},"shim":{"jquery":{"exports":"$"}}}) }
}
Данный скрипт настраивает RequireJS необходимым нам образом и должен предшествовать самому RequireJS
Финал
Создадим небольшой coffescript файл (простите, если кого-то этим огорчил, но от чистого javascript я подустал) в каталоге app/assets/js/main.coffee
require ['jquery','requirejs-domready!'],->
$('body').text 'Success'
И в интересующей нас view, добавим
<script type="application/javascript" src="@routes.Application.requireJsConfig()"></script>
<script data-main="@routes.Assets.at("js/main.js")" src="@routes.WebJarAssets.at(WebJarAssets.locate("require.min.js"))"></script>
Запускаем и видим, что все необходимые javascript-файлы загрузились и код выполнился
Итог
В данном примере мы познакомились с возможностями WebJars. От себя добавлю, что ничего кардинально-инновационного я не обнаружил, но все же они облегчают frontend разработку.
Автор: lucky_libora