+7 (499) 346-87-75
11.08.2014

Оптимизация модулей RequireJS в Symfony2.

О пользе модульного подхода в программировании на любом языке говорилось уже достаточно много, по-этому приведу кратко основные положительные моменты для JS особо не вдаваясь в подробности. Разделение приложения на модули позволяет сделать код:

• значительно более читабельным и прозрачным для понимания

• гораздо более простым в поддержке

• гибким и расширяемым

• пригодным для написания достаточно больших приложений

• легко тестируемым и более простым в отладке

Так же документация модульного кода гораздо более эффективна.

Модульность, наряду с фреймворками, помогает вывести яваскрипт на качественно новый уровень и позволяет ему перейти из ранга вспомогательных и дополнительных в ранг серьезных самостоятельных языков программирования.

Однако, модульный подход на выходе обеспечивает нас множеством файлов, которые совершенно неэффективно вытягивать с сервера на клиент по одиночке из вполне очевидных причин.

Существует хорошо зарекомендовавшие себя библиотеки способные решить большинство поставленных задач и избежать отрицательных моментов. Одной из наиболее популярных библиотек для написания модульных приложений на яваскрипт является RequireJS. RequireJS хорошо документирована и касаться разработки с ее использованием в этой статье мы не будем. Рассмотрим подробнее как интегрировать RequireJS в Symfony2 с последующей оптимизацией созданных нами модулей. Для подобной цели очень кстати может оказаться HearsayRequireJSBundle, так что, какая проблема, берем бандл инсталлируем через компоузер и все! Возможно у кого-то так и получилось, однако могли возникнуть и некоторые нюансы. Чтобы максимально сгладить процесс знакомства с подобной интеграцией предлагаю прочесть то, что изложено ниже.

Установка бандла дело нехитрое: в composer.json пропишем


"hearsay/require-js-bundle": "2.0.*@dev"

Дальше, как предлагают в документации:


$ php composer.phar update hearsay/require-js-bundle

В AppKernel добавим:

	
new Hearsay\RequireJSBundle\HearsayRequireJSBundle(),
	

Пытаемся почистить кэш — выясняется, что конфигурация не отвечает требованиям. Во-первых, необходима установленная библиотека node.js (если нет) не беда:

	
sudo apt-get update; sudo apt-get install nodejs
	

Неплохо былобы иметь и саму Requirejs:

	
sudo npm install requirejs
	
- таким образом мы установим ее локально в папку проекта и будем соответственно использовать локальные пути к исполнимому файлу, можно, естественно и глобально с ключом «-g». Наш путь окажутся такими:
	
%kernel.root_dir%/../node_modules/requirejs/require.js
%kernel.root_dir%/../node_modules/requirejs/bin/r.js
	

- соответсевенно к require.js и к r.js. Именно r.js и есть та самая либа, которая поможет нам из кучи различных AMD JS модулей нашего проекта создать один, может не такой красивый, но очень оптимизированный файл для продакшена.

Теперь давайте попробуем сконфигурировать наш бандл:

	
# app/config/config.yml
hearsay_require_js:
    require_js_src:  //cdnjs.cloudflare.com/ajax/libs/require.js/2.1.14/require.min.js
    initialize_template: HearsayRequireJSBundle::initialize.html.twig
    #папка в которую будут собираться наши, не полностью обработанные, скрипты в «дев» версии
    #в каталоге «web».
    base_url:  js
    #путь к папке со скриптами в бандле
    base_dir: %kernel.root_dir%/../src/Acme/DemoBundle/Resources/assets/js # Required
    #пути к основным модулям и скриптам для
    #для внешних библиотек не забываем указывать «external: true»
    paths:
        main:
            location: @AcmeDemoBundle/Resources/assets/js/main
        jquery:
            location: //ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min 
            external: true
        underscore:
            location: //cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min
            external: true
        backbone:
            location: //cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.2/backbone-min
            external: true
        text:
            location: @AcmeDemoBundle/Resources/assets/js/vendor/text
        bootstrap:
            location: //maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min
            external: true		
    #конфиг  shim соответственно
    shim:
       bootstrap:
           deps: [jquery]
    #конфигурация оптимизатора, в нашем случае r.js
    optimizer:
        path: %kernel.root_dir%/../node_modules/requirejs/bin/r.js
        #для продакшена прячем все не оптимизированные файлы для папки web
        hide_unoptimized_assets: true
        #настройки оптимизатора (r.js например можно посмотреть здесь
	#https://github.com/jrburke/r.js/blob/master/build/example.build.js)
    options:
      removeCombined: true
      name: main
      #воспользуемся библиотекой uglify2 для оптимизации, она входит в стандартную сборку r.js
      optimize: uglify2
      #настройки для  uglify2
      uglify2:
         output:
            beautify: false
         compress:
           sequences: true
           global_defs:
             DEBUG: false
         warnings: true
         mangle: false
		

