An Introduction to Inject

Post on 13-Jan-2015

3.168 views 2 download

description

Given at the Front End Developers United Meetup in Mountain View, CA

Transcript of An Introduction to Inject

©2012 LinkedIn Corporation. All Rights Reserved.

INJECTJakob Heuser – maintainer@InjectJS

©2012 LinkedIn Corporation. All Rights Reserved. 2

©2012 LinkedIn Corporation. All Rights Reserved. 3

©2012 LinkedIn Corporation. All Rights Reserved.

©2012 LinkedIn Corporation. All Rights Reserved.

©2012 LinkedIn Corporation. All Rights Reserved.

©2012 LinkedIn Corporation. All Rights Reserved.

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 8

LinkedIn’s Web Development

6+ Vertical Engineering Groups 80+ Web Developers (horizontal) linkedin.com

– Main Site– Tools for Recruiters– Mobile Products

Performance is a shared goal in the frontend

©2012 LinkedIn Corporation. All Rights Reserved.

Performance has Come a Long Way

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 10

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 11

In The Beginning

<script type="text/javascript" src="jquery.js"></script> <script type="text/javascript" src="shared.js"></script> <script type="text/javascript" src="app.js"></script></body></html>

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 12

In The Beginning

Blocking (less painful in the footer) Very manual May not have needed everything you were loading

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 13

Async loading

var load = ['jquery.js', 'shared.js', 'app.js'];var head = document.getElementById('head')[0];var scr;for (var i = 0, len = load.length; i < len; i++) { scr = document.createElement('script'); scr.type = 'text/javascript'; scr.src = load[i]; head.appendChild(scr);}

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 14

Async Loader Libraries

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 15

Things got better

