Hidden divs for "lazy javascript" loading? Possible security/other issues?
I'm curious about people's opinion's and thoughts about this situation. The reason I'd like to lazy load javascript is because of performance. Loading javascript at the end of the body reduces the browser blocking and ends up with much faster page loads.
But there is some automation I'm using to generate the html (django specifically). This automation has the convenience of allowing forms to be built with "Widgets" that output content it needs to render the entire widget (extra javascript, css, ...). The problem is that the widget wants to output javascript immediately into the middle of the document, but I want to ensure all javascript loads at the end of the body.
When the following widget is added to a form, you can see it renders some <script>...</script>
tags:
class AutoCompleteTagInput(forms.TextInput):
class Media:
css = {
'all': ('css/jquery.autocomplete.css', )
} 开发者_如何学编程
js = (
'js/jquery.bgiframe.js',
'js/jquery.ajaxQueue.js',
'js/jquery.autocomplete.js',
)
def render(self, name, value, attrs=None):
output = super(AutoCompleteTagInput, self).render(name, value, attrs)
page_tags = Tag.objects.usage_for_model(DataSet)
tag_list = simplejson.dumps([tag.name for tag in page_tags],
ensure_ascii=False)
return mark_safe(u'''<script type="text/javascript">
jQuery("#id_%s").autocomplete(%s, {
width: 150,
max: 10,
highlight: false,
scroll: true,
scrollHeight: 100,
matchContains: true,
autoFill: true
});
</script>''' % (name, tag_list,)) + output
What I'm proposing is that if someone uses a <div class=".lazy-js">...</div>
with some css (.lazy-js { display: none; }
) and some javascript (jQuery('.lazy-js').each(function(index) { eval(jQuery(this).text()); }
), you can effectively force all javascript to load at the end of page load:
class AutoCompleteTagInput(forms.TextInput):
class Media:
css = {
'all': ('css/jquery.autocomplete.css', )
}
js = (
'js/jquery.bgiframe.js',
'js/jquery.ajaxQueue.js',
'js/jquery.autocomplete.js',
)
def render(self, name, value, attrs=None):
output = super(AutoCompleteTagInput, self).render(name, value, attrs)
page_tags = Tag.objects.usage_for_model(DataSet)
tag_list = simplejson.dumps([tag.name for tag in page_tags],
ensure_ascii=False)
return mark_safe(u'''<div class="lazy-js">
jQuery("#id_%s").autocomplete(%s, {
width: 150,
max: 10,
highlight: false,
scroll: true,
scrollHeight: 100,
matchContains: true,
autoFill: true
});
</div>''' % (name, tag_list,)) + output
Nevermind all the details of my specific implementation (the specific media involved), I'm looking for a consensus on whether the method of using lazy-loaded javascript through hidden a hidden tags can pose issues whether security or other related?
One of the most convenient parts about this is that it follows the DRY principle rather well IMO because you don't need to hack up a specific lazy-load for each instance in the page. It just "works".
UPDATE: I'm not sure if django has the ability to queue things (via fancy template inheritance or something?) to be output just before the end of the </body>
?
I would prefer a tool that lets me "append" content to the output stream (or) append it to a buffer, that will be outputted at the end of the page, just before the </body>
tag.
I'm not sure which commercial tools support this (or does django?) but this is how I've built my frameworks.
As for your question about security/other issues... the script will process whenever it is read (unless you output a script tag with the defer
attribute (in IE/newer browsers)) thus unless it is physically moved, it doesn't change the behavior or make it "lazy".
Security wise, pulling content out of the script tag, and calling eval()
on it opens you up to the possibility of something executing that you were not planning on. (unlikely, but possible)
The problem is that the widget wants to output javascript immediately into the middle of the document, but I want to ensure all javascript loads at the end of the body.
Then I would not use that widget. Dynamically supplied client-side script from the client side is a disaster that will break security without you or your user being any wiser. How would you know if that code were compromised, for example?
精彩评论