Где-нибудь в layout.twig вызов наших яваскриптов может выглядеть таким образом:

	
{% javascripts filter='requirejs'
	'@AcmeDemoBundle/Resources/assets/js/main.js'
%}
	{{ require_js_initialize({ 'main' : asset_url }) }}
{% endjavascripts %}

	

Если хотим, чтобы наши скрипты оптимизировались только на продакшене, а в «дев» версии были видны не оптимизированными, в определение фильтра добавим знак вопроса {% javascripts filter='?requirejs'... А в файле app/config/config_dev.yml, пропишем:

	
hearsay_require_js:
	optimizer:
		hide_unoptimized_assets: false

	

И, напоследок, раз уж заговорили про оптимизацию скриптов, оптимизация для css. Воспользуемся библиотекой uglifycss. Установка так же достаточно простая, как и с предыдущим модулем, из корневой директории сайта:

	
sudo npm install uglifycss
		

После успешной установки исполняемый файл найдем по адресу:

	
%kernel.root_dir%/../node_modules/uglifycss/uglifycss
	

В конфигурации объявим фильтр:

	
 app/config/config.yml
assetic:
	filters:
		uglifycss:
			bin: %kernel.root_dir%/../node_modules/uglifycss/uglifycss

	 

Созданный таким образом фильтр можно использовать в twig, например, так:

	
{% stylesheets '@AcmeDemoBundle/Resources/assets/css/*' filter='?uglifycss' filter='cssrewrite' %}
	<link rel="stylesheet" href="{{ asset_url }}"/>
{% endstylesheets %}

	

Таким образом, общая структура нашего приложения может иметь следующий вид:

	
//src/Acme/DemoBundle/Resources/assets/js/
bundles/
| --    user/
|       | --    collections/
|               | --    users.js
|       | --    models/
|               | --    user.js
|       | --    templates/
|               | --    user.html
|               | --    users.html
|       | --    main.js
vendor/
| --    text.js
app.js
main.js
router.js

//src/Acme/DemoBundle/Resources/assets/css/
style.css
user.css

	

В продакшен версии в папке «web» после выполнения команды

	
app/console assetic:dump --env=prod
	

появятся папки js/ и css/ и выглядеть они будут, как-то так:

	
web/
| --    css/
|        | --    ecde8f1.css
| --    js/
|        | --    b50c14d.js 

	

P.S. Чтобы получать наши новые статьи раньше других или просто не пропустить новые публикации - подписывайтесь на нас в Facebook, VK, Twitter, LiveJournal и LinkedIn

P.P.S. Совсем скоро в нашей бизнес-школе Digitov стартуют курсы: Хочу стать Junior PHP Developer!, Symfony 2. Гибкая разработка, Разработка веб-приложений на Python / Django и Ruby on Rails. По рельсам к профессиональной разработке. Подписывайтесь на курсы сейчас и сможете купить их со скидкой.

Автор

Сергей Харланчук
Сергей Харланчук
Senior Web Developer / Team Lead, компания SECL Group / Internet Sales Technologies
+7 (499) 346-87-75 info@seclgroup.ru

ВВЕРХ
Форма заказа