-
-
Save branneman/37865bcfc5d102c2be6c to your computer and use it in GitHub Desktop.
<!doctype html> | |
<html> | |
<head> | |
... | |
<script> | |
(function(d){ | |
if (!('querySelector' in d && 'addEventListener' in window)) return; | |
d.documentElement.className += ' has-js'; | |
d.addEventListener('DOMContentLoaded', function() { | |
var s = d.createElement('script'); | |
s.setAttribute('src', '/static/js/vendor/requirejs/require.js'); | |
s.setAttribute('data-main', '/static/js/main'); | |
d.body.appendChild(s); | |
}); | |
}(document)); | |
</script> | |
</head> | |
<body> | |
... | |
</body> | |
</html> |
(function(){ | |
require.config({ | |
map: { | |
'*': { | |
classList: 'polyfills/classList', | |
conditioner: 'vendor/conditionerjs/conditioner' | |
} | |
} | |
}); | |
var polyfills = []; | |
if (!('classList' in document.documentElement)) { | |
polyfills.push('classList'); | |
} | |
// ... more feature detections ... | |
require(['conditioner'].concat(polyfills), function(conditioner) { | |
conditioner.init(); | |
}); | |
}()); |
Sorry to go OT a bit, but just to chip in re: your last point: have you seen https://polyfill.io ?
It's "Polyfill As A Service" and I am lovin' the idea: you simply link to 1 script endpoint and the UA automagically receives appropriate polyfills. You can—of course—also specify features explicitly:https://cdn.polyfill.io/v1/docs/features/
Anyway, off-topic for your use-case but my feeling is that this could be an elegant way to deal with polyfills…
I'm going with a has-js class instead of a no-js class, because Progressive Enhancement.
Interesting, I'm going to think on this some more.
a simple x.className += ' has-js' will have to do then.
It might be simple, but it's probably fast as well.
Also, right now I can call insertBefore on the current script at the end of the body. What do you propose for inserting the script tag at the end of the body?
I'd say document.body.appendChild()
I copied it from the Google Analytics code, but I'm unsure why they add it as well.
They have added it because Google Analytics is embedded in the head and they use a 'queue' object for all the tracking stuff (it works before the script is loaded).
I don't see any other way, I want them to be conditionally loaded, every browser gets different polyfills.
I would find a common set of functionality and merge those. Or, you could only polyfill once a module loads that requires certain polyfills. Certainly for conditional modules that would be preferable.
Updated! Thanks for the response so far :)
Looks nice, I've taken a stab at shortening the mustard cut a bit. And have implemented the bouncer pattern.
(function(){
var d = document;
if (!('querySelector' in d && 'addEventListener' in window)) {return;}
d.documentElement.className += ' has-js';
d.addEventListener('DOMContentLoaded', function() {
var s = d.createElement('script');
s.setAttribute('src', '/static/js/vendor/requirejs/require.js');
s.setAttribute('data-main', '/static/js/main');
d.body.appendChild(s);
});
}());
Also the new module enabled
property in Conditioner might be interesting in relation to the polyfills. It's a micro mustard cut.
To prevent polluting the global scope with the _polyfills
variable you could wrap the entire main.js
in a self executing function or maybe even make a separate polyfills module.
Manual minification, I love it. We can do even better:
(function(d){
// ...
}(document));
Also, would it be possible to shorten both the setAttribute
calls? I know s.src =
will work, but will this work for the data attribute as well?
var s = d.createElement('script');
s.src = '/static/js/vendor/requirejs/require.js';
s['data-main'] = '/static/js/main';
Or we could go crazy and save more bytes:
(function(d, f){
s[f]('src', '/static/js/vendor/requirejs/require.js');
s[f]('data-main', '/static/js/main');
}(document, 'setAttribute'));
On second thought, let's stop here ;) We should leave minification to a minifier.
Anyway, I've updated the gist with the sane changes.
Haha, brilliant! :-) Excellent plan to leave minifying to the pros ;)
I'm going with a
has-js
class instead of ano-js
class, because Progressive Enhancement.This is possible, however since I'm loading the polyfills in my
main.js
, this means I can't useclassList
anymore, a simplex.className += ' has-js'
will have to do then.Also, right now I can call
insertBefore
on the current script at the end of the<body>
. What do you propose for inserting the<script>
tag at the end of the body?I copied it from the Google Analytics code, but I'm unsure why they add it as well.
Sure, why not ;)
You're right. I've removed the
deps
variable, and underscored thepolyfills
variable to indicate it's private.I don't see any other way, I want them to be conditionally loaded, every browser gets different polyfills.