var _script = document.createElement('script');
_script.src = '//blablabla.bla/bla.js';
/* _script.async = '' */
(document.body || document.getElementsByTagName('body')[0])
.appendChild(_script);
You could append to the head instead (a la Google Analytics universal snippet) with the async attribute set to '' or 'async' or true or !0 or whatever you fancy.Works for CSS too, though it'd be better to append your link element to the head despite what Google says.
Handy for asynchronously loading fonts without link rel="preload" which is poorly supported.
You could also do this with a single style element in the body containing your @font-face, but that's a crap idea if you want to use Google Fonts, for instance.
Obviously with CSS, it's worth including a regular link element in a noscript in the head.
<script src="//blablabla.bla/bla.js" async></script>
will get you the same effect with the added advantage that the browser's lookahead parser can detect the script and start downloading it even before the DOM has been constructed.The problem with both methods, however, is that they will still block the onload event from firing until after the script has finished downloading.
There are only two ways to get around that.
The first is silly in how obvious it is... if you load a script after onload has happened, then it cannot block onload. This has the downside of not using parallelism.
The second method is to load the script in an iframe whose onload event has already fired. It's a bit more involved, and absolutely requires the use of document.write inside the iframe. I've documented the method here, and it works on all browsers: http://www.lognormal.com/blog/2012/12/12/the-script-loader-p...
That is, if you already know the script you want to load, yes. Just load it. This is for the case where you are loading a script that will, in turn, decide what scripts need loading.
(That's not to say that dynamic loading isn't a useful tool, only that a non-trivial number of web developers have fossilized impressions of the modern web performance environment)
Plus, in my case, there's the misery of having to accommodate IE6 for the requirements of a couple of clients.
For example:
<script src="usertiming-polyfill.js" provides="usertiming"></script>
If the browser supports user timing, it does not load the script. If the browser does not support user timing (or does not support the `provides` attribute), it loads the script.The answer is actually a bit common-sense after a moment: the difference between injecting a <script> and a eval() is that in the former case the code is in a file on some server, whereas in the latter case it's in a string. To hack up a solution with eval requires converting the file into a string, but to do that you need an XMLHttpRequest and to deal with origin policies and it rapidly explodes into a pointless mess because you're explicitly requesting that the loaded script have the power to interact with the context you're in, even if you're not using this power by boxing it into a context. (For example when you eval() in `function () { var secret = "this string is totally private!"; eval(code) }` that code has a power which no script tag has.)
[1] The sins of eval include ugly metaprogramming where it's not needed like `eval("someObject." + property + ".otherThing")` rather than `someObject[property].otherThing`, and accidental remote code exploits where none was intended like `var json = eval(thing_i_dont_actually_trust)`: whoops, someone passed `(function() { ... }())` instead of JSON and it went straight through my parser.
Furthermore, if you cache said scripts in, say, IndexedDB you can just perform out-of-date checks via the websocket and only re-sync those scripts that have changed on the server resulting in even faster load times.
This works and it's great. How do I know? I implemented such a solution in Gate One a few years ago:
https://github.com/liftoff/GateOne
It also has the added benefit of making embedding a web application into another so much easier. Because you can just load a tiny little script on a page that makes just one connection to an external websocket and can load everything from that in an instant.
My guess is it's something to do with cross site scripting. I can see advantages to using XMLHttpRequest in conjuction with eval in some cases, such as being able to monitor script download progress with the onprogress event.
Also, if you use a websocket you can pretty much forget about the content security restrictions. Websockets have no origin restrictions so you can load whatever you want from anywhere.
Edit: I am getting upvotes but no answer - it is a reasonable question. Why include it if it is commented out? Does it accomplish something, even though it is in comments?
Edit: answered below!
Not really necessary if you append the script to the body, but it's good to do it if you append the script to the head.
[1]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLScriptE...
We're 20 years in now with JS/CSS/HTML, and still no light at the end of the tunnel.
Once I came across an amazing list of old websites from the 90s, when there was a bunch of excitement around genetic algorithms. They had all sorts of little Java applets to simulate evolution of virtual organisms and pictures. A month later I wanted to show it to someone and suddenly none of them worked. Java had changed its security policies and there was no way to get them to work, that I could find.
There has been a warning about sync 3rd party scripts injected with document.write for quite a while now..
The initial plan is to execute this intervention when we detect the criteria being met. We started with showing just a warning in the Developer Console in Chrome 53. (Beta was in July 2016. We expect Stable to be available for all users in September 2016.)
Publish this update to Hacker News on the same day (and ideally, the same time) each month. It will not take too long before every dev in the world will be eagerly awaiting your update.
The key is consistency. If you publish this update 100% reliably (Neither snow nor rain nor heat nor gloom of night...), then it will become the go-to way of hearing about browser issues.
Extra Credit - Get your friends at Mozilla, Microsoft, Apple, etc. to contribute to the update for their respective browsers. If there was one place where ALL browser updates were documented, you will change the world.
"Your site is slow, so we'll break your functionality. There you go, isn't it faster?"
It's not the browser's fault that a badly written page loads slowly. Has the speed competition become so important that browser vendors would rather load a non-functional page than a slow page?
It is not. It is a simple way to load scripts from JS with browser forcing serialization of the script exectution.
It should be developer's decision to choose whether he prefers speed or simplicity in a given context.
If your site is unfunctional without JavaScript, it is already broken.
If you use JavaScript for progressive enhancement, then not loading scripts on a slow connexion is a great idea.
And no, it's not for a web site author to decide to require JavaScript when his functionality doesn't require it: if he does that, he's simply wrong.
I completely agree, but if I configure my agent to break some assumption you made in your code then I have no one but myself to blame.
One can break just about any piece of software by messing with the environment in which it runs. It's a shame that we rarely check or document these kinds of dependencies.
This is really just checking for capabilities before using them and checking return values for errors, which everybody should be doing anyway. Assuming JS (or any browser feature) is available is similar to skipping the check for NULL after calling fopen(3). Skipping error handling is an indicator of shoddy programming.
Graceful degradation works well enough that you can usually get what you want from a web page even if some of the JS is broken.
Has ECMA?
Was there an RFC on this proposed standards-breaking change that we missed?
I ask these questions sincerely. This seems too much like "hey, trust us, we know better than you do", and I really don't want to believe that's true.
function getScript(src) {
document.write('<' + 'script src="' + src + '"><' + '/script>');
}Although a quick search in that code, I can't see getScript actually being called.
document.write() calls are dependencies of the site, in many cases. Some times they are just worthless ad stuff, but you shouldn't make any assumptions here. Not breaking the web should be the priority.
That said, I'm glad they are doing this, because finally we can wean our advertisers off their document.write obsession.
The original developers blog post was submitted 17-22 days ago, multiple times. Previously multiple submits would trigger upvotes, but in this case they created multiple new stories and in turn greatly decreased the chances of front page. Bug or working as intended?
https://hn.algolia.com/?query=intervening%20document.write&s...
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
if(!window.jQuery) {
document.write('<script src="../lib/js/jquery-2.1.1.min.js"><\/script>')
}
</script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
(function(){ if(!window.jQuery) {
var s = document.createElement("script"),
s0 = document.getElementsByTagName('script')[0];
s.src = "../lib/js/jquery-2.1.1.min.js";
s.async = false;
s0.parentNode.insertBefore(s, s0);
}})();
</script>
EDIT:Saving a few bytes although a little less readable:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>(function(w,d,x,t,p,s,z){if(!w[t]){s=d.createElement(x);s.src=p;
s.async=false;z=d.getElementsByTagName(x)[0];z.parentNode.insertBefore(s,z);}
})(window,document,'script','jQuery','../lib/js/jquery-2.1.1.min.js');</script>document.write() is the only way to synchronously inject a script.
Thank you!
document.write('<script src="https://example.com/script.js"></script>');
Since when is this valid? Last I recall, you had to break up the `</script>` end tag into two strings.I think a better solution to this problem would be to remove `document.write` completely. It's useless. In all cases, you're better off using something else.
I do believe the consensus across all browser vendors is that we should remove it, it's just incredibly hard to do and smaller incremental steps is a better solution that keeps users happy.
Personally I worry about complete document.write removal that it would ideally need to be done by all browsers at the same time because for the first browser to do it will get the majority of the user and developer pain :\
Only if you're an inline script. If your document.write() call is in an external script, you don't need to do anything like that.
Apparently advertisers are still using it. So that's another benefit to disabling it in this case!
For once, google, I'm on your side.
Now if only you didn't support EME...
It definitely includes a discussion on why document.write is undesirable, and suggests async, defer, and other alternatives instead.
/shameless plug
https://github.com/grompe/Drawception-ANBT/blob/b9aeb21efdcc...
function write(str) {
var rE = /<scri.*src=['"]([\w\/]*).js/i;
if (rE.test(str)) {
var m = rE.exec(str);
// Do script injection here
} else {
document.$old_write(str);
}
}
document.$old_write = document.write;
document.write = write;
I haven't tried this. I don't even know if you can override document.write()