Closure: The Definitive Guide [JAVASCRIPT][Closure. Guide]
%5BJAVASCRIPT%5D%5BClosure.%20The%20Definitive%20Guide%5D
%5BJAVASCRIPT%5D%5BClosure.%20The%20Definitive%20Guide%5D
%5BJAVASCRIPT%5D%5BClosure.%20The%20Definitive%20Guide%5D
Closure_The_Definitive_Guide
%5BClosure%20The%20Definitive%20Guide%20by%20Michael%20Bolin%20-%202010%5D
User Manual:
Open the PDF directly: View PDF
.
Page Count: 594
| Download | |
| Open PDF In Browser | View PDF |
www.it-ebooks.info
www.it-ebooks.info
Closure: The Definitive Guide
Michael Bolin
Beijing • Cambridge • Farnham • Köln • Sebastopol • Tokyo
www.it-ebooks.info
Closure: The Definitive Guide
by Michael Bolin
Copyright © 2010 Michael Bolin. All rights reserved.
Printed in the United States of America.
Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472.
O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions
are also available for most titles (http://my.safaribooksonline.com). For more information, contact our
corporate/institutional sales department: (800) 998-9938 or corporate@oreilly.com.
Editors: Simon St.Laurent and Julie Steele
Production Editor: Kristen Borg
Copyeditor: Nancy Kotary
Proofreader: Kristen Borg
Indexer: Ellen Troutman Zaig
Cover Designer: Karen Montgomery
Interior Designer: David Futato
Illustrator: Robert Romano
Printing History:
September 2010:
First Edition.
Nutshell Handbook, the Nutshell Handbook logo, and the O’Reilly logo are registered trademarks of
O’Reilly Media, Inc. Closure: The Definitive Guide, the image of a golden plover, and related trade dress
are trademarks of O’Reilly Media, Inc.
Many of the designations used by manufacturers and sellers to distinguish their products are claimed as
trademarks. Where those designations appear in this book, and O’Reilly Media, Inc., was aware of a
trademark claim, the designations have been printed in caps or initial caps.
While every precaution has been taken in the preparation of this book, the publisher and author assume
no responsibility for errors or omissions, or for damages resulting from the use of the information contained herein.
ISBN: 978-1-449-38187-5
[M]
1283888246
www.it-ebooks.info
Table of Contents
Foreword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii
My Experiences with Closure
Audience
ECMAScript Versus JavaScript
Using This Book
Acknowledgments
xviii
xx
xx
xxi
xxiv
1. Introduction to Closure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Tools Overview
Closure Library
Closure Templates
Closure Compiler
Closure Testing Framework
Closure Inspector
Closure Design Goals and Principles
Reducing Compiled Code Size Is Paramount
All Source Code Is Compiled Together
Managing Memory Matters
Make It Possible to Catch Errors at Compile Time
Code Must Work Without Compilation
Code Must Be Browser-Agnostic
Built-in Types Should Not Be Modified
Code Must Work Across Frames
Tools Should Be Independent
Downloading and Installing the Tools
Closure Library and Closure Testing Framework
Closure Templates
Closure Compiler
Closure Inspector
2
2
3
3
4
4
5
5
6
6
7
7
7
8
8
8
9
10
11
12
12
iii
www.it-ebooks.info
Example: Hello World
Closure Library
Closure Templates
Closure Compiler
Closure Testing Framework
Closure Inspector
12
13
14
17
19
21
2. Annotations for Closure JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
JSDoc Tags
Type Expressions
Simple Types and Union Types
Function Types
Record Types
Special @param Types
Subtypes and Type Conversion
The ALL Type
JSDoc Tags That Do Not Deal with Types
Constants
Deprecated Members
License and Copyright Information
Is All of This Really Necessary?
25
29
29
31
32
33
38
41
41
42
43
43
43
3. Closure Library Primitives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Dependency Management
calcdeps.py
goog.global
COMPILED
goog.provide(namespace)
goog.require(namespace)
goog.addDependency(relativePath, provides, requires)
Function Currying
goog.partial(functionToCall, ...)
goog.bind(functionToCall, selfObject, ...)
Exports
goog.getObjectByName(name, opt_object)
goog.exportProperty(object, propertyName, value)
goog.exportSymbol(publicPath, object, opt_objectToExportTo)
Type Assertions
goog.typeOf(value)
goog.isDef(value)
goog.isNull(value)
goog.isDefAndNotNull(value)
goog.isArray(obj)
iv | Table of Contents
www.it-ebooks.info
45
45
47
48
48
50
51
54
54
57
58
58
58
60
61
62
62
63
63
63
goog.isArrayLike(obj)
goog.isDateLike(obj)
goog.isString(obj), goog.isBoolean(obj), goog.isNumber(obj)
goog.isFunction(obj)
goog.isObject(obj)
Unique Identifiers
goog.getUid(obj)
goog.removeUid(obj)
Internationalization (i18n)
goog.LOCALE
goog.getMsg(str, opt_values)
Object Orientation
goog.inherits(childConstructorFunction, parentConstructorFunction)
goog.base(self, opt_methodName, var_args)
goog.nullFunction
goog.abstractMethod
goog.addSingletonGetter(constructorFunction)
Additional Utilities
goog.DEBUG
goog.now()
goog.globalEval(script)
goog.getCssName(className, opt_modifier),
goog.setCssNameMapping(mapping)
64
64
64
65
65
65
65
66
67
67
68
68
68
69
69
70
70
70
70
71
71
71
4. Common Utilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
goog.string
goog.string.htmlEscape(str, opt_isLikelyToContainHtmlChars)
goog.string.regExpEscape(str)
goog.string.whitespaceEscape(str, opt_xml)
goog.string.compareVersions(version1, version2)
goog.string.hashCode(str)
goog.array
goog.array.forEach(arr, func, opt_obj)
Using Iterative goog.array Functions in a Method
goog.object
goog.object.get(obj, key, opt_value)
goog.setIfUndefined(obj, key, value)
goog.object.transpose(obj)
goog.json
goog.json.parse(str)
goog.json.unsafeParse(str)
goog.json.serialize(obj)
goog.dom
75
75
77
78
78
79
79
80
81
82
82
83
83
84
85
85
86
86
Table of Contents | v
www.it-ebooks.info
goog.dom.getElement(idOrElement)
goog.dom.getElementsByTagNameAndClass(nodeName, className,
elementToLookIn)
goog.dom.getAncestorByTagNameAndClass(element, tag,
className)
goog.dom.createDom(nodeName, attributes, var_args)
goog.dom.htmlToDocumentFragment(htmlString)
goog.dom.ASSUME_QUIRKS_MODE and
goog.dom.ASSUME_STANDARDS_MODE
goog.dom.classes
goog.dom.classes.get(element)
goog.dom.classes.has(element, className)
goog.dom.classes.add(element, var_args) and
goog.dom.classes.remove(element, var_args)
goog.dom.classes.toggle(element, className)
goog.dom.classes.swap(element, fromClass, toClass)
goog.dom.classes.enable(element, className, enabled)
goog.userAgent
Rendering Engine Constants
Platform Constants
goog.userAgent.isVersion(version)
goog.userAgent.product
goog.net.cookies
goog.net.cookies.isEnabled()
goog.net.cookies.set(name, value, opt_maxAge, opt_path,
opt_domain)
goog.net.cookies.get(name, opt_default)
goog.net.cookies.remove(name, opt_path, opt_domain)
goog.style
goog.style.getPageOffset(element)
goog.style.getSize(element)
goog.style.getBounds(element)
goog.style.setOpacity(element, opacity)
goog.style.setPreWrap(element)
goog.style.setInlineBlock(element)
goog.style.setUnselectable(element, unselectable, opt_noRecurse)
goog.style.installStyles(stylesString, opt_node)
goog.style.scrollIntoContainerView(element, container, opt_center)
goog.functions
goog.functions.TRUE
goog.functions.constant(value)
goog.functions.error(message)
vi | Table of Contents
www.it-ebooks.info
86
87
89
91
92
93
95
95
95
96
96
97
98
98
99
101
102
102
104
104
104
105
105
105
105
106
106
106
106
106
107
107
108
108
108
108
109
5. Classes and Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
Example of a Class in Closure
Closure JavaScript Example
Equivalent Example in Java
Static Members
Singleton Pattern
Example of a Subclass in Closure
Closure JavaScript Example
Equivalent Example in Java
Declaring Fields in Subclasses
@override and @inheritDoc
Using goog.base() to Simplify Calls to the Superclass
Abstract Methods
Example of an Interface in Closure
Multiple Inheritance
Enums
goog.Disposable
Overriding disposeInternal()
112
112
115
116
118
119
119
123
124
125
126
127
128
130
132
132
133
6. Event Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
A Brief History of Browser Event Models
Closure Provides a Consistent DOM Level 2 Events API Across Browsers
goog.events.listen()
goog.events.EventTarget
goog.events.Event
goog.events.EventHandler
Handling Keyboard Events
137
138
138
141
146
148
152
7. Client-Server Communication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
Server Requests
goog.net.XmlHttp
goog.net.XhrIo
goog.net.XhrManager
goog.Uri and goog.uri.utils
Resource Loading and Monitoring
goog.net.BulkLoader
goog.net.ImageLoader
goog.net.IframeLoadMonitor
goog.net.MultiIframeLoadMonitor
goog.net.NetworkTester
Cross-Domain Communication
goog.net.jsonp
goog.net.xpc
155
155
156
161
163
165
165
167
168
169
169
170
171
173
Table of Contents | vii
www.it-ebooks.info
Uploading Files
Comet
176
178
8. User Interface Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
Design Behind the goog.ui Package
goog.ui.Component
Basic Life Cycle
Components with Children
Events
States
Errors
goog.ui.Control
Handling User Input
Managing State
Delegating to the Renderer
Example: Responding to a Mouseover Event
goog.ui.Container
Using Common Components
Pulling in CSS
goog-inline-block
Example of Rendering a Component: goog.ui.ComboBox
Example of Decorating a Control: goog.ui.Button and
goog.ui.CustomButton
Creating Custom Components
example.Checklist and example.ChecklistItem
example.ui.ChecklistItem and example.ui.ChecklistItemRenderer
example.ui.Label
example.ui.Checklist and example.ui.ChecklistRenderer
Rendering Example
Decorating Example
Conclusions
182
184
184
190
194
195
196
197
198
199
201
206
206
210
212
215
218
220
227
228
229
232
233
236
237
239
9. Rich Text Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
Design Behind the goog.editor Package
Trade-offs: Control, Code Size, and Performance
goog.editor.BrowserFeature
Creating an Editable Region
goog.editor.Field
goog.editor.SeamlessField
Extending the Editor: The Plugin System
Registering Plugins
Interacting with Plugins
goog.editor.Plugin
viii | Table of Contents
www.it-ebooks.info
241
242
243
243
244
251
253
253
254
256
Built-in Plugins
Custom Plugins
UI Components
Dialogs
Toolbar
Selections
goog.dom.Range
goog.dom.AbstractRange
goog.editor.range
260
265
270
270
274
278
279
281
285
10. Debugging and Logging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289
Creating Logging Information
goog.debug.LogRecord
goog.debug.Logger.Level
goog.debug.Logger
Displaying Logging Information
goog.debug.Console
goog.debug.DivConsole
goog.debug.DebugWindow
goog.debug.FancyWindow
Profiling JavaScript Code
Reporting JavaScript Errors
290
290
291
292
297
298
298
298
299
300
302
11. Closure Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303
Limitations of Existing Template Systems
Server-Side Templates
Client-Side Templates
Introducing Closure Templates
Creating a Template
Declaring Templates with {namespace} and {template}
Commenting Templates
Overriding Line Joining with {sp} and {nil}
Writing Raw Text with {literal}
Building Soy Expressions
Displaying Data with {print}
Managing Control Flow with {if}, {elseif}, and {else}
Advanced Conditional Handling with {switch}, {case}, and {default}
Looping over Lists with {foreach}
Leveraging Other Templates with {call} and {param}
Identifying CSS Classes with {css}
Internationalization (i18n)
Compiling Templates
Compiling a Template for JavaScript
303
303
304
305
306
309
310
310
312
312
315
316
317
318
319
321
321
322
323
Table of Contents | ix
www.it-ebooks.info
Compiling a Template for Java
Defining a Custom Function
326
328
12. Using the Compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333
Benefits of Using the Compiler
Reducing Code Size
Catching Errors at Compile Time
Protecting Code Through Obfuscation
How the Compiler Works
Compiler Options
Compilation Levels
Formatting Options
Warning Levels
Running the Compiler
Closure Compiler Service UI
Closure Compiler Service API
Closure Compiler Application
Programmatic Java API
Integrating the Compiler into a Build Process
Partitioning Compiled Code into Modules
Introducing the Application Code
Introducing the Module Loading Code
Partitioning the Input
Loading the Modules
Refining the Partitioning
334
334
335
336
337
338
338
343
344
346
346
349
351
354
357
363
365
368
370
373
376
13. Advanced Compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379
What Happens During Compilation
Externs and Exports
Property Flattening
Property Renaming
Preparing Code for the Compiler
Input Language
Programmatic Evaluation of Strings of JavaScript Code
Never Use the with Keyword
Checks Provided by the Compiler
Type Checking
Access Controls
Optimizations Performed by the Compiler
Processing Closure Primitives
Devirtualizing Prototype Methods
Inlining
x | Table of Contents
www.it-ebooks.info
380
383
400
404
406
406
407
408
408
408
414
417
417
418
421
14. Inside the Compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427
Tour of the Codebase
Getting and Building the Compiler
Compiler.java
CompilerPass.java
JSSourceFile.java
CompilerOptions.java
CompilationLevel.java
WarningLevel.java
PassFactory.java
DefaultPassConfig.java
CommandLineRunner.java
com.google.common.collect
Hidden Options
Checks
Renaming
Optimizations
Output
Example: Extending CommandLineRunner
Example: Visualizing the AST Using DOT
What Is DOT?
Converting the AST to DOT
Hooking into MyCommandLineRunner
Example: Creating a Compiler Check
Example: Creating a Compiler Optimization
427
427
431
432
433
433
433
434
434
434
435
435
436
436
440
442
448
450
452
453
453
455
456
460
15. Testing Framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 465
Creating Your First Test
Example: Testing an Email Validator
Assertions
Life Cycle of a Test Case
Differences from JsUnit
Mock Objects
goog.testing.PropertyReplacer
goog.testing.PseudoRandom
goog.testing.MockClock
Testing to Ensure That an Error Is Thrown
Testing Input Events
Testing Asynchronous Behavior
goog.testing.ContinuationTestCase
goog.testing.AsyncTestCase
Running a Single Test
Running Multiple Tests
466
466
471
474
475
476
476
478
479
482
483
483
483
487
489
490
Table of Contents | xi
www.it-ebooks.info
Automating Tests
System Testing
492
494
16. Debugging Compiled JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 497
Verify That the Error Occurs in Uncompiled Mode
Format Compiled Code for Debugging
Compile with --debug=true
Use the Closure Inspector
497
498
500
501
A. Inheritance Patterns in JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 505
Example of the Functional Pattern
Example of the Pseudoclassical Pattern
Drawbacks to the Functional Pattern
Potential Objections to the Pseudoclassical Pattern
Won’t Horrible Things Happen if I Forget the New Operator?
Didn’t Crockford Also Say I Wouldn’t Have Access to Super Methods?
Won’t All of the Object’s Properties Be Public?
Won’t Declaring SomeClass.prototype for Each Method and Field of
SomeClass Waste Bytes?
I Don’t Need Static Checks—My Tests Will Catch All of My Errors!
505
506
508
511
511
512
512
512
513
B. Frequently Misunderstood JavaScript Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . 515
JavaScript Objects Are Associative Arrays Whose Keys Are Always Strings
There Are Several Ways to Look Up a Value in an Object
Single-Quoted Strings and Double-Quoted Strings Are Equivalent
There Are Several Ways to Define an Object Literal
The prototype Property Is Not the Prototype You Are Looking For
The Syntax for Defining a Function Is Significant
What this Refers to When a Function Is Called
The var Keyword Is Significant
Block Scope Is Meaningless
515
516
516
517
520
523
524
526
527
C. plovr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 531
Getting Started with plovr
Config Files
Build Command
Serve Command
Displaying Compiler Errors
Auditing Compiled Code Size
Generating Externs from Exports
Generating a Source Map
532
532
534
535
537
538
539
540
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 541
xii | Table of Contents
www.it-ebooks.info
Foreword
I was sitting on a balcony on the west side of Manhattan, sipping on a warm glass of
scotch with a few others. Michael Bolin joined us. Michael wrote this book. At the time,
Michael was working on Google Tasks. I was the tech lead on our JavaScript optimizer,
later named Closure Compiler. Michael didn’t join us to talk about JavaScript optimization though. He didn’t want to talk scotch either, to his detriment. He wanted to talk
JavaScript-driven text editing, and thus he wanted to talk to Julie.
You will receive a proper introduction to Julie in Chapter 9, but for now, just know
that Julie is our expert on how text editors are implemented in each web browser.
Michael found that, when managing a task list in a web browser, you want a few features
built into your plain text editor. You want to make words bold for emphasis. You want
a keyboard shortcut to move your cursor to the next task item. He didn’t want to have
to write a whole editor. He just wanted a few tweaks on top of what the browser provides, to make the experience smoother for the user. How would you implement this?
Julie explained that there are many, many choices for such a thing. “Should you use a
textarea?” “Should you use a contentEditable region?” “Should you rely on the
browser’s built-in rich text functions?” “Should you implement the ‘bold’ function in
JavaScript?” “How do you make sure the cursor ends up on the right line, given that
browsers each implement cursor selection differently?” “Should you put all the text
editing in an iframe to isolate it from the rest of the page?Ӡ
“Is there code you can reuse for this?”
You don’t really want to implement all these things from scratch. A lot of them will
need to call into esoteric browser APIs in complex ways. Many of those APIs are buggy,
poorly documented, or simply do not perform very well. For some of those APIs, it’s
easier to read the browser source code than to find reasonable documentation.
† Fun fact: as the number of JavaScript developers in a room increases, the probability that someone will suggest
“iframes” as the solution to your problem asymptotically approaches 1.
xiii
www.it-ebooks.info
You’ll find answers to many of those specific questions throughout this book. But I
think the question that the book is most interested in (and rightly so) is about how to
make it easy to reuse code for Ajax apps. It spins off into a few other equally substantial
questions.
How do you share JavaScript code? How do you organize large amounts of common
JavaScript, often built for highly specialized tasks? How do you weigh one team’s need
for boatloads of new features and customizations against another team’s need to keep
the size of the JavaScript they’re sending to the user small?
The Closure Tools were designed to solve many of these problems. Maybe that’s understating the point. These problems are at the very core of their design. Many of the
tools were started by our friends on Gmail. Gmail began as a relatively modest JavaScript app. Then they added more and more features, and watched it grow beyond any
hope of control or maintainability. Frederick P. Brooks, Jr., famously described largesystem programming as “a tar pit, and many great and powerful beasts have thrashed
violently in it.” In a language like JavaScript, a highly dynamic environment where
almost everything can be mutated and there’s no standard way to specify contracts
(type checking or otherwise), the tar is fast and can suck down even a small group of
developers.
The Closure Tools developers tried to bring “closure” to this mess. (I agree the pun is
terrible. It is not mine.) They followed strict idioms for namespacing code and defining
classes. They adopted ECMAScript 4’s type language for specifying contracts. The
compiler forced the developer to declare their variables, and emitted warnings for other
frowned-upon idioms. The Closure Tools, in short, tried to add some structure to the
language. Many engineering teams at Google found this structure useful, and built their
products on top of it.
A long time passed. The Closure Tools remained proprietary for years. This wasn’t
meant to be. Both the compiler and the libraries were always designed to be open source
projects. But more importantly, they were designed for building Google apps first, and
to be open source projects second. So releasing them publicly took a back seat to other
things.
Have you ever tried to publicly open up the code of a proprietary project? Several engineers had tried to release Closure Compiler. They had all given up. It is surprisingly
difficult. There are two major parts. First, you have to release the code: port it to a
public build system like Apache Ant, remove all of its nonopen dependencies, and
rewrite any dependencies that you can’t remove. Second, you have to write documentation: loads of documentation.
You can imagine how skeptical I was when Michael first came by my desk to talk about
making Closure Compiler an open source project. This was early 2009. By this point,
“publicly releasing Closure Compiler” was the sort of daunting chore that you’ve procrastinated forever and a half. We’d work on it for a month, realize that we seemed no
xiv | Foreword
www.it-ebooks.info
closer to completion, and then procrastinate some more. It was sort of like reading
Infinite Jest. Or cleaning my apartment.
Obviously, Michael succeeded in his effort to release the compiler. I think it was some
combination of being persistent, asking a lot of good questions, and commissioning a
lot of good help from smart people. Of course, Michael is a web app developer first,
and a open source engineer second, so he also helped design and write the Closure
Compiler web frontend. By pure serendipity, Closure Library, Closure Templates, and
Closure Debugger were all released along with it.
But making the code available was just the first part of opening up the project. This
book marks a major milestone in the second: documenting it all. There’s surprisingly
comprehensive knowledge in this book, more than any one engineer on the project
knows. I’ve already started telling our interns to stop bothering me, and instead just
read this Closure book’s sections on appending DocumentFragments, or on using
XHRs, or on the binding of the “this” keyword. You can read this book like an API
reference manual for the Closure Tools. You can even read it more generally as an API
reference for web application development.
If you want to get the most out of it, pay attention to Michael’s explanations of how
and why these tools came to be. Michael explains how they can help you to manage
complexity. There were many missteps and false starts. Along the way, Michael will
drop hints about pitfalls to watch out for, mistakes that we made and how you can
avoid them too. You’ll even learn how to build your own tools and compiler plugins
to help tame your own large codebase.
Just remember that this is first and foremost a practical guide to how to build your own
rich web apps. So quit reading this foreword and go to it!
—Nick Santos
Former Closure Compiler Tech Lead
Foreword | xv
www.it-ebooks.info
www.it-ebooks.info
Preface
JavaScript borrows many great ideas from other programming languages, but its most
unique, and perhaps most powerful, feature is that any code written in JavaScript can
run as-is in any modern web browser. This is a big deal, and it is unlikely to change
anytime soon.
As web browsers improve and become available on more devices, more applications
are being ported from desktop applications to web applications. With the introduction
of HTML5, many of these applications will be able to work offline for the first time. In
order to create a superior user experience, much of the logic that was previously done
on the server will also have to be available on the client. Developers who have written
their server logic in Java, Python, or Ruby will have to figure out how to port that server
logic to JavaScript. Tools like Google Web Toolkit, which translate Java to JavaScript
can help with this, though such tools are often clumsy because the idioms from one
programming language do not always translate smoothly into that of another. However, if your server code is written in JavaScript, this is not an issue.
I believe that the use of server-side JavaScript (SSJS) is just beginning. Previously, most
implementations of JavaScript were too slow to be considered a viable option for server
code. Fortunately, the recent competition among browser vendors to have the fastest
JavaScript engine makes that difference far less significant (http://shootout.alioth.debian
.org).
Because of the emerging support for offline web applications, it is compelling to write
both the client and the server in the same programming language to avoid the perils
associated with maintaining parallel implementations of the same logic. Because it is
extremely unlikely that all of the major browser vendors will adopt widespread support
for a new programming language, that will continue to force the client side of a web
application to be written in JavaScript, which in turn will pressure developers to write
their servers in JavaScript as well. This means that the size of the average JavaScript
codebase is likely to increase dramatically in the coming years, so JavaScript developers
will need better tools in order to manage this increased complexity. I see Closure as the
solution to this problem.
xvii
www.it-ebooks.info
Closure is a set of tools for building rich web applications with JavaScript, and brings
with it a new approach to writing JavaScript and maintaining large JavaScript applications. Each tool in the suite is designed to be used independently (so jQuery developers
can make use of the Closure Compiler and Closure Templates, even if they are not
interested in the Closure Library), but they are most effective when used together.
Many JavaScript toolkits today focus on DOM utilities and UI widgets. Such functionality is incredibly useful when building the interface for a web application, but the
emergence of SSJS will require an equivalent effort in building server-side JavaScript
libraries. There, the focus is likely to be on data structures and efficient memory usage,
both of which are already woven into the Closure framework.
I believe that Closure will play an important part in making web applications faster and
more reliable. As an active user of the Web, I have a vested interest in making sure this
happens. That’s why I had to write this book. Rather than document every API in
Closure, I have tried to provide detailed explanations for the most commonly used
APIs, particularly those that are unique to the Closure approach.
Indeed, learning Closure will change the way you develop JavaScript applications.
My Experiences with Closure
When I worked at Google from 2005 to 2009, I used Closure to help build Google
Calendar and Google Tasks. When the initial work on Calendar was done in 2005, only
the Compiler was available, and it was (and is) known internally as the JavaScript
Compiler. At the time, there were a number of common JavaScript utilities that teams
would copy from one another. This led to many forked versions, so improvements to
one copy did not propagate to the others.
Meanwhile, the JavaScript codebase for Gmail had grown so large and complex that
developers complained that it was too hard for them to add new features. This triggered
a rewrite of the Gmail client, which precipitated the development of the two other major
tools in the Closure suite: the Library and Templates. The Library was simply named
“Closure,” as it was a play on the programming construct used so frequently in JavaScript, as well as the idea that it would bring “closure” to the nightmare that was
JavaScript development at Google.
Like many other JavaScript toolkits, the goal of Closure was to provide a comprehensive
cross-browser library. Instead of adopting an existing solution, such as Dojo, Google
decided to roll its own. By having complete control of its library, it could ensure that
the API would be stable and that the code would work with its (then) secret weapon:
the Closure Compiler. This made it possible to buck the trend established by libraries
like Prototype that encouraged the use of absurdly short function names. In Closure,
nondescript function names such as $ were eschewed in favor of more descriptive ones
because the Compiler would be responsible for replacing longer names with shorter
ones.
xviii | Preface
www.it-ebooks.info
The build system at Google was amended to express dependencies between JavaScript
files (these relationships are reflected by goog.provide() and goog.require() statements
in the Closure Library). For the first time, dependencies were organized into wellnamed packages, which introduced a consistent naming scheme and made utilities
easier to find. In turn, this made code reuse more straightforward, and the Library
quickly achieved greater consistency and stability than the previous dumping ground
of JavaScript utilities. This new collection of common code was far more trustworthy,
so teams started to link to it directly rather than fork their own versions, as they were
no longer afraid that it would change dramatically out from under them.
Finally, Closure Templates (known internally as Soy) were created to address the problem that most existing templating systems were designed to generate server code, but
not JavaScript code. The first version of Soy generated only JavaScript, but it was later
extended to generate Java as well, to provide better support for the “HTML Decorator”
pattern described in Chapter 8, User Interface Components.
By the time I started work on Google Tasks, these tools had matured considerably.
They were invaluable in creating Tasks. While the Calendar team was busy replacing
their original utility functions with Closure Library code and swapping out their homebrewed (or Bolin-brewed) template solution with Soy, I was able to make tons of progress on Tasks because I was starting with a clean slate. Because Gmail has been stung
by hard-to-track-down performance regressions in the past, the barrier for getting code
checked in to Gmail is high. In integrating Tasks with Gmail, I was forced to gain a
deeper understanding of the Closure Tools so I could use them to optimize Tasks to
the satisfaction of the Gmail engineers. Later, when I integrated Tasks in Calendar, I
learned how to organize a sizable JavaScript codebase so it could be incorporated by
even larger JavaScript projects.
One of my major takeaways from using Closure is that trying to address limitations of
the JavaScript programming language with a JavaScript library is often a mistake. For
example, JavaScript does not have support for multiline strings (like triple-quote in
Python), which makes it difficult to create templates for HTML. A bad solution (which
is the one I created for Google Calendar back in 2005 that they were still trying to phase
out so they could replace it with Soy in 2009) is to create a JavaScript library like jQuery
Templates (http://plugins.jquery.com/project/jquerytemplate). Such a library takes a
string of JavaScript as the template and parses it at runtime with a regular expression
to extract the template variables. The appeal, of course, is that implementing something
like jQuery Templates is fairly easy, whereas implementing a template solution that is
backed by an actual parser is fairly hard (Closure Templates does the latter). In my
experience, it is much better to create a tool to do exactly what you want (like Closure
Templates) than it is to create a construct within JavaScript that does almost what you
want (like jQuery Templates). The former will almost certainly take longer, but it will
pay for itself in the long run.
Preface | xix
www.it-ebooks.info
Audience
As this is a book about Closure, a suite of JavaScript tools, it assumes that you are
already familiar with JavaScript. Nevertheless, because so many JavaScript programmers learn the language by copying and pasting code from existing websites, Appendix B is included to try to identify incorrect assumptions you may have made about
JavaScript when coming from your favorite programming language. Even those who
are quite comfortable with the language are likely to learn something.
Other than the Closure Tools themselves, this book does not assume that you are
already familiar with other JavaScript tools (such as JSLint and YUI Compressor) or
libraries (such as Dojo and jQuery), though sometimes parallels will be drawn for the
benefit of those who are trying to transfer their knowledge of those technologies in
learning Closure. The one exception is Firebug, which is a Firefox extension that helps
with web development. In addition to being considered an indispensable tool for the
majority of web developers, it must be installed in order to use the Closure Inspector.
Unlike the other tools in the suite, the use of the Closure Inspector is tied to a single
browser: Firefox. Because Firebug is updated frequently and has comprehensive documentation on its website, this book does not contain a tutorial on Firebug because it
would likely be outdated and incomplete. http://getfirebug.com should have everything
you need to get started with Firebug.
Finally, this book makes a number of references to Java when discussing Closure.
Although it is not necessary to know Java in order to learn Closure, it is helpful to be
familiar with it, as there are elements of Java that motivate the design of the Closure
Library. Furthermore, both Closure Templates and the Closure Compiler are written
in Java, so developers who want to modify those tools will need to know Java in order
to do so. This book will not teach you Java, though a quick search on Amazon will
reveal that there of hundreds of others that are willing to do so.
ECMAScript Versus JavaScript
This book includes several references to ECMAScript, as opposed to JavaScript, so it
is important to be clear on the differences between the two. ECMAScript is a scripting
language standardized by Ecma International, and JavaScript is an implementation of
that standard. Originally, JavaScript was developed by Netscape, so Microsoft developed its own implementation of ECMAScript named JScript. This means that technically, “ECMAScript” should be used to refer to the scripting language that is universally
available on all modern web browsers, though in practice, the term “JavaScript” is used
instead. To quote Brendan Eich, the creator of JavaScript: “ECMAScript was always
an unwanted trade name that sounds like a skin disease.” To be consistent with colloquial usage (and honestly, just because it sounds better), JavaScript is often used to
refer to ECMAScript in this book.
xx | Preface
www.it-ebooks.info
However, ECMAScript is mentioned explicitly when referring to the standard. The
third edition of the ECMAScript specification (which is also referred to as ES3) was
published in December 1999. As it has been around for a long time, it is implemented
by all modern web browsers. More recently, the fifth edition of the ECMAScript specification (which is also referred to as ES5) was published in December 2009. (During
that 10-year period, there was an attempt at an ES4, but it was a political failure, so it
was abandoned.) As ES5 is a relatively new standard, no browser implements it fully
at the time of this writing. Because Closure Tools are designed to create web applications that will run on any modern browser, they are currently designed around ES3.
However, the Closure developers are well aware of the upcoming changes in ES5, so
many of the newer features of Closure are designed with ES5 in mind, with the expectation that most users will eventually be using browsers that implement ES5.
Using This Book
This book explains all of the Closure Tools in the order they are most likely to be used.
• Chapter 1, Introduction to Closure, introduces the tools and provides a general
overview of how they fit together with a complete code example that exercises all
of the tools.
When working on a JavaScript project, you will spend the bulk of your time designing
and implementing your application. Because of this, the majority of the book is focused
on how to leverage the Closure Library and Closure Templates to implement the functionality you desire. Of all the topics covered in this part of the book, the rich text editor
is the one that appears most frequently in the Closure Library discussion group. To
that end, I recruited goog.editor expert Julie Parent as a contributing author, so fortunately for you and for me, Julie wrote Chapter 9.
• Chapter 2, Annotations for Closure JavaScript, explains how to annotate JavaScript
code for use with the Closure Compiler.
• Chapter 3, Closure Library Primitives, provides documentation and commentary
on every public member of base.js in the Closure Library.
• Chapter 4, Common Utilities, surveys functionality for performing common operations with the Closure Library, such as DOM manipulation and user agent
detection.
• Chapter 5, Classes and Inheritance, demonstrates how classes and inheritance are
emulated in Closure.
• Chapter 6, Event Management, explains the design of the Closure Library event
system and the best practices when using it.
• Chapter 7, Client-Server Communication, covers the various ways the goog.net
package in the Closure Library can be used to communicate with the server.
Preface | xxi
www.it-ebooks.info
• Chapter 8, User Interface Components, discusses a number of the UI widgets provided by the Closure Library and documents the life cycle of a Closure widget.
• Chapter 9, Rich Text Editor, examines the rich text editor widget in the Closure
Library in detail. This chapter is written by Julie Parent, who wrote the overwhelming majority of the code for this component.
• Chapter 10, Debugging and Logging, demonstrates how to add logging statements
that can be used during development, but can also be removed in production code.
• Chapter 11, Closure Templates, covers how Templates can be used to generate
parameterized JavaScript and Java functions that generate HTML efficiently.
The next three chapters will explain how to get the most out of your source code using
the Closure Compiler:
• Chapter 12, Using the Compiler, demonstrates how to minify code using the
Compiler.
• Chapter 13, Advanced Compilation, goes beyond the Compiler as a minifier and
explains how to use it as a proper compiler, showing how to identify errors at
compile time and achieve size reductions that go far beyond what ordinary minification can do.
• Chapter 14, Inside the Compiler, explores the source code of the Closure Compiler
itself and reveals how to use it as the basis of your own JavaScript tools.
The remaining chapters will focus on evaluating your code to ensure that it does what
you designed it to do:
• Chapter 15, Testing Framework, explains how to write and run unit tests using the
Framework.
• Chapter 16, Debugging Compiled JavaScript, demonstrates how to find errors in
compiled code using the Closure Inspector.
The first two appendixes provide additional information about JavaScript: they are
designed to enrich your knowledge of the language. The third appendix discusses a
build tool that unites the Closure Tools in a way that makes them easier to use.
• Appendix A, Inheritance Patterns in JavaScript, discusses two approaches for simulating inheritance in JavaScript and focuses on the advantages of the approach
used by Closure.
• Appendix B, Frequently Misunderstood JavaScript Concepts, explains features of
the language that often trip up developers, both old and new.
• Appendix C, plovr, introduces a build tool of the same name that can dramatically
simplify and speed up development with the Closure Tools.
xxii | Preface
www.it-ebooks.info
Conventions Used in This Book
The following typographical conventions are used in this book:
Italic
Indicates new terms, URLs, and email addresses.
Constant width
Used for program listings, as well as within paragraphs to refer to program elements
such as filenames, file extensions, variable or function names, databases, data
types, environment variables, statements, and keywords.
Constant width bold
Shows commands or other text that should be typed literally by the user.
Constant width italic
Shows text that should be replaced with user-supplied values or by values determined by context.
This icon signifies a tip, suggestion, or general note.
This icon indicates a warning or caution.
Using Code Examples
This book is here to help you get your job done. In general, you may use the code in
this book in your programs and documentation. You do not need to contact us for
permission unless you’re reproducing a significant portion of the code. For example,
writing a program that uses several chunks of code from this book does not require
permission. Selling or distributing a CD-ROM of examples from O’Reilly books does
require permission. Answering a question by citing this book and quoting example
code does not require permission. Incorporating a significant amount of example code
from this book into your product’s documentation does require permission.
We appreciate, but do not require, attribution. An attribution usually includes the title,
author, publisher, copyright holder, and ISBN. For example: “Closure: The Definitive
Guide by Michael Bolin (O’Reilly). Copyright 2010 Michael Bolin,
978-1-449-38187-5.”
If you feel your use of code examples falls outside fair use or the permission given here,
feel free to contact us at permissions@oreilly.com.
Preface | xxiii
www.it-ebooks.info
Safari® Books Online
Safari Books Online is an on-demand digital library that lets you easily
search over 7,500 technology and creative reference books and videos to
find the answers you need quickly.
With a subscription, you can read any page and watch any video from our library online.
Read books on your cell phone and mobile devices. Access new titles before they are
available for print, and get exclusive access to manuscripts in development and post
feedback for the authors. Copy and paste code samples, organize your favorites, download chapters, bookmark key sections, create notes, print out pages, and benefit from
tons of other time-saving features.
O’Reilly Media has uploaded this book to the Safari Books Online service. To have full
digital access to this book and others on similar topics from O’Reilly and other publishers, sign up for free at http://my.safaribooksonline.com.
How to Contact Us
Please address comments and questions concerning this book to the publisher:
O’Reilly Media, Inc.
1005 Gravenstein Highway North
Sebastopol, CA 95472
800-998-9938 (in the United States or Canada)
707-829-0515 (international or local)
707 829-0104 (fax)
We have a web page for this book, where we list errata, examples, and any additional
information. You can access this page at:
http://oreilly.com/catalog/9781449381875/
To comment or ask technical questions about this book, send email to:
bookquestions@oreilly.com
For more information about our books, conferences, Resource Centers, and the
O’Reilly Network, see our website at:
http://www.oreilly.com
Acknowledgments
I would like to start out by thanking my contributing author, Julie Parent, for her
outstanding work on the rich text editing chapter, and perhaps more importantly, for
her many years of work on the rich text editor widget itself while working at Google.
What started out as a component for the (now forgotten) Google Page Creator product
xxiv | Preface
www.it-ebooks.info
way back in 2005 has become a critical widget for many Google Apps today (most
notably, Gmail). If they gave out doctorates for the field of “little-known browser bugs
that make rich text editing in the browser nearly impossible,” then Julie would be a
leader in the field and Chapter 9 could have been used as her dissertation. Julie, thank
you so much for putting the same amount of diligence into writing your chapter as you
did in developing the rich text editor in the first place.
Next, I owe a tremendous amount of thanks (and a nice bottle of scotch) to Nick Santos,
who has been a phenomenal technical reviewer. He responded to the call for reviewers
with alacrity and his enthusiasm in the project never waned. In doing a review of this
book, Nick effectively engaged in a 35,000-line code review, and provided so many
corrections and helpful suggestions that this book probably would not even be worth
reading if Nick had not read it first. In addition to all of his work as a reviewer, Nick
played (and continues to play) an active role in open-sourcing the Closure Compiler as
well as its development. You can see the breadth and depth of Nick’s knowledge in the
Closure Compiler discussion group, as he is an extremely active member there, as well.
In addition to Nick, I was fortunate enough to have two other Google engineers who
helped build pieces of the Closure Tools suite to participate in the review process. Erik
Arvidsson (who co-created the Closure Library with Dan Pupius—thanks, Dan!) provided lots of valuable feedback on the chapters on the Library. Likewise, the creator of
Closure Templates, Kai Huang, provided detailed criticisms of the chapter on Soy.
Many thanks to both Erik and Kai for lending their time and expertise to ensure that
the story of their work was told correctly.
As Nick explained in the foreword, taking a closed source project and turning it into
an open source one is a lot of work, so I would also like to recognize those who played
an important role in that process. Nathan Naze, Daniel Nadasi, and Shawn Brenneman
all pitched in to open source the Closure Library. Robby Walker and Ojan Vafai also
helped out by moving the rich text editor code into the Library so that it could be opensourced, as well. Extra thanks to Nathan for continuing to manage the open-sourcing
effort and for giving talks to help get the word out about the Library. It is certainly an
example of well-spent 20% time at Google.
In that same vein, I would also like to thank Dan Bentley for helping ensure that all of
this Closure code made it out into the open. Google is lucky to have him working in
their Open Source Programs Office, as his genuine belief and interest in open source
benefits the entire open source community.
I would also like to thank my former teammates on the Closure Compiler team who
all contributed to the open source effort as well as Compiler development: Robert
Bowdidge, Alan Leung, John Lenz, Nada Amin, and Antonio Vincente. Also, thanks
to our manager, Ram Ramani, who supported this effort the whole way through and
helped coordinate the open source launch. I also want to give credit to our intern, Simon
Mathieu, who worked with me to create the Closure Compiler Service.
Preface | xxv
www.it-ebooks.info
Thank you to Joey Schorr for navigating the world of not just Firefox extensions, but
also Firebug extensions, in order to create and maintain the Closure Inspector. Without
Joey, all of our compiled JavaScript would be filled with alert() statements (though
for some of us, that’s how our uncompiled JavaScript looks, too!).
Five hundred pages later, I now have a much better appreciation for the work of David
Westbrook and Ruth Wang, who as tech writers at Google produced much of the public
documentation for Closure Tools that is freely available on http://code.google.com.
Thanks to both David and Ruth for their attention to detail in explaining what these
Closure shenanigans are all about.
Although I have already dropped the names of a lot of Googlers, I know that there are
many more who have contributed to Closure over the years, so I am sure that I am
leaving some out, and I apologize for any omissions. I hope that all of you continue to
make Closure the best choice when choosing a set of tools for building amazing web
applications. As frontend engineers working on products at Google, your work already
has the opportunity to reach many users around the world. But now that all of Closure
is open source, you have the opportunity to have a similar impact on web developers.
I hope that opportunity does not go to waste!
Believe it or not, there were also people who never worked at Google who also helped
make this book possible. Thank you to my editors, Julie Steele and Simon St.Laurent,
who helped green-light this project back in November 2009, less than a month after
the Closure Tools were even open-sourced. I would also like to thank my “unofficial
editors,” which includes everyone who posted a comment on the Rough Cut, especially
Donald Craig and Derek Slager. Not only did all of you help make this book better, but
you also gave me the confidence that someone was actually going to read this thing
someday and that it was worth writing.
Finally, I would like to thank Sarah, without whose unrelenting patience and support
I would not have been able to finish this book. In many ways, writing a book is a lonely
endeavor, but you never let it get that way because you were there to encourage me
throughout the entire process. I would also like to thank my mom, whose love of books
undoubtedly helped inspire me to write this one. Thanks to my sister Katie for letting
me know when she noticed a jump in my page count graph, as it means a lot to know
that someone out there cares and is paying attention. And last but not least, I would
like to thank my father for betting me $500 that I would not be a published author by
30, which provided the extra motivation I needed to see this book all the way through.
I’ll take my winnings in cash, old man!
xxvi | Preface
www.it-ebooks.info
CHAPTER 1
Introduction to Closure
Closure is a collection of tools for building rich web applications in JavaScript. Each
tool in the suite is open-sourced under the Apache 2.0 license, and is created, maintained, and made available for free by Google. Closure is used in the development of
many web applications at Google, including Gmail, Google Maps, and Google Docs.
The performance and scale of these web applications is a testament to the strength and
sophistication of the Closure Tools suite.
Some developers might balk at the thought of expanding the role of JavaScript in their
web applications. Why should the codebase of a language that relies on global variables
and has no support for namespaces get bigger and more complex? Others may point
out that Google simultaneously offers the Google Web Toolkit (GWT) so that web
developers do not even have to concern themselves with JavaScript. Why do we need
new tools for JavaScript when the tools for avoiding it already exist?
Whether you like it or not, JavaScript is the lingua franca of the Web. Although tools
such as GWT do a reasonable job of abstracting away JavaScript, they also create barriers between you and the metal of the browser. Instead of creating tools to circumvent
JavaScript, why not build tools to address its problems head-on?
This is where Closure comes in: the tools make it significantly easier to maintain a large
JavaScript codebase. Using Closure essentially extends JavaScript to include features
available in other programming languages, such as namespaces, type checking, and
data hiding. Furthermore, it does so without incurring the runtime overhead of previous
approaches (see Appendix B). More importantly, it does not sacrifice the good parts of
JavaScript (prototypal inheritance, regular expression literals, first-class functions) that
are not available in other programming languages, such as Java. This transforms JavaScript from a language one must “deal with” into one that is fun and productive.
1
www.it-ebooks.info
In addition to making your development team happier, using Closure will also make
your users happier. The crown jewel of the suite, the Closure Compiler, can significantly reduce the amount of JavaScript that users will have to download when visiting
your site. It does this by replacing long variable names with shorter ones, removing
unused code, and by applying a variety of other optimizations. In addition to making
your web application faster, shrinking code will also save you money because it reduces
bandwidth costs. Further, it helps protect your IP because renaming variables serves
to obfuscate your code, making it more difficult for other websites to copy your
functionality.
Tools Overview
In addition to the Closure Compiler, there are currently four other tools available in
the Closure suite. Figure 1-1 shows the common workflow when using all of the tools
together. This section provides a brief description of each tool in the order in which it
is encountered in this book.
Figure 1-1. Workflow when using Closure Tools.
Closure Library
The Closure Library is a comprehensive JavaScript library analogous to other contemporary offerings, such as jQuery, Dojo, and MooTools. The coding style and use of
annotations in the Closure Library are tailored for use with the Closure Compiler,
which is its main distinguishing feature when compared to other JavaScript libraries.
2 | Chapter 1: Introduction to Closure
www.it-ebooks.info
This can have dramatic effects on the Compiler’s ability to minify code, as a simple
minification experiment finds that Closure Library code can be 85 percent smaller when
using the Closure Compiler in place of the YUI Compressor (http://blog.bolinfest.com/
2009/11/example-of-using-closure-compiler-to.html).
The Closure Library is also implemented with a strong emphasis on performance and
readability. It is frugal in creating objects, but generous in naming and documenting
them. It also has an elegant event system, support for classes and inheritance, and a
broad collection of UI components, including a rich text editor. Closure Library code
is regularly tested across browsers, and to the extent that it can, will also work in nonbrowser JavaScript environments, such as Rhino (http://www.mozilla.org/rhino/) and
the Microsoft Windows Script Host. Because the Library is a resource for Google engineers first and an open source project second, it is a safe bet that every line of code
in the Library was developed to support at least one Google product. The style of the
Library will first be introduced in Chapter 2, and the functionality of the Library will
be covered in the following eight chapters.
Closure Templates
Closure Templates provide an intuitive syntax for creating efficient JavaScript functions
(or Java objects) that generate HTML. This makes it easier to create a large string of
HTML that can in turn be used to build up the DOM. Unfortunately, most programming languages do not have native support for templates, so creating a separate
templating solution is a common practice for web frameworks (J2EE has JSP, Python
developers frequently use Django’s template system, etc.). A unique aspect of Closure
Templates is that the same template can be compiled into both Java and JavaScript, so
those running servers written in Java (or JavaScript!) can use the same template on both
the server and the client. The benefits of this, along with Closure Templates, will be
covered in Chapter 11.
Closure Compiler
The Closure Compiler is a JavaScript optimizing compiler: it takes JavaScript source
code as input and produces behaviorally equivalent source code as output. That is,
when the output code is used in place of the input code, the observable effect will be
the same (though the output code is likely to execute faster than the original). As a
simple example, if the input code were:
/**
* @param {string} name
*/
var hello = function(name) {
alert('Hello, ' + name);
};
hello('New user');
Tools Overview | 3
www.it-ebooks.info
then the Compiler would produce the following behaviorally-equivalent output:
alert("Hello, New user");
Executing either code snippet will have the same effect: an alert box will display with
the text "Hello, New user". However, the output code is more concise, so it can be
downloaded, parsed, and executed faster than the input code.
Furthermore, the Compiler can detect a large class of errors by performing static checks
at compile time, much like JSLint. This helps find bugs earlier, dramatically speeding
up JavaScript development. Using the Compiler to identify problems is not a substitute
for unit testing, but it certainly helps.
For existing JavaScript applications, the Closure Compiler is likely to be the Closure
Tool that is most immediately useful. Although it will be most effective when used to
compile code written in the style of the Closure Library, replacing an existing dependency on jQuery or Dojo with that of the Library could be time-consuming. By comparison, the Closure Compiler can be used in place of existing JavaScript minifiers (such
as JSMin or YUI Compressor) with much less effort. The Compiler will be introduced
in Chapter 12.
Closure Testing Framework
The Closure Testing Framework is a unit-testing framework that runs in the browser,
much like JsUnit. Most Closure Library code has a corresponding test that runs in the
Framework. It is good programming practice to create tests for your own code and to
run them regularly to identify regressions. Because the Closure Testing Framework runs
inside the browser, additional software is needed to automate the process of starting
up a browser, running the tests, and recording the results. Selenium is likely the best
solution for that purpose. The Closure Testing Framework will be explained in
Chapter 15.
Closure Inspector
The Closure Inspector is an extension to Firebug to aid in debugging compiled JavaScript. Firebug is an extension for Firefox (which is not developed by Google) that
brings together a number of web development tools, including a JavaScript debugger,
available through the browser. When using the Firebug debugger with obfuscated code
produced by the Closure Compiler, it is hard to trace a runtime error back to its position
in the original source code. The Closure Inspector facilitates debugging by exposing
the mapping between the original and compiled code in the Firebug UI. It will be discussed in more detail in Chapter 16.
4 | Chapter 1: Introduction to Closure
www.it-ebooks.info
Closure Design Goals and Principles
Before diving into the code, it is important to understand the design goals and principles
that motivate the implementation of the Closure Tools. Much of the design of the
toolkit is motivated by the capabilities of the Compiler and the style of the Library.
Reducing Compiled Code Size Is Paramount
The primary objective of the Closure Compiler is to reduce the size of JavaScript code.
Because Google serves so many pages with JavaScript and prides itself on speed (Google
engineers have T-shirts that say “Fast is my favorite feature”), it is imperative that the
JavaScript required to display a page is as small as possible. Even when JavaScript is
cached by the browser, it must still be parsed and executed again when the page that
uses it is reloaded. The smaller the JavaScript, the less time this takes.
Specifically, the Compiler favors reducing the size of gzipped JavaScript over uncompressed JavaScript. For example, it might be tempting to have the Compiler rewrite the
following function:
Line.prototype.translate = function(distance) {
this.x1 += distance;
this.y1 += distance;
this.x2 += distance;
this.y2 += distance;
};
so that it creates a temporary variable for this before compiling the code:
Line.prototype.translate = function(distance) {
var me = this;
me.x1 += distance;
me.y1 += distance;
me.x2 += distance;
me.y2 += distance;
};
The motivation here is that the Compiler can rename me but cannot rename this because this is a JavaScript keyword. Although using the temporary variable results in
smaller uncompressed code when run through the Compiler, the gzipped size of the
compiled code is larger when using the temporary variable. Because the overwhelming
majority of browsers can accept gzipped JavaScript, the Compiler focuses on optimizations that will benefit the gzipped code size. Most optimizations are wins for both
compressed and gzipped JavaScript, but there are occasionally exceptions, such as this
one.
JavaScript code should be written in a way that can be compiled efficiently by the
Compiler. This is fundamental to understanding the design of the Closure Library: the
verbosity of the code is not representative of its size after being processed by the Compiler. If more code (or annotations) need to be written to result in smaller compiled
code, then that is preferable to writing less code that results in larger compiled code.
Closure Design Goals and Principles | 5
www.it-ebooks.info
For example, writing comprehensive utility libraries is acceptable as long as the unused
parts can be removed by the Compiler. Complementary methods should be replaced
with a single parameterized method (e.g., prefer setEnabled(enable) to enable() and
disable()). This reduces the number of method declarations and is more amenable to
function currying. Therefore, to fully understand the Closure Library, one must also
understand how the Compiler rewrites JavaScript code.
One may wonder if any emphasis is placed on using the Compiler to produce JavaScript
with better runtime performance. The short answer is yes, but because runtime performance is so much harder to measure than code size, more engineering time has been
spent on improving minification. Fortunately, many reductions in code size also
improve performance, as many optimizations result from evaluating expressions at
compile time rather than runtime.
All Source Code Is Compiled Together
The Compiler is designed to compile all code that could be run during the course of
the application at once. As shown in Figure 1-1, there are many potential sources of
input, but the Compiler receives all of them at the same time. This is in contrast to
other languages, in which portions of source code are compiled into reusable modules.
In Closure, it is the opposite: source code is initially compiled together and is then
carved up into modules that may be progressively loaded by a web application. This is
done to ensure that the variable names used in individual modules are globally unique.
Managing Memory Matters
As the Gmail team explained on their blog (http://gmailblog.blogspot.com/2008/09/new
-gmail-code-base-now-for-ie6-too.html), they encountered a performance problem with
Internet Explorer 6 (IE6) with respect to memory management that prevented IE6 users
from getting a newer version of Gmail until Microsoft provided a patch to IE6 users.
Although this caused the Gmail engineers a considerable amount of pain, it did force
them to invest extra effort into managing memory on the client.
Like most modern programming languages, JavaScript manages its own memory. Unfortunately, this does not preclude the possibility of a memory leak, as failing to release
references to objects that are no longer needed can still cause an application to run out
of memory. The Closure Library uses goog.Disposable to ensure that references are
released as soon as possible so that objects may be garbage collected. goog.Disposa
ble will be introduced in Chapter 5, and managing event listeners (another common
source of memory leaks) will be explained in Chapter 6.
The issues with IE6’s garbage collection are so severe that the Closure Library offers
goog.structs.Map as an abstraction around JavaScript’s native Object to reduce the
number of string allocations when iterating over the keys of an object. The justification
is revealed in a comment in the goog.structs.Map source code:
6 | Chapter 1: Introduction to Closure
www.it-ebooks.info
/**
* An array of keys. This is necessary for two reasons:
*
1. Iterating the keys using for (var key in this.map_) allocates an
*
object for every key in IE which is really bad for IE6 GC perf.
*
2. Without a side data structure, we would need to escape all the keys
*
as that would be the only way we could tell during iteration if the
*
key was an internal key or a property of the object.
*
* This array can contain deleted keys so it's necessary to check the map
* as well to see if the key is still in the map (this doesn't require a
* memory allocation in IE).
* @type {!Array.}
* @private
*/
this.keys_ = [];
Now that Microsoft has provided a patch for the problem with IE6, such
micromanagement of string allocation is less compelling. However, as more mobile
devices are running web browsers with fewer resources than their desktop equivalents,
attention to memory management in general is still merited.
Make It Possible to Catch Errors at Compile Time
The Closure Compiler is not the first tool to try to identify problems in JavaScript code
by performing static checks; however, there is a limit to how much can be inferred by
the source code alone. To supplement the information in the code itself, the Compiler
makes use of developer-supplied annotations which appear in the form of JavaScript
comments. These annotations are explained in detail in Chapter 2.
By annotating the code to indicate the parameter and return types of functions, the
Compiler can identify when an argument of the incorrect type is being passed to a
function. Similarly, annotating the code to indicate which data are meant to be private
makes it possible for the Compiler to identify when the data are illegally accessed. By
using these annotations in your code, you can use the Compiler to increase your confidence in your code’s correctness.
Code Must Work Without Compilation
Although the Compiler provides many beneficial transformations to its input, the code
for the Closure Library is also expected to be able to be run without being processed
by the Compiler. This not only ensures that the input language is pure JavaScript, but
also makes debugging easier, as it is always possible to use the deobfuscated code.
Code Must Be Browser-Agnostic
The Closure Library is designed to abstract away browser differences and should work
in all modern browsers (including IE6 and later). It should also work in non-browser
environments, such as Rhino and the Windows Script Host (though historically the
Closure Design Goals and Principles | 7
www.it-ebooks.info
motivation behind creating a browser-agnostic library was to support WorkerPools in
Google Gears). This means that common browser objects such as window and naviga
tor are not assumed to exist.
This does not mean that the Closure Library lacks utilities for dealing with browserspecific APIs such as the DOM. On the contrary, the Library provides many methods
for working within the browser. However, Library code that works with objects that
are universally available in all JavaScript environments (strings, arrays, functions, etc.)
does not rely on APIs that are available only to the browser. This makes the Closure
Library a good candidate for use with server-side JavaScript, as well.
Built-in Types Should Not Be Modified
Built-in object prototypes, such as Object, Function, Array, and String should not be
modified. This makes it possible to use Closure alongside other JavaScript libraries,
such as jQuery. In practice, however, using Closure with other libraries is generally
inefficient. Each library will have its own logic for event management, string manipulation, etc., which means that duplicate logic will likely be included, increasing the
amount of JavaScript code that will be loaded.
Code Must Work Across Frames
The Closure Library is designed to be loaded once per frameset (though it is designed
so that multiple instances of the Library should not “step on each other” if it is loaded
more than once). The Library recognizes that built-in objects, such as Arrays, may be
constructed in different frames and therefore will have distinct prototypes. For web
applications that use multiple frames (such as using a separate