Optimising Your Front End Workflow With Symfony, Twig, Bower and Gulp

32,739 views

Published on

We take great care in our back end coding workflow, optimising, automating and abstracting as much as is possible. So why don't we do that with our front end code?

We'll take a look at some tools to help us take our front end workflow to the next level, and hopefully optimise our load times in the process!

We'll be looking at using Twig templates and optimising them for the different areas of your application, integrating Bower and Gulp for managing assets and processing our front-end code to avoid repetitive tasks - looking at how that impacts the typical Symfony workflow.

Published in: Technology
2 Comments
45 Likes
Statistics
Notes
  • hey, was wondering how to view project in browser after cloning the git repo locally.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • We were inspired by this talk to build gassetic - it's a gulp build tool that can be used for Symfony2
    https://github.com/crossborne/gassetic/blob/master/Resources/doc/GasseticAndSymfony2.md
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
32,739
On SlideShare
0
From Embeds
0
Number of Embeds
365
Actions
Shares
0
Downloads
213
Comments
2
Likes
45
Embeds 0
No embeds

No notes for slide

Optimising Your Front End Workflow With Symfony, Twig, Bower and Gulp

  1. OPTIMISING YOUR FRONT END WORKFLOW
  2. MATTHEW DAVIS @mdavis1982
  3. PhpSpec phpspec/nyan-formatters
  4. PhpSpec R! WW AW R phpspec/nyan-formatters
  5. Terrible at jokes
  6. Terrible at jokes Sorry!
  7. Advances in back end code
  8. D DD COM POSI TION ENICS STH CALI Advances in back end code Y R D TDD PSR ES FAC TER IN SOLID
  9. COMPOSER
  10. When we look at front end code…
  11. Cool tools for front end code
  12. BOWER S S LE SASS ANGULAR GRU NT I PT R for front end code SC E tools Cool FFE CO IG W GU T LP N MA EO Y REQUI RE JS
  13. * more And a GAZILLION
  14. * more And a GAZILLION *approximately
  15. Lack of practical examples
  16. 😢
  17. Let’s change that!
  18. 😄
  19. Example Project https://github.com/mdavis1982/workflow
  20. Example Project Simple Article Management https://github.com/mdavis1982/workflow
  21. Example Project Simple Article Management Administration Area https://github.com/mdavis1982/workflow
  22. Twig
  23. Insanely powerful
  24. Insanely powerful Compiled and cached
  25. Insanely powerful Compiled and cached Often overlooked
  26. Translate all the things
  27. Translations are notoriously messy
  28. But it’s easy to keep them organised
  29. config.yml framework:
 translator: { fallback: "%locale%" }
  30. Article.php /**
 * The title of the Article
 *
 * @var string
 *
 * @ORMColumn(type="string", length=255)
 *
 * @AssertNotBlank(message="article.title.not_blank")
 * @AssertLength(
 * max=255,
 * maxMessage="article.title.length.max"
 * )
 */
 protected $title;
  31. validators.en.yml article:
 title:
 not_blank: You must enter a title
 length:
 max: The title cannot be longer than {{ limit }} characters
 
 content:
 not_blank: You must enter some content

  32. ArticleType.php $builder
 ->add(
 'title',
 'text',
 [
 'label' => 'article.label.title'
 ]
 )
  33. ArticleType.php $builder
 ->add(
 'title',
 'text',
 [
 'label' => 'article.label.title'
 ]
 ) For all properties in the form
  34. forms.en.yml article:
 label:
 title: Title
 content: Content
 submit: Save

  35. forms.en.yml?!
  36. ArticleType.php /**
 * {@inheritdoc}
 */
 public function setDefaultOptions(OptionsResolverInterface $resolver)
 {
 $resolver->setDefaults([
 'data_class' => 'MDEntityArticle',
 'translation_domain' => 'forms'
 ]);
 }
  37. When your translations don’t work…
  38. CLEAR THE CACHE!
  39. CLEAR THE CACHE! Even in the dev environment
  40. Translate everything
  41. Translate everything All titles, actions, single words
  42. Translate everything All titles, actions, single words Translations per ‘section’
  43. admin.en.yml article:
 title:
 list: All Articles
 create: Add a New Article
 
 action:
 create: Add New
 cancel: Cancel

  44. list.html.twig {% block body %}
 <h1>{{ 'article.title.list'|trans({}, 'admin') }}</h1>
 {% if articles %}
 <ul class="articles">
 {% for article in articles %}
 <li>{{ article.title }}</li>
 {% endfor %}
 </ul>
 {% endif %}
 
 <a href="{{ path('admin.article.create') }}”> {{ 'article.action.create'|trans({}, 'admin') }} </a>
 {% endblock body %}
  45. Messy
  46. Template Inheritance
  47. Default base template
  48. base.html.twig <!DOCTYPE html>
 <html>
 <head>
 <meta charset="UTF-8" />
 <title>{% block title %}Welcome!{% endblock %}</title>
 {% block stylesheets %}{% endblock %}
 <link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" />
 </head>
 <body>
 {% block body %}{% endblock %}
 {% block javascripts %}{% endblock %}
 </body>
 </html>
  49. Doesn’t promote great code
  50. base.html.twig <!doctype html>
 
 <!--[if lt IE 7 ]> <html lang="en" class="no-js ie6 lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
 <!--[if IE 7 ]> <html lang="en" class="no-js ie7 lt-ie9 lt-ie8"> <![endif]-->
 <!--[if IE 8 ]> <html lang="en" class="no-js ie8 lt-ie9"> <![endif]-->
 <!--[if IE 9 ]> <html lang="en" class="no-js ie9"> <![endif]-->
 <!--[if (gt IE 9)|!(IE)]><!-->
 <html lang="en" class="no-js"><!--<![endif]-->
 <head>
 <meta charset="utf-8" />
 <title>{% block title %}{% endblock title %}</title>
 
 <!-- Set up mobile viewport for responsive design -->
 <meta name="viewport" content="width=device-width" />
 
 {% block stylesheets %}{% endblock stylesheets %}
 </head>
 <body>
 {% block content %}{% endblock content %}
 {% block javascripts %}{% endblock javascripts %}
 </body>
 </html>

  51. Gives us a better foundation
  52. The same HTML structure and assets per ‘section’?
  53. New ‘Layouts’ Directory
  54. Directory Structure
  55. admin.html.twig {% extends "::base.html.twig" %}
 
 {% block title %} {{ 'defaults.title'|trans({}, 'admin') }} {% endblock title %}
 
 {% block content %}
 {% block body %}{% endblock body %}
 {% endblock content %}

  56. frontend.html.twig {% extends "::base.html.twig" %}
 
 {% block title %}{{ 'defaults.title'|trans }}{% endblock title %}
 
 {% block content %}
 {% block header %}{% endblock header %}
 {% block body %}{% endblock body %}
 {% block footer %}{% endblock footer %}
 {% endblock content %}
  57. What?!
  58. Change the extends
  59. list.html.twig {% extends "MDMainBundle:Layouts:admin.html.twig" %}
 
 {% block body %}
 <h1>{{ 'article.title.list'|trans({}, 'admin') }}</h1>
 {% if articles %}
 <ul class="articles">
 {% for article in articles %}
 <li>{{ article.title }}</li>
 {% endfor %}
 </ul>
 {% endif %}
 
 <a href="{{ path('admin.article.create') }}”> {{ 'article.action.create'|trans({}, 'admin') }} </a>
 {% endblock body %}

  60. Given ourselves flexible base
  61. Given ourselves flexible base All boilerplate code is DRY
  62. Given ourselves flexible base All boilerplate code is DRY Defaults per ‘section’
  63. trans_default_domain
  64. list.html.twig {% extends "MDMainBundle:Layouts:admin.html.twig" %}
 
 {% trans_default_domain "admin" %}
 
 {% block body %}
 <h1>{{ 'article.title.list'|trans }}</h1>
 {% if articles %}
 <ul class="articles">
 {% for article in articles %}
 <li>{{ article.title }}</li>
 {% endfor %}
 </ul>
 {% endif %}
 
 <a href="{{ path('admin.article.create') }}”> {{ 'article.action.create'|trans }} </a>
 {% endblock body %}

  65. But wait!
  66. admin.html.twig {% trans_default_domain "admin" %}
  67. NOPE
  68. And it won’t be fixed
  69. Node.js http://nodejs.org
  70. Node.js Server-side JavaScript http://nodejs.org
  71. Node.js Server-side JavaScript Adds extra functionality http://nodejs.org
  72. npm
  73. npm Composer for node
  74. npm Composer for node Install globally or into project
  75. OMG!!1!
  76. Bower http://bower.io
  77. Demo: Installing Bower With No Sudo - Eek!
  78. 👎
  79. Demo: Installing Bower Successfully - Yay!
  80. 👍
  81. Getting stuff into your project
  82. Find dependencies
  83. Demo: Using Bower To Search For Packages - Modernizr
  84. Install dependencies
  85. Demo: Using Bower To Install Packages - Modernizr
  86. We can do better
  87. .bowerrc
  88. Demo: Using .bowerrc To Customise Installation Directory
  89. Better
  90. Better Save dependencies
  91. bower.json
  92. Demo: Using Bower To Save Dependencies To bower.json
  93. Don’t forget .gitignore
  94. Easy to reference assets
  95. Easy to reference assets {% block javascripts %} <script src="{{ asset('/vendor/modernizr/modernizr.js') }}"></script> {% endblock javascripts %}
  96. Easy to reference assets {% block javascripts %} <script src="{{ asset('/vendor/modernizr/modernizr.js') }}"></script> {% endblock javascripts %} Globally or per ‘section’
  97. Different locations?
  98. Non-standard install
  99. Non-standard install Make it clear
  100. Non-standard install Make it clear Potentially more flexibility
  101. Gulp http://gulpjs.com
  102. Build tool
  103. “ Every week someone who doesn’t understand Make writes a new build system in JavaScript. #gruntjs #gearjs #gulpjs #broccolijs. Laugh or cry? https://twitter.com/aslak_hellesoy/status/435506106496851968
  104. Streaming
  105. Plugin architecture
  106. Demo: Installing Gulp Globally With npm
  107. One extra step
  108. Demo: Installing Gulp and Gulp-Util Into A Project With npm
  109. Don’t forget .gitignore
  110. Minify JavaScript
  111. Demo: Using Gulp To Minify JavaScript
  112. Use it in our project
  113. frontend.html.twig {% block javascripts %}
 <script src="{{ asset('/web/js/vendor/modernizr.js') }}"></script>
 {% endblock javascripts %}
  114. ITCHY NOSE!!!
  115. We have 2 copies in web/
  116. We have 2 copies in web/ Bower install to /assets/vendor
  117. We have 2 copies in web/ Bower install to /assets/vendor Prevents source being public
  118. (S)CSS
  119. Normal SCSS workflow
  120. frontend.scss @import "assets/vendor/normalize-scss/normalize";
 
 $body-width: 60% !default;
 
 body
 {
 width: $body-width;
 margin: 0 auto;
 }

  121. gulpfile.js var scss = require('gulp-sass'); ! ! gulp.task('scss', function() {
 return gulp.src('assets/scss/*.scss')
 .pipe(scss())
 .pipe(gulp.dest('web/css'));
 });
  122. frontend.html.twig {% block stylesheets %}
 <link rel="stylesheet" href="{{ asset('/css/frontend.css') }}" />
 {% endblock stylesheets %}
  123. matt at Chloe in ~/Sites/workflow.dev on dev * 🍔 $ gulp scss [gulp] Using file /Users/matt/Sites/workflow.dev/gulpfile.js [gulp] Working directory changed to /Users/matt/Sites/workflow.dev [gulp] Running 'scss'... [gulp] Finished 'scss' in 11 ms
  124. Running commands manually gets old real fast
  125. Watching!
  126. gulpfile.js gulp.task('watch', function() {
 gulp.watch('assets/scss/**/*.scss', ['scss']);
 });
  127. Demo: Gulp Watch In Action
  128. Awesomesauce!
  129. Only scratching the surface!
  130. Gulp plugins
  131. TESTS T IN L CONCAT ONS plugins ATIGulp IFIC OT N IG W T SE I TIM BROW P O SERIF Y RENAME COP Y GI T
  132. Custom actions are easy
  133. Setting up a project can be tedious
  134. Can be taken much further!
  135. GAZILLIONS of tools available
  136. GAZILLIONS of tools available Don’t use all of them!
  137. Plan it!
  138. Plan it! **groan**
  139. Questions?
  140. Thanks! @mdavis1982

×