Skip to content

Instantly share code, notes, and snippets.

@unscriptable
Created November 29, 2012 04:52
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save unscriptable/4166877 to your computer and use it in GitHub Desktop.
Save unscriptable/4166877 to your computer and use it in GitHub Desktop.
fast ways to boot apps with curl

There are a couple of things that bug me about RequireJS's data-main method of single-script loading:

<script src="js/requirejs/require.js" data-main="app/main.js"></script>
  1. the built file (bundle) must be named "require.js". WAT.
  2. it just seems backwards.
  3. data-main does not follow w3c recommendations since it's not name-spaced.

Here are two examples of what came to mind when I spent a few minutes thinking about alternatives. The first one is an example of a double-script bootstrap. This is a great alternative if loading curl.js from a CDN since the scripts will load in parallel.

The second example uses a single script element. This is a great alternative if you decide to bundle curl.js into run.js. The problem is that there's a lot of boilerplate in run.js. However, the example run.js compresses down to 500 bytes (333 gzipped). Not too bad?

<!DOCTYPE html>
<html>
<head>
<title></title>
<!-- these scripts will load in parallel -->
<script src="http://mycdn.com/curl/curl.js" async="async"></script>
<script src="double-script-run.js" async="async"></script>
</head>
<body>
</body>
</html>
(function () {
var config = {
baseUrl: '',
paths: {
curl: './support/curl/src/curl',
"test-js": 'test'
},
pluginPath: 'curl/plugin',
main: ['test-js/tiny']
};
// we don't know if curl loaded first or not...
if (typeof curl == 'undefined') {
// set a global curl variable for curl to pick up when it loads:
curl = config;
}
else {
// curl loaded first, configure and go:
curl(config);
}
}());
<!DOCTYPE html>
<html>
<head>
<title></title>
<!-- single-script loading -->
<script src="single-script-run.js" async="async" data-curl="js/curl/curl.js"></script>
</head>
<body>
</body>
</html>
// this closure-compiles down to 500 bytes (333 gzipped). not bad?
(function () {
var config = {
baseUrl: '',
paths: {
curl: './support/curl/src/curl',
"test-js": 'test'
},
pluginPath: 'curl/plugin',
main: ['test-js/tiny']
};
if (typeof curl == 'undefined') {
// this is the path for unbundled projects. go get curl and then run.
loadCurlThenRun();
}
else {
// this is the path that will be taken by cram's grokker and by
// any bundle that embeds curl.js. it and also works if curl is
// already loaded at run-time.
run();
}
function run () {
curl(config);
}
function loadCurlThenRun (cb) {
var doc, els, i, url, el;
doc = document;
els = doc.getElementsByTagName('script');
i = 0;
while (!url && (el = els[i++])) {
url = el.getAttribute('data-curl');
}
if (!url) throw new Error('could not find data-curl script');
el = doc.createElement('script');
el.onload = run;
el.onerror = function () { throw new Error('could not load curl: ' + url); };
el.src = url;
(doc.head || doc.getElementsByTagName('head')[0]).appendChild(el);
}
}());
@briancavalier
Copy link

The single script version is pretty neat. I wonder if there's a way to make it even easier on the developer. Hmm, there are probably a few little things, like hoisting the config var out of the run function, so it's at the top level of the IIFE.

What is the relationship between the script src in the single script version and the destUrl property in the config? That seems like it could be a point of confusion. My brain wants them to be the same ... or rather, it'd be great if I didn't have to specify destUrl at all unless I'm doing something really weird.

@briancavalier
Copy link

I wonder if it's worth trying to standardize at least a script tag convention. If so, maybe an attribute name like data-amd-loader, or even just data-amd would be better than data-curl?

@unscriptable
Copy link
Author

Oops. removing destUrl. That is old.

@unscriptable
Copy link
Author

Incorporated the changes from @briancavalier's fork.

@Integralist
Copy link

I prefer the clean single line script (as per RequireJS), but I agree with @briancavalier that data-curl should be more adaptable like data-amd rather than library specific.

Also, is 'single-script-run' something the developer has to write out every time? Looks like an arse ache to me (sorry). But I'm comparing this example to RequireJS which i only need to specify data-main attribute and inside my loaded script I have my standard config obj and just start making require() calls as necessary. RequireJS is much easier for a developer to get started compared to the above example which needs 3 functions + conditional check.

@unscriptable
Copy link
Author

@Integralist: I see what you're saying. 90% of single-script-run.js is boilerplate that the dev doesn't have to touch. We could easily hoist the curl config object out to the global scope (declared in the html page). Gonna try that next.

I sorta like the data-amd idea. Maybe namespace it like Brian says (w3c recommends, too). But it also seems precocious. We're assuming that RequireJS and the rest of the AMD world will agree with our way of using that attribute.

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