Using RequireJS with CakePHP

5,717 views

Published on

CakeFest 2013 presentation

Published in: Technology
2 Comments
7 Likes
Statistics
Notes
  • The CakePHP Html helper will accept an absolute path to the file. So, if your bower components folder is in the webroot, you can use: "/bower_components/requirejs/require.js"
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • When you write `echo $this->Html->script("require.js"...` in slide 16, are you using bower.json? How should I handle it if using bower and the require.js file is in bower_components?
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
5,717
On SlideShare
0
From Embeds
0
Number of Embeds
1,612
Actions
Shares
0
Downloads
51
Comments
2
Likes
7
Embeds 0
No embeds

No notes for slide

Using RequireJS with CakePHP

  1. 1. USING REQUIREJS WITH CAKEPHPStephen Young @young_steveo Sr. Software Engineer - Zumba Fitness
  2. 2. WHAT'S THE POINT?
  3. 3. The Javascript layer of a typical MVC app starts simple. ...like a jQuery Zen garden. $(function(){ /* animate the blog title */ $('.title').slideDown(); });
  4. 4. As the project matures, things get a little more tricky. $(function(){ /* animate the blog title */ $('.title').slideDown(350, function(){ $.get('/stats/count').done(function(data){ $('.statsCount') .html(data.count) .addClass('green'); }); }); }); Still maintainable... -ish
  5. 5. ...before long
  6. 6. /* mega_file.js */ $(function(){ if (window.isBlogPage && typeof window.App !== 'undefined') { var app = new App(); /* animate the blog title */ $('.title').slideDown(350, function(){ $.get('/stats/count').done(function(data){ $('.statsCount').html(data.count).addClass('green'); $.getScript('/js/superAwesomePlugin', function(){ $.get('/posts/someData').done(function(data){ if(data.posts){ doSomeCoolStuff(data.posts); } }); }); }); }); } else if (window.isCategory) { /* oh, god, please, stop! */
  7. 7. Don't forget the layout file...
  8. 8. <script src="js/box2d/common/b2Settings.js"></script> <script src="js/box2d/common/math/b2Vec2.js"></script> <script src="js/box2d/common/math/b2Mat22.js"></script> <script src="js/box2d/common/math/b2Math.js"></script> <script src="js/box2d/collision/b2AABB.js"></script> <script src="js/box2d/collision/b2Bound.js"></script> <script src="js/box2d/collision/b2BoundValues.js"></script> <script src="js/box2d/collision/b2Pair.js"></script> <script src="js/box2d/collision/b2PairCallback.js"></script> <script src="js/box2d/collision/b2BufferedPair.js"></script> <script src="js/box2d/collision/b2PairManager.js"></script> <script src="js/box2d/collision/b2BroadPhase.js"></script> <script src="js/box2d/collision/b2Collision.js"></script> <script src="js/box2d/collision/Features.js"></script> <script src="js/box2d/collision/b2ContactID.js"></script> <script src="js/box2d/collision/b2ContactPoint.js"></script> <script src="js/box2d/collision/b2Distance.js"></script>
  9. 9. THERE IS A BETTER WAY.
  10. 10. WHAT IS REQUIREJS? javascript module & file loader AMD (asynchronous module definition) optimization tool http://requirejs.org
  11. 11. WHAT'S SO GREAT ABOUT AMD? Encapsulation Dependency Management
  12. 12. AMD EXAMPLE Define your modules: /* define(id?, dependencies?, factory); */ define("SomeModule", ["dependency"], function(dependency) { var SomeModule = function(){}; SomeModule.prototype.init = function(){ dependency.doStuff(); }; /* etc. */ return SomeModule; });
  13. 13. AMD EXAMPLE Load your modules and use them: /* require(dependencies, callback); */ require(["ModuleA", "ModuleB"], function(ModuleA, ModuleB) { var module = new ModuleA(); ModuleA.init(); /* etc. */ });
  14. 14. REQUIRE() OR DEFINE() ? Use `define` to declare a module for use elsewhere. Use `require` to pre-load dependencies and/or do some stuff.
  15. 15. WHAT IS CAKEPHP? (just kidding)
  16. 16. HELLO WORLD /* app/Views/Layouts/someLayout.ctp */ echo $this->Html->script("require.js", [ "data-main" => "/js/bootstrap" ]); /* app/webroot/js/bootstrap.js */ requirejs.config({ paths : { jquery : 'js/vendor/jquery.min' } }); require(['js/libs/blogs']); /* app/webroot/js/libs/blogs.js */ require(['jquery'], function($){ $(function(){ /* etc. */ }); });
  17. 17. IT IS THAT SIMPLE. IS IT THAT SIMPLE? IT NEVER IS, IS IT? Even with RequireJS, things can get out of hand. As with many great tools, RequireJS gives you plenty of "rope."
  18. 18. TIPS Keep your modules focused; remember the single responsibility principle. Define a solid directory structure, and stick to it. (like your CakePHP /app directory) Think "automagic" and document your conventions. /js/README.md
  19. 19. GOING BEYOND "HELLO WORLD" i.e. What if your project contains LOTS of javascript?
  20. 20. DISCLAIMER This works for us, and we like it, but feel free to tweak it to meet your needs. image from gifsoup.com
  21. 21. IDENTIFY SECTIONS FOR YOUR PROJECT 1. Break the project down into sections, and create a module for each section (e.g. blog.js, shop.js, etc). 2. Identify any functionality that would be shared across multiple sections, and put them into common modules.
  22. 22. CHANGE THE LAYOUT BEFORE: /* (data-main does the heavy lifting) */ echo $this->Html->script("require.js", [ "data-main" => "/js/bootstrap" ]); AFTER: /* no more data-main */ echo $this->Html->script("require.js"); <script> require(['/js/bootstrap.js'], function(){ require(['modules/<?php echo $javascriptModule; ?>']); }); </script>
  23. 23. MODIFY THE APPCONTROLLER public function beforeRender(){ $this->set(array( 'javascriptModule' => $this->javascriptModule )); } public function beforeFilter() { /* just a nice convention, you could use a default file too */ if (!$this->javascriptModule){ $moduleName = Inflector::underscore($this->name); $this->javascriptModule = $moduleName; } }
  24. 24. NEW BOOTSTRAP.JS FILE requirejs.config({ paths : { jquery : 'js/vendor/jquery', someLib : 'js/libs/someLib', anotherLib : 'js/libs/anotherLib' }, shim : { anotherLib : ['jquery', 'someLib'] } });
  25. 25. OPTIMIZATION
  26. 26. R.JS RequireJS ships with a great minification/concatenation tool It runs in Node.js, Java with Rhino, or a browser It is configurable Bonus: it can minify CSS files for you too (but I'm not going to cover that today)
  27. 27. CONCATENATE DEPENDENCIES r.js will combine modules that are specified as dependencies in your module definitions
  28. 28. CONFIGURATION FILE { "modules": [ { "name" : "bootstrap", "include" : [ "underscore", "backbone", "jquery" ] }, { "name" : "blogs", exclude: ['bootstrap'] }, { "name" : "shops", exclude: ['bootstrap'] }, { "name" : "profiles", exclude: ['bootstrap'] }, /* etc. */
  29. 29. THAT'S IT! QUESTIONS?
  30. 30. EXAMPLE REPO github.com/young-steveo/require_cake

×