Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Use Closure Tools to Build Rich WebApps

Use Closure Tools to Build Rich WebApps

Introduction to how to use Google Closure Tools to build rich web apps

Eric Shangkuan

March 02, 2011
Tweet

More Decks by Eric Shangkuan

Other Decks in Programming

Transcript

  1. Outlines • Introduction to Closure Tools • http://code.google.com/closure/ • Build

    a Web Application • Design by using Closure Library widgets • Build and compress the JavaScript codes (deployment) • Extend Closure Libraries • Q. & A.
  2. Closure Tools • Closure Library • Rich widgets, used to

    build the UI of applications. • Hide the cross-browser issues • Object (prototype)-oriented Design • Closure Compiler • Analysis and optimize the JavaScript code • Compress the size of code • Closure Template • Used to build HTML template (dynamic content) • Building template by either JavaScript or Java. • Closure Linter • A JavaScript code style checker • Guideline is Google JavaScript Style Guide
  3. Render VS. Decorate • Render: Create the component with pure

    JavaScript code, and render it on a DOM element. • Decorate: Use HTML to construct the structure of the component, and then, `decorate` (bind) it in JavaScript. <div id="namelist" class="goog-menu"> <div class="goog-menuitem">Alice</div> <div class="goog-menuitem">Bob</div> <div class="goog-menuitem">Charles</div> </div> HTML mockup: Decorate in JavaScript: var menu = new goog.ui.Menu(); menu.decorate(goog.dom.getElement('namelist'));
  4. Closure Compiler • Analysis to optimize code and remove unused

    code. • Compress the code size • Usages: online, web service, binary JAR file. var DEBUG = false; if (DEBUG) { console.log('Show debug messages...'); } var message = 'foo' + 'bar' + 'baz' + 'qux'; alert(message); alert('foobarbazqux');
  5. Closure Template • Use Closure Template tags (soy syntax) to

    build template. • Compile the template to a JavaScript file. {namespace foo.bar} /** * @param $name * @param? $greetingWord */ {template .helloName} {if not $greetingWord} Hello {$name}! {else} {$greetingWord} {$name}! {/if} {/template} foo.js file <!-- hello.html --> <script src="soyutils.js"></script> <script src="foo.js"></script> <script> document.write( foo.bar.helloName({name: 'Eric', greetingWord: 'Hello'})); </script>
  6. Project Template • Here is an example of Closure Tool-based

    project template PROJECT_ROOT/ bin/ build.py closure-compiler.jar yui-compressor.jar SoyToJsSrcCompiler.jar closure-library/ -- PUT CLOSURE LIBRARY HERE -- app.html app.js deps.js jquery.min.js soyutils.js styles.css tweet_item.soy
  7. app.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>A Simple Twitter

    Client</title> <link rel="stylesheet" href="styles.css"> </head> <body> <!-- application container --> <div id="app"> <div id="top"></div> <h3>Results:</h3> <ul id="bottom"></ul> </div> <!-- load necessary JavaScript libraries --> <script src="jquery.min.js"></script> <script src="soyutils.js"></script> <script src="tweet_item_template.js"></script> <script src="closure-library/closure/goog/base.js"></script> <!-- will define org.ericsk.twitter class here --> <script src="app.js"></script> <!-- start the application --> <script> app = new org.ericsk.twitter(); app.init(); </script> </body> </html>
  8. Skeleton of app.js (function(window, undefined){ var APPNAME = 'org.ericsk.twitter'; //

    define the application class’s canonical name goog.provide(APPNAME); // load closure library dependencies goog.require('...'); ... var appInst = null; // application prototype (class) var App = App || function() { appInst = this; }; // define App’s prototype (methods, members, ...) App.prototype.init = function() { ... }; ... // mapping the App prototype to the symbol -- org.ericsk.twitter goog.exportSymbol(APPNAME, App); })(window);
  9. Create Search Controls goog.require('goog.ui.Button'); goog.require('goog.ui.CustomButton'); goog.require('goog.ui.Textarea'); goog.require('goog.ui.TextareaRenderer'); /** * Initialize

    the search controls (textfield and button) */ App.prototype._initControls = function() { var topPanel = goog.dom.getElement('top'); // create the controls var searchField = new goog.ui.Textarea(); var searchButton = new goog.ui.CustomButton('Search'); // bind event handler goog.events.listen(searchButton, goog.ui.Component.EventType.ACTION, this._onSearchButtonClicked); // render these controls searchField.render(topPanel); searchButton.render(topPanel); // bind to App instance this.searchField = searchField; this.searchButton = searchButton; };
  10. Tweet Item Template {namespace org.ericsk} /** * Tweet item template

    * @param avatarUrl * @param username * @param tweet * @param tweet_id */ {template .TweetItem} <li class="tweet-item"> <img src="{$avatarUrl}" alt="" class="tweet-avaatar"> <button class="tweet-view" data-tweetid="{$tweet_id}">View</button> <h5 class="tweet-username">{$username}</h5> <div class="tweet-content">{$tweet}</div> </li> {/template}
  11. On Search Button is Clicked $.getJSON('http://search.twitter.com/search.json', {'q': query}, function(data) {

    var buf = []; for (var i in data.results) { var item = data.results[i]; buf.push(org.ericsk.TweetItem({ 'avatarUrl': item.profile_image_url, 'username': item.from_user, 'tweet': item.text, 'tweet_id': item.id })); } $bottom.html(buf.join('')); } );
  12. Deployment • Closure library contains large amount of widgets •

    Your application doesn’t use every JavaScript code • Load dependencies every time the application executes may increase the application’s response time => poor experience • Use Closure Builder to calculate dependencies... • Extract necessary JavaScript files • Compress these JavaScript files into ONE JavaScript file
  13. Closure Builder Script /path/to/closure_builder.py --output_mode=compiled --comiler_jar=/path/to/closure-compiler.jar --compiler_flags="--warning_level=QUIET" --compiler_flags="--js=jquery.min.js” --compiler_flags="--js=soyutils.js" --compiler_flags="--js=tweet_item_template.js"

    --root=. --root=closure-library --namespace="org.ericsk.twitter" > app.min.js Build the JavaScript files... Build the CSS files... java -jar /path/to/yui-compressor.jar --type css styles.css > styles.min.css for file in CSS_FILES: java -jar /path/to/yui-compressor.jar --type css file >> styles.min.css
  14. app-production.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>A Simple Twitter

    Client</title> <link rel="stylesheet" href="styles.min.css"> </head> <body> <!-- application container --> <div id="app"> <div id="top"></div> <h3>Results:</h3> <ul id="bottom"></ul> </div> <!-- load necessary JavaScript libraries --> <script src="app.min.js"></script> <!-- start the application --> <script> app = new org.ericsk.twitter(); app.init(); </script> </body> </html>
  15. In Closure’s Way • Ref: third_party/ directory. • Use goog.provider('goog.namespace.YOUR_LIB');

    to declare your module. • Use goog.addDependency('/path/to/lib.js', [DEPENDENCIES]); to setup the dependencies.
  16. Custom Component Sample /* /path/to/mylib/lib.js */ goog.provide('goog.mylib'); goog.mylib = function(params)

    { ... }; goog.mylib.prototype.fooBar = function() { ... }; /* /path/to/deps.js */ goog.addDependency('/path/to/mylib/lib.js', ['goog.dom', 'goog.events', ...]); /* app.html */ ... <script src="/path/to/closure-library/base.js"></script> <script src="/path/to/deps.js"></script> <script> goog.require('goog.mylib'); </script> <script> var lib = new goog.mylib(...); ... </script>