Skip to content

Instantly share code, notes, and snippets.

@azproduction
Forked from 140bytes/LICENSE.txt
Created December 13, 2011 13:56
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save azproduction/1472202 to your computer and use it in GitHub Desktop.
Save azproduction/1472202 to your computer and use it in GitHub Desktop.
Lazy (and synchronous) Module Declaration in 126 bytes

LMD in 126 bytes

Big JavaScript application cause huge startup latency. A 1Mb of JavaScript initializes about ~600-3000ms! without touching any part of DOM. LMD is inspired by AMD and provides similar module interface. It evals module only when they are required.

  1. Modules are similar to AMD: there is a require, but no define (all defined on startup) nor exports (module function returns object)
  2. All modules are loaded at startup
  3. Each function-module is initialized (evaled) on demand

Original LMD: https://github.com/azproduction/lmd

Demo: http://jsfiddle.net/SKNHH/1/

function (
modules, // map of modules
main, // main module function
module, // tmp var
inited_modules // list of inited modules
) {
inited_modules = {}; // init
main(function require(moduleName) { // pass require fucntion only
module = modules[moduleName];
if (!inited_modules[moduleName]) { // lazy init
try {
if (module[0]=='(') { // its a lazy module
module = (0,this.eval)(module); // global eval it!
}
module = module(require); // lazy module init
} catch(e){}
}
inited_modules[moduleName] = 1; // mark module as inited
return modules[moduleName] = module; // return
});
}
function(a,b,c,d){d={},b(function e(b){c=a[b];if(!d[b])try{c[0]=="("&&(c=(0,eval)(c)),c=c(e)}catch(f){}return d[b]=1,a[b]=c})}
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2011 Mikhail Davydov
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
{
"name": "lmd",
"description": "Lazy (and synchronous) Module Declaration",
"keywords": [
"lmd",
"amd",
"module",
"synchronous"
]
}
<!DOCTYPE html>
<title>Lmd</title>
<div>Expected value: <b>Hello World, %username%!</b></div>
<div>Actual value: <b id="ret"></b></div>
<script>
var mods = {
"i18n": {"hello": "Hello", "world": "World"},
"lazy_module_render": "(function (require) {var i18n = require('i18n');return {'hw': function(name){return i18n.hello + ' ' + i18n.world + ', ' + name + '!'}}})",
"module_printer": function printer(require) {
return function (text) {
document.getElementById("ret").innerHTML = text;
}
}
};
var main = function (require) {
var render = require("lazy_module_render"),
print = require("module_printer");
print(render.hw('%username%'));
};
(function(a,b,c,d){d={},b(function e(b){c=a[b];if(!d[b])try{c[0]=="("&&(c=(0,eval)(c)),c=c(e)}catch(f){}return d[b]=1,a[b]=c})})
(mods, main);
</script>
@atk
Copy link

atk commented Dec 13, 2011

I hardly see any real world application for that. Wouldn't it be much better for the page performance to load the required modules afterwards in an asynchronous fashion?

@azproduction
Copy link
Author

I like AMD (it reduces startup latency, too) but,

  1. Few modules is a few requests: +headers, +requests, +time... often download time > parse/init time.
  2. Its often hard to balance the number of modules: number of requests/modules vs parse/init time vs module size.
  3. Separation of the application into multiple parts reduces its fault tolerance (if request aborts application have to resend it, and user have to wait...)
  4. Imo monolithic module > separeted modules for client side apps. My application caches monolithic module in localStorage (yeah rly!)

In addition to AMD, LMD is inspired by:
http://www.nczonline.net/blog/2011/02/14/separating-javascript-download-and-execution/
http://googlecode.blogspot.com/2009/09/gmail-for-mobile-html5-series-reducing.html
Google Dart declarative modules

@nikola
Copy link

nikola commented Dec 13, 2011

The try/catch block severely degrades performance, so I doubt that this approach actually improves performance. Do you have any numbers at hand?

@azproduction
Copy link
Author

"try/catch degrades performance" no doubt - its a 140bytes version.

Sencha Ext JS 4 full version, packed - (1Mb of JS localhosted)
iOS Safari 4 - load time 300ms, init time 3000ms
Firefox 8 - load time 32ms, init time 500-600

Sencha Ext JS 4 full version, packed, JSONed - load time same, 10-30ms init time

@atk
Copy link

atk commented Dec 14, 2011

Thanks for clarification. Maybe it's just a personal dislike, but I find that any javascript > 100kb in a page is usually a sure sign for a lot of unneccessary code.

@azproduction
Copy link
Author

Depend on application scale

  • mail.yandex.com (mail tab): 470Kb of pure js, without xslt templates
  • mail.yandex.com (chat): 164Kb js+templates
  • gmail.com inbox page: a few(10-15) small js files loaded via xhr ~700Kb
  • twitter.com: one js file 240Kb

@nikola
Copy link

nikola commented Dec 14, 2011

Well, you had written in the rationale about "startup latency" and that your implementation aims to reduce it. Hence my comment that I doubt that your approach actually solves the issue.

Also, please note that the unconditional try/catch will obscure any errors in the loaded modules. I'm thinking about modules that usually raise errors when a selftest fails etc.

@azproduction
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment