Sprockets
 You’ve got tons of JavaScript.
Time to do something about it.


     Christophe Porteneuve
        JSConf.eu 20...
Hi, I’m Christophe

• I’m 32 and I live in Paris, France
• I use Rails all day at work
• I’m a Prototype Core member
• I w...
The problem
The problem

• JavaScript is the next big language…
The problem

• JavaScript is the next big language…
• It’s already getting big, codewise!
The problem

• JavaScript is the next big language…
• It’s already getting big, codewise!
• Many apps have countless JS fil...
The problem

• JavaScript is the next big language…
• It’s already getting big, codewise!
• Many apps have countless JS fil...
The problem

• JavaScript is the next big language…
• It’s already getting big, codewise!
• Many apps have countless JS fil...
The problem

• JavaScript is the next big language…
• It’s already getting big, codewise!
• Many apps have countless JS fil...
The solution
The solution

• You want to split your JS code in neat files
  and folders!
The solution

• You want to split your JS code in neat files
  and folders!
• You want some structure, dammit!
The solution

• You want to split your JS code in neat files
  and folders!
• You want some structure, dammit!
• But you wa...
The solution

• You want to split your JS code in neat files
  and folders!
• You want some structure, dammit!
• But you wa...
So many cool things…
So many cool things…

• Use require directives and load paths to
  structure your source
So many cool things…

• Use require directives and load paths to
  structure your source

• Preprocess constants!
So many cool things…

• Use require directives and load paths to
  structure your source

• Preprocess constants!
• Create...
Getting organized
Getting organized




        …
        //= require "lang"
        //= require "ajax"
        //= require "dom"
Getting organized



        //=   require   "dom/dom"
        //=   require   "dom/selector"
        //=   require   "dom...
Getting organized
        //=   require   "ajax/ajax"
        //=   require   "ajax/responders"
        //=   require   "a...
The load path
Sprockets has a load path, much like C’s or
Ruby’s
The load path
Sprockets has a load path, much like C’s or
Ruby’s

Using the load path:
         //= require <coolobj>
    ...
The load path
Sprockets has a load path, much like C’s or
Ruby’s

Using the load path:
          //= require <coolobj>
   ...
Constants FTW!

Put a constants.yml file somewhere in your
load path
• It’s a YAML file
• Heard of YAML, right?
• Super simp...
Constants for you
Constants for you
Constants for you


        PROTOTYPE_VERSION: 1.6.1_rc3