$LAB .script("jquery.js") .script("shared.js").wait() .script("app.js").wait(function() { // all code loaded });

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 16

Framework natives

// in your app code...YUI({ modules: { 'shared': { fullpath: 'http://example.com/js/shared.js', requires: ['get', 'node'] } }}).use('shared', function(Y) { // In YUI, "Y" is decorated with functionality});

// in shared.js...YUI.add('shared', function(Y) { // add function to the "Y" object});

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 17

Framework natives

// note, this is Dojo 1.7// Dojo 1.8 uses AMD and we're getting to that!dojo.require('shared.js');dojo.ready(function() { // custom code});

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 18

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 19

And We Brought it to the Browser

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 20

Browser Packaging Solutions

Put together discrete pieces into one payload Support the asynchronous require() method

– I want “X”, so… var x = require(“X”); Excellent single page application solutions

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 21

The CommonJS Standard

var myVar = require(“string”)– Returns the “string” module’s items assigned to the module’s “exports”

variable– Require is a global variable (always available)

require.ensure(dependencies, function() {})– The “Asynchronous/A” Draft– Download all of the dependencies (an array)– Then run the callback function (second param)– Available off the require function

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 22

Asynchronous Module Definition

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 23

The AMD Standard

define(moduleId, dependencies, function() {})– Name this download “moduleId” [optional]– Before running, download & execute dependencies (array, [optional])– Then run the callback function (“dependencies” are arguments)– If you depend on “require” or “exports”, they will work like their

CommonJS counterparts

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 24

Harmony Modules in ECMAScript!

Nested virtualization State isolation Dynamic loading Global namespace isolation Compilation hooks http://wiki.ecmascript.org/doku

.php?id=harmony:modules_examples

Some day

©2012 LinkedIn Corporation. All Rights Reserved.

Let’s Talk INJECT

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 26

In A Slide

Inject is a Dependency Management Framework for the browser Supports CommonJS and AMD specifications Works cross-domain (CDNs) Does not require precompilation in order to function

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 27

For Libraries That Aren’t Inject

“AMD” examples still work for browsers Telling the framework where files are differs The “run” command will be slightly different

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 28

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 29

Our Files

inject.js – the main inject file (that’s all we need for now)

program_cjs.js – load a “math” library, and add 2 + 3 program_amd.js – same thing, with AMD syntax

math_cjs.js – exposes an “add” function for adding numbers math_amd.js – same thing, with AMD syntax

©2012 LinkedIn Corporation. All Rights Reserved.

1. Get Inject

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 31

http://www.injectjs.com

Download Inject (Big Yellow Button) Documentation and Howtos Source code Mailing List

©2012 LinkedIn Corporation. All Rights Reserved.

2. Build Site Structure

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 33

Directory Structure

<site_root>/js– inject.js– /modules/

program_amd.js program_cjs.js math_amd.js math_cjs.js

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 34

program_*.js

// program_cjs.jsvar math = require('math_cjs');alert('math_cjs:' + math.add(2, 3));

// program_amd.jsdefine(['math_amd'], function(math) { alert('math_amd:’ + math.add(2, 3));});

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 35

math_*.js

// math_cjs.jsexports.add = function(a, b) { return a + b;};

// math_amd.jsdefine(function() { return { add: function(a, b) { return a + b; } }});

©2012 LinkedIn Corporation. All Rights Reserved.

3. Add Inject, Call Program

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 37

Inject’s Script Tag and Inject.run()

<head> <script src="/js/inject.js"></script></head><body> <!-- ... --> <script type="text/javascript"> Inject.setModuleRoot('/js/modules'); // run CommonJS Code... require.run('program_cjs'); // math_cjs: 5 // ... or AMD Code require.run('program_amd'); // math_amd: 5 </script></body>

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 38

©2012 LinkedIn Corporation. All Rights Reserved.

INJECT API

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 40

Inject.setModuleRoot Where do I find files?

setModuleRoot(String)– String: a URL path where files can be found.

/js/modules http://example.com/js/modules

If using a CDN (Advanced) use a full URL

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 41

Inject.setExpires How long to store files?

setExpires(integer)– Integer: how long in minutes to preserve the cache

Built in localStorage module to improve caching Older items from Inject are automatically dropped to make room Inject.setExpires(0) can create a “dev” environment

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 42

Inject.reset The ultimate escape hatch

Clears Inject’s localStorage Removes all in-JS memory of currently loaded items Acts as if it hasn’t seen a module yet

©2012 LinkedIn Corporation. All Rights Reserved.

INJECT Advanced API

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 44

Inject.addRule Change the Behavior of a Module

addRule(Regex|String, Integer?, Object)– Regex|String: if the module matches the regular expression / string,

any alterations in Object will be applied– Integer (optional): allows you to dynamically reorder the rules by

assigning them weights– Object: a set of alterations to perform

“Lock” a module’s identifier to a URL Turn on/off the automatic attachment of “.js” to module IDs when

converted to a URL Rewrite the code before it is executed

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 45

addRule Lock a Module’s Path

Inject.addRule('module/path', { path: 'http://example.com/external/module.js'});

Inject.addRule('module/anotherPath', { path: ’/local_directory/library/module.js'});

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 46

addRule Turn on/off the “.js” Suffix

// module/path.jsInject.addRule('module/path', { useSuffix: true});

// module/pathInject.addRule('module/path', { useSuffix: false});

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 47

addRule Alter the File (ie non AMD/CJS Code)

// <= 0.4.0Inject.addRule(/^jquery$/, { path: '/path/to/jquery.js', useSuffix: false, pointcuts: { after: function () { module.exports = jQuery.noConflict(); } }});

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 48

addRule Alter the File (ie non AMD/CJS Code)

// >= 0.4.1Inject.addRule(/^jquery$/, { path: '/path/to/jquery.js', useSuffix: false, pointcuts: { afterFetch: function (next, text) { next(null, [ text, 'module.exports = jQuery.noConflict();' ].join('\n')); } }});

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 49

Inject.plugin Extend Functionality to non-JS Things

plugin(String, Object, Object?)– String: an identifier for the plugin. Automatically creates an addRule()

that matches modules beginning with “<string>!”– Object: this is the same object used in addRule() to modify a module– Object (optional): any functions placed in the 3rd parameter are made

available under Inject.plugins.<string>

An easy interface for addRule to handle non-JS files Inject comes with support for CSS, JSON, and Plain Text

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 50

plugin The “text” Plugin

(function () { Inject.plugin('text’, { useSuffix: false, path: function (path) { return path.replace(/^text!\s*/, ''); }, pointcuts: { afterFetch: function (next, text) { next(null, ['', 'var text = "', encodeURIComponent(text), '";', 'module.setExports(decodeURIComponent(text));', ''].join('') ); } } }, {});})();

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 51

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 52

Roadmap

0.4.1 Final– Robust plugin support– afterFetch non-blocking pointcuts

0.4.2 Librarian Release– Internal library upgrades: Link, Fiber, EasyXDM– Standardize testing framework

0.4.x Planned– localStorage on CDN side– Reduced code base (EasyXDM for IE7 only)– Coffeescript Plugin– Npm “install”-like functionality, global modules

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved.

INJECThttps://github.com/linkedin/inject

LINKEDIN UED©2012 LinkedIn Corporation. All Rights Reserved. 54

Useful Links

http://www.stevesouders.com/blog/2009/04/27/loading-scripts-without-blocking/

http://dojotoolkit.org/documentation/tutorials/1.8/modern_dojo/ http://www.injectjs.com http://requirejs.org https://github.com/amdjs/amdjs-api/wiki/AMD http://www.commonjs.org