YUI and Node.js Sitting in a tree S-E-R-V-I-N-G H-T-T-P Tom Hughes-Croucher @sh1mmer
Jan 15, 2015
YUI and Node.jsSitting in a tree
S-E-R-V-I-N-G H-T-T-P
Tom Hughes-Croucher@sh1mmer
YUI3 + Node.js IS SO AWESOME
MY ENTIRE PRESENTATION IS IN COMIC SANS
AND YOU WILL STILL LOVE ME AT THE END
Node.js• Server-side JavaScript process
• Uses V8
• Non-blocking
• Event Driven
• CommonJS module format
Node.js• Server-side JavaScript process
• Uses V8
• Non-blocking
• Event Driven
• CommonJS module format
AWESOME!
At JSCONF.US 2010Node was ☜⎻⎻⎻⎻⎻☞ this fast
ButRyan doesn’t roll like that. Ryan rolls like this
Why SSJS?
JavaScript programmers
3 > 2 > 1
Massive Code base of YUI and other JS librariesI heard some people use this thing called jQuery,
but I’m not convinced it’ll catch on
Laziness or “I’m sick of writing stuff twice”I could have said efficiency, but I think we all secretly long to sit around in our y-fronts. Except Higgins, who already does.
Progressive Enhancement is free*Remember WWCD (What Would Crockford Do)
*close enough
TL;DR:SSJS is Awesome
Like a Unicorn riding a Narwhal
YUI3Awesome like a Narwhal riding a Unicorn
YUI 3• Modular
• Sandboxed
• Intrinsic component loading
• Core team + community (50+ extensions)
• Not just about manipulating the DOM
YUI 3• Script Loading
• Remote i/o
• Events and Attributes
• Data Manipulation
• Language Utilities
• Templating
Making it work - 1
if (typeof exports == 'object') { exports.YUI = YUI; }
YUI exports itself per the CommonJS spec
Making it work - 2
YUI({ logFn: function(str, t, m) { if (str instanceof Object || str instanceof Array) { if (str.toString) { str = str.toString(); } else { str = sys.inspect(str); } } // output log messages to stderr sys.error('[' + t.toUpperCase() + ']: ' + m + str); }});
Fin.
‘ello World Node Style
#!/usr/bin/env nodevar YUI = require("../lib/node-yui3").YUI, Y = YUI();
Y.log('ello World');
‘ello World YUI Style
#!/usr/bin/env noderequire("../lib/node-yui3").YUI().log('ello World');
[~/examples (master)⚡] ➔ ./hello.js [INFO]: ello World
‘ello World YUI Style
Enabling YUI’s LoaderYUI.add(‘get’, function(Y) { // reads from file system or creates a httpClient // for remote data. Y.Get.script = function(s, cb) { var urls = Y.Array(s), url, i, l = urls.length; for (i=0; i<l; i++) { // doesn't need to be blocking, so don't block. YUI.include(url, function(err) { if (err) { Y.log(err, 'error', 'get'); } pass(cb); }); // replaced with process.compile so YUI doesn’t // need to be global // require.async(url, function (err, mod) { } };});
Enabling YUI’s Loader#!/usr/bin/env nodevar YUI = require('../lib/node-yui3').YUI;
YUI({ filter: 'debug'}).use('event-custom', function(Y) { Y.on('pwnd', function() { Y.log('Never gonna give you up, never gonna let you down...'); });
Y.fire('pwnd');});
Enabling YUI’s Loader[~/examples (master)⚡] ➔ ./loader.js [INFO]: (yui) Module requirements: event-custom[INFO]: (yui) Modules missing: event-custom, 1[INFO]: (yui) Fetching loader: yui_3_1_0_1_12711895820541, ./yui3/build/loader/loader-debug.js[INFO]: (get) URL: /lib/yui3/build/loader/loader-debug.js[INFO]: (yui) Module requirements: yui-base,yui-log,dump,oop,yui-later,event-custom[INFO]: (yui) Modules missing: dump,oop,event-custom, 3[INFO]: (yui) Using Loader[INFO]: (loader) attempting to load dump, ./yui3/build/[INFO]: (get) URL: /lib/yui3/build/dump/dump-debug.js[INFO]: (loader) attempting to load oop, ./yui3/build/[INFO]: (get) URL: /lib/yui3/build/oop/oop-debug.js[INFO]: (loader) attempting to load event-custom, ./yui3/build/[INFO]: (get) URL: /lib/yui3/build/event-custom/event-custom-debug.js[INFO]: (loader) loader finishing: success, yui_3_1_0_1_12711895820541, yui-base,yui-log,dump,oop,yui-later,event-custom[INFO]: (event) yui_3_1_0_1_12711895820544: pwnd->sub: yui_3_1_0_1_12711895820545[INFO]: Never gonna give you up, never gonna let you down...
Accessing Remote Data
#!/usr/bin/env node
var sys = require('sys'), YUI = require('../lib/node-yui3').YUI;
YUI().use('json', 'gallery-yql', function(Y) { var q = 'select * from github.user.info where (id = "apm")', o = new Y.yql(q); o.on('query', function(r) { //sys.inspects serializes objects to text sys.puts(sys.inspect(r)); });});
Using the YQL module from YUI Gallery
Accessing Remote Data[~/src/nodejs-yui3/examples (master)⚡] ➔ ./yql.js [INFO]: (get) URL: http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20github.user.info%20where%20(id%20%3D%20%22apm%22)&format=json&callback=YUI.yql.yui_3_1_0_1_12711910026086&env=http%3A%2F%2Fdatatables.org%2Falltables.env&
{ count: '1', created: '2010-04-13T08:36:47Z', lang: 'en-US', results: { user: { 'gravatar-id': 'fd657f26f290d8869901f0eaf3441b97' , name: 'Adam Moore' , login: 'apm' // -snip- } }}
DOMIt’s BOM.
What about the DOM?• YUI isn’t all about the DOM
• But YUI has many DOM-centric modules.
• Being able to use these components on the server opens up some interesting opportunities.
Rendering HTML - nodejs-dom
• Dav pulled together two open source projects to do it:
• jsdom - DOM level 1 support, written in JavaScript
• node-htmlparser - HTML parser written in JavaScript. Needed for innerHTML
• These are not nodeJS specific implementations
Rendering HTML - nodejs-dom
• DOM element creation and manipulation
• Selector API
• YUI’s Node API
Rendering HTML - nodejs-dom
#!/usr/bin/env nodevar sys = require('sys'), http = require('http'), url = require('url');var YUI = require("../lib/node-yui3").YUI;YUI().use('nodejs-dom', 'node', function(Y) { var document = Y.Browser.document, navigator = Y.Browser.navigator, window = Y.Browser.window; http.createServer(function (req, res) { var urlInfo = url.parse(req.url, true); YUI().use('nodejs-dom', 'node', function(Page) { document = Page.Browser.document; navigator = Page.Browser.navigator; window = Page.Browser.window; document.title = 'Calendar Test'; Page.one('body').addClass('yui-skin-sam'); var ln = document.createElement('link'); // ...
Rendering HTML
http://yuiloader.davglass.com/calendar/
Progressive Enhancement
• YUI 2 calendar control is loaded via the YUI 2 in 3 project
• The calendar control is fully rendered on the server.
• No script.
• Page and nav clicks are round trips.
• If script is enabled, we could enhance the links to pull only the data for each page and render on the client.
Multiple Response Types
http://yuiloader.davglass.com/template/
Multiple Response Types• First response will render the entire page.
• A client without script can request the fully rendered page.
• A script enabled client can request just the new content.
• A script enabled client with the source that is running on the server can request just the JSON data structure that creates the content.
• It’s the same code.
Other Uses
• Fast utility layer testing with YUI Test.
• Smoke tests for DOM-centric code.
• Could emulate some browser quirks.
• Validation Code
Summary• YUI 3’s design made it easy to get
running on Node.js
• JavaScript libraries are awesomely valuable on the server side
• Server side DOM shows crazy potential for a single code base
Resources• YUI: http://developer.yahoo.com/yui/
• Node.js: http://nodejs.org/
• nodejs-yui: http://github.com/davglass/nodejs-yui3/
• nodejs-yui3loader: http://github.com/davglass/nodejs-yui3loader
• Test Loader: http://yuiloader.davglass.com/demo/
• http://yuiloader.davglass.com/calendar/
Today presentation wasBrought to you by
the letters:J and S
And the fonts:Comic Sansmonofur
Tom Hughes-Croucher@sh1mmer
Slides, etc --> http://speakerrate.com/sh1mmer
Pls rate me. kthxbai.