Constants for you


        PROTOTYPE_VERSION: 1.6.1_rc3




        var Prototype = {
          Version: '<%= PROTOTYPE_V...
Bundling assets


                         //= require "color"
                         //= provide "../assets"




    Be...
I can haz?

• It’s a Ruby gem
• You don’t need to know Ruby though
• You do need Ruby and Rubygems installed
I can haz?

    • It’s a Ruby gem
    • You don’t need to know Ruby though
    • You do need Ruby and Rubygems installed
$...
As a command-line tool…

$ sprocketize
Usage: sprocketize [options] filename [filename ...]
    -C, --directory=DIRECTORY ...
As a command-line tool…

$ sprocketize
Usage: sprocketize [options] filename [filename ...]
    -C, --directory=DIRECTORY ...
Within Ruby code…
Within Ruby code…

require 'rubygems'
require 'sprockets'

secretary = Sprockets::Secretary.new(
  :asset_root   => "publi...
As a CGI script…
         Say you have this tree
As a CGI script…
         Say you have this tree

         :load_path:
           - javascripts
           - vendor/sprock...
As a CGI script…
<VirtualHost *:80>
  ServerName www.sprocketsrule.com
  DocumentRoot "/var/webapps/sprocketsrule/public"
...
As a CGI script…
<VirtualHost *:80>
  ServerName www.sprocketsrule.com
  DocumentRoot "/var/webapps/sprocketsrule/public"
...
As a CGI script…
<VirtualHost *:80>




                                 T
  ServerName www.sprocketsrule.com




        ...
…or use Rails!
…or use Rails!

$ script/plugin install git://github.com/sstephenson/sprockets-rails.git
…or use Rails!

$ script/plugin install git://github.com/sstephenson/sprockets-rails.git




ActionController::Routing::Ro...
…or use Rails!

$ script/plugin install git://github.com/sstephenson/sprockets-rails.git




ActionController::Routing::Ro...
…or use Rails!



                                                  O M E
                         S
$ script/plugin insta...
Hey, like to squeeze?
Hey, like to squeeze?


  Just because it’s one big file
doesn’t mean it’s one small file

     (that didn’t come out right)
YUI Compressor
YUI Compressor

• Arguably the best source shrinker out
  there
YUI Compressor

• Arguably the best source shrinker out
  there
• 100% safe yet full of optimizations
YUI Compressor

• Arguably the best source shrinker out
  there
• 100% safe yet full of optimizations
• Better than JSMin,...
YUI Compressor

• Arguably the best source shrinker out
  there
• 100% safe yet full of optimizations
• Better than JSMin,...
YUI Compressor

• Arguably the best source shrinker out
  there
• 100% safe yet full of optimizations
• Better than JSMin,...
The gem wrapper
The gem wrapper
$ sudo gem install --remote yui-compressor
The gem wrapper
$ sudo gem install --remote yui-compressor




compressor = YUI::JavaScriptCompressor.new(:munge => true)
...
The gem wrapper
$ sudo gem install --remote yui-compressor




compressor = YUI::JavaScriptCompressor.new(:munge => true)
...
A match made in heaven
# config/sprockets.yml

:asset_root: public
:load_path:
  - app/javascripts
  - vendor/sprockets/*/...
So what’s left?
So what’s left?


• Tweak your assets HTTP server: GZip and
  cache the heck on the client side
So what’s left?


• Tweak your assets HTTP server: GZip and
  cache the heck on the client side
• If necessary, offload mai...
Apache config you’ll love
LoadModule deflate_module /usr/lib/apache2/modules/mod_deflate.so
LoadModule headers_module /usr/...
Numbers!

                                 No opti.                  All opti.

       Bytes                     292.520  ...
Numbers!

                                 No opti.                  All opti.

       Bytes                     292.520  ...
Numbers!

                                 No opti.                  All opti.

       Bytes                     292.520  ...
Numbers!

                                 No opti.                  All opti.

       Bytes                     292.520  ...
Numbers!

                                 No opti.                  All opti.

       Bytes                     292.520  ...
Numbers!


                                    V
                                 No opti.                  All opti.

   ...
Google Ajax Libraries API
Google Ajax Libraries API

• Google hosts most recent versions of
  Prototype, jQuery, script.aculo.us,
  MooTools, Dojo, ...
Google Ajax Libraries API

• Google hosts most recent versions of
  Prototype, jQuery, script.aculo.us,
  MooTools, Dojo, ...
Google Ajax Libraries API

• Google hosts most recent versions of
  Prototype, jQuery, script.aculo.us,
  MooTools, Dojo, ...
Thank you, Sam.
Thank you, Sam.
•   Sprockets, Sprockets-Rails and
    YUI::Compressor are open-
    source stuff by Sam
    Stephenson, c...
Thank you, Sam.
•   Sprockets, Sprockets-Rails and
    YUI::Compressor are open-
    source stuff by Sam
    Stephenson, c...
Thank you, Sam.
•   Sprockets, Sprockets-Rails and
    YUI::Compressor are open-
    source stuff by Sam
    Stephenson, c...
Thank you!
   Any questions?



 Christophe Porteneuve
  tdd@tddsworld.com
     JSConf.eu 2009
Sprockets
Upcoming SlideShare
Loading in …5
×

Sprockets

14,816 views

Published on

Sprockets is an easy solution to managing large JavaScript codebases by letting you structure it, bundle it with related assets, and consolidate it as one single file, with pre-baked command-line tooling, CGI front and Rails plugin. It's a framework-agnostic open-source solution that makes for great serving performance while helping you structure and manage your codebase better.

Published in: Technology
1 Comment
18 Likes
Statistics
Notes
  • its very useful for our project
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
14,816
On SlideShare
0
From Embeds
0
Number of Embeds
37
Actions
Shares
0
Downloads
101
Comments
1
Likes
18
Embeds 0
No embeds

No notes for slide
  • Sprockets

    1. Sprockets You’ve got tons of JavaScript. Time to do something about it. Christophe Porteneuve JSConf.eu 2009
    2. Hi, I’m Christophe • I’m 32 and I live in Paris, France • I use Rails all day at work • I’m a Prototype Core member • I wrote Prototype and script.aculo.us (“The Bungee Book”) • I’m glad to be here!
    3. The problem
    4. The problem • JavaScript is the next big language…
    5. The problem • JavaScript is the next big language… • It’s already getting big, codewise!
    6. The problem • JavaScript is the next big language… • It’s already getting big, codewise! • Many apps have countless JS files
    7. The problem • JavaScript is the next big language… • It’s already getting big, codewise! • Many apps have countless JS files • Loading → lots of requests → latence
    8. The problem • JavaScript is the next big language… • It’s already getting big, codewise! • Many apps have countless JS files • Loading → lots of requests → latence • Or you could maintain one big file…
    9. The problem • JavaScript is the next big language… • It’s already getting big, codewise! • Many apps have countless JS files • Loading → lots of requests → latence • Or you could maintain one big file… • …which sucks
    10. The solution
    11. The solution • You want to split your JS code in neat files and folders!
    12. The solution • You want to split your JS code in neat files and folders! • You want some structure, dammit!
    13. The solution • You want to split your JS code in neat files and folders! • You want some structure, dammit! • But you want to serve just one file!
    14. The solution • You want to split your JS code in neat files and folders! • You want some structure, dammit! • But you want to serve just one file! • Enter Sprockets
    15. So many cool things…
    16. So many cool things… • Use require directives and load paths to structure your source
    17. So many cool things… • Use require directives and load paths to structure your source • Preprocess constants!
    18. So many cool things… • Use require directives and load paths to structure your source • Preprocess constants! • Create “JS plugins,” complete with related CSS/image assets, bundle them and distribute them easily
    19. Getting organized
    20. Getting organized … //= require "lang" //= require "ajax" //= require "dom"
    21. Getting organized //= require "dom/dom" //= require "dom/selector" //= require "dom/form" //= require "dom/event" Element.addMethods(); … //= require "lang" //= require "ajax" //= require "dom"
    22. Getting organized //= require "ajax/ajax" //= require "ajax/responders" //= require "ajax/base" //= require "ajax/request" //= require "ajax/response" //= require "ajax/updater" //= require "ajax/periodical_updater" //= require "dom/dom" //= require "dom/selector" //= require "dom/form" //= require "dom/event" Element.addMethods(); … //= require "lang" //= require "ajax" //= require "dom"
    23. The load path Sprockets has a load path, much like C’s or Ruby’s
    24. The load path Sprockets has a load path, much like C’s or Ruby’s Using the load path: //= require <coolobj> //= require <coollib/coolobj>
    25. The load path Sprockets has a load path, much like C’s or Ruby’s Using the load path: //= require <coolobj> //= require <coollib/coolobj> Using paths relative to the current file: //= require "coolobj" //= require "subdir/coolobj"
    26. Constants FTW! Put a constants.yml file somewhere in your load path • It’s a YAML file • Heard of YAML, right? • Super simple yet powerful
    27. Constants for you
    28. Constants for you
    29. Constants for you PROTOTYPE_VERSION: 1.6.1_rc3
    30. Constants for you PROTOTYPE_VERSION: 1.6.1_rc3 var Prototype = { Version: '<%= PROTOTYPE_VERSION %>', Browser: (function(){ …
    31. Bundling assets //= require "color" //= provide "../assets" Because you require <color_picker>, Sprockets can copy the assets to your asset root (somewhere inside your document root)
    32. I can haz? • It’s a Ruby gem • You don’t need to know Ruby though • You do need Ruby and Rubygems installed
    33. I can haz? • It’s a Ruby gem • You don’t need to know Ruby though • You do need Ruby and Rubygems installed $ sudo gem install --remote sprockets
    34. As a command-line tool… $ sprocketize Usage: sprocketize [options] filename [filename ...] -C, --directory=DIRECTORY Change to DIRECTORY before doing anything -I, --include-dir=DIRECTORY Adds the directory to the Sprockets load path -a, --asset-root=DIRECTORY Copy provided assets into DIRECTORY … -h, --help Shows this help message -v, --version Shows version
    35. As a command-line tool… $ sprocketize Usage: sprocketize [options] filename [filename ...] -C, --directory=DIRECTORY Change to DIRECTORY before doing anything -I, --include-dir=DIRECTORY Adds the directory to the Sprockets load path -a, --asset-root=DIRECTORY Copy provided assets into DIRECTORY … -h, --help Shows this help message -v, --version Shows version $ sprocketize -I src -a dist src/application.js > dist/javascripts/application.js
    36. Within Ruby code…
    37. Within Ruby code… require 'rubygems' require 'sprockets' secretary = Sprockets::Secretary.new( :asset_root => "public", :load_path => ["vendor/sprockets/*/src", "vendor/plugins/*/javascripts"], :source_files => ["app/javascripts/application.js", "app/javascripts/**/*.js"] ) concatenation = secretary.concatenation concatenation.save_to("public/sprockets.js") secretary.install_assets
    38. As a CGI script… Say you have this tree
    39. As a CGI script… Say you have this tree :load_path: - javascripts - vendor/sprockets/*/src :source_files: - javascripts/mysite.js - javascripts/*.js :output_file: public/sprockets.js So you write this sprockets.yml
    40. As a CGI script… <VirtualHost *:80> ServerName www.sprocketsrule.com DocumentRoot "/var/webapps/sprocketsrule/public" <Directory "/var/webapps/sprocketsrule/public"> Options +ExecCGI +FollowSymLinks AddHandler cgi-script .cgi RewriteEngine on RewriteCond /sprockets.js !-f RewriteRule ^sprockets.js /nph-sprockets.cgi [P,L] SetEnv sprockets_generate_output_file true </Directory> </VirtualHost> <script type="text/javascript" src="/sprockets.js"></script>
    41. As a CGI script… <VirtualHost *:80> ServerName www.sprocketsrule.com DocumentRoot "/var/webapps/sprocketsrule/public" <Directory "/var/webapps/sprocketsrule/public"> Options +ExecCGI +FollowSymLinks Provided in the ext/ AddHandler cgi-script .cgi directory of Sprockets RewriteEngine on RewriteCond /sprockets.js !-f RewriteRule ^sprockets.js /nph-sprockets.cgi [P,L] SetEnv sprockets_generate_output_file true </Directory> </VirtualHost> <script type="text/javascript" src="/sprockets.js"></script>
    42. As a CGI script… <VirtualHost *:80> T ServerName www.sprocketsrule.com A DocumentRoot "/var/webapps/sprocketsrule/public" N E <Directory "/var/webapps/sprocketsrule/public"> Options +ExecCGI +FollowSymLinks Provided in the ext/ AddHandler cgi-script .cgi directory of Sprockets RewriteEngine on RewriteCond /sprockets.js !-f RewriteRule ^sprockets.js /nph-sprockets.cgi [P,L] SetEnv sprockets_generate_output_file true </Directory> </VirtualHost> <script type="text/javascript" src="/sprockets.js"></script>
    43. …or use Rails!
    44. …or use Rails! $ script/plugin install git://github.com/sstephenson/sprockets-rails.git
    45. …or use Rails! $ script/plugin install git://github.com/sstephenson/sprockets-rails.git ActionController::Routing::Routes.draw do |map| SprocketsApplication.routes(map) # ... end
    46. …or use Rails! $ script/plugin install git://github.com/sstephenson/sprockets-rails.git ActionController::Routing::Routes.draw do |map| SprocketsApplication.routes(map) # ... end <%= sprockets_include_tag %>
    47. …or use Rails! O M E S $ script/plugin install git://github.com/sstephenson/sprockets-rails.git A W E ActionController::Routing::Routes.draw do |map| SprocketsApplication.routes(map) # ... end <%= sprockets_include_tag %>
    48. Hey, like to squeeze?
    49. Hey, like to squeeze? Just because it’s one big file doesn’t mean it’s one small file (that didn’t come out right)
    50. YUI Compressor
    51. YUI Compressor • Arguably the best source shrinker out there
    52. YUI Compressor • Arguably the best source shrinker out there • 100% safe yet full of optimizations
    53. YUI Compressor • Arguably the best source shrinker out there • 100% safe yet full of optimizations • Better than JSMin, ShrinkSafe, Packer…
    54. YUI Compressor • Arguably the best source shrinker out there • 100% safe yet full of optimizations • Better than JSMin, ShrinkSafe, Packer… • Does not obfuscate (which is good)
    55. YUI Compressor • Arguably the best source shrinker out there • 100% safe yet full of optimizations • Better than JSMin, ShrinkSafe, Packer… • Does not obfuscate (which is good) • Distributed as a JAR file
    56. The gem wrapper
    57. The gem wrapper $ sudo gem install --remote yui-compressor
    58. The gem wrapper $ sudo gem install --remote yui-compressor compressor = YUI::JavaScriptCompressor.new(:munge => true) compressor.compress('(function () { var foo = {}; foo["bar"] = "baz"; })()') # => '(function(){var a={};a.bar="baz"})();'
    59. The gem wrapper $ sudo gem install --remote yui-compressor compressor = YUI::JavaScriptCompressor.new(:munge => true) compressor.compress('(function () { var foo = {}; foo["bar"] = "baz"; })()') # => '(function(){var a={};a.bar="baz"})();' YUI::JavaScriptCompressor.new( :java => "/usr/bin/java", :jar_file => "/path/to/my/yuicompressor-2.4.2.jar" ) Full compressor support: CSS too, options aplenty…
    60. A match made in heaven # config/sprockets.yml :asset_root: public :load_path: - app/javascripts - vendor/sprockets/*/src - vendor/plugins/*/javascripts :source_files: - app/javascripts/application.js - app/javascripts/**/*.js :compress: :munge: true Warning: not in master gems yet. See my forks. (incidentally, in production use at http://letsfreckle.com)
    61. So what’s left?
    62. So what’s left? • Tweak your assets HTTP server: GZip and cache the heck on the client side
    63. So what’s left? • Tweak your assets HTTP server: GZip and cache the heck on the client side • If necessary, offload mainstream libs serving to Google
    64. Apache config you’ll love LoadModule deflate_module /usr/lib/apache2/modules/mod_deflate.so LoadModule headers_module /usr/lib/apache2/modules/mod_headers.so LoadModule expires_module /usr/lib/apache2/modules/mod_expires.so AddOutputFilterByType DEFLATE text/html text/plain text/xml application/xml ↪application/xhtml+xml text/javascript text/css application/x-javascript ExpiresActive On ExpiresByType image/gif "access plus 5 years" ExpiresByType image/png "access plus 5 years" ExpiresByType image/jpeg "access plus 5 years" ExpiresByType text/javascript "access plus 5 years" ExpiresByType application/x-javascript "access plus 5 years" ExpiresByType text/css "access plus 5 years" Header unset ETag FileETag None Header add Cache-Control "public" http://javascriptrocks.com/performance/
    65. Numbers! No opti. All opti. Bytes 292.520 30.919 HTTP requests 3 / 38* 1 Load time (unprimed) 1900+456ms 400+43ms Load time (primed) 1900+76ms 1+41ms * monolithic vendor scripts / structured source
    66. Numbers! No opti. All opti. Bytes 292.520 30.919 HTTP requests 3 / 38* 1 Load time (unprimed) 1900+456ms 400+43ms Load time (primed) 1900+76ms 1+41ms * monolithic vendor scripts / structured source
    67. Numbers! No opti. All opti. Bytes 292.520 30.919 HTTP requests 3 / 38* 1 Load time (unprimed) 1900+456ms 400+43ms Load time (primed) 1900+76ms 1+41ms * monolithic vendor scripts / structured source
    68. Numbers! No opti. All opti. Bytes 292.520 30.919 HTTP requests 3 / 38* 1 Load time (unprimed) 1900+456ms 400+43ms Load time (primed) 1900+76ms 1+41ms * monolithic vendor scripts / structured source
    69. Numbers! No opti. All opti. Bytes 292.520 30.919 HTTP requests 3 / 38* 1 Load time (unprimed) 1900+456ms 400+43ms Load time (primed) 1900+76ms 1+41ms * monolithic vendor scripts / structured source
    70. Numbers! V No opti. All opti. Bytes Y M HTTP requests Load time (unprimed) M 292.520 3 / 38* 1900+456ms 30.919 400+43ms 1 Load time (primed) 1900+76ms 1+41ms * monolithic vendor scripts / structured source
    71. Google Ajax Libraries API
    72. Google Ajax Libraries API • Google hosts most recent versions of Prototype, jQuery, script.aculo.us, MooTools, Dojo, Ext Core,YUI…
    73. Google Ajax Libraries API • Google hosts most recent versions of Prototype, jQuery, script.aculo.us, MooTools, Dojo, Ext Core,YUI… • Top-notch serving (e.g. cache-related headers + GZipping) + CDN
    74. Google Ajax Libraries API • Google hosts most recent versions of Prototype, jQuery, script.aculo.us, MooTools, Dojo, Ext Core,YUI… • Top-notch serving (e.g. cache-related headers + GZipping) + CDN • Bonus: if another site loaded it already, your user doesn’t have to load it for your site!
    75. Thank you, Sam.
    76. Thank you, Sam. • Sprockets, Sprockets-Rails and YUI::Compressor are open- source stuff by Sam Stephenson, creator of Prototype.
    77. Thank you, Sam. • Sprockets, Sprockets-Rails and YUI::Compressor are open- source stuff by Sam Stephenson, creator of Prototype. • http://github.com/sstephenson
    78. Thank you, Sam. • Sprockets, Sprockets-Rails and YUI::Compressor are open- source stuff by Sam Stephenson, creator of Prototype. • http://github.com/sstephenson • http://github.com/tdd
    79. Thank you! Any questions? Christophe Porteneuve tdd@tddsworld.com JSConf.eu 2009

    ×