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.
Axa Assurance Maroc - Insurer Innovation Award 2024
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!
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
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
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
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
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
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
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>
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 %>
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
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)
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
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!
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.
80. Thank you!
Any questions?
Christophe Porteneuve
tdd@tddsworld.com
JSConf.eu 2009