隐藏的div为“懒惰的javascript”加载?可能的安全/其他问题?

时间:2010-05-04 16:11:32

标签: javascript security django-forms lazy-evaluation

我很好奇人们对这种情况的看法和想法。我之所以懒加载javascript是因为性能。在正文末尾加载javascript可以减少浏览器阻塞,最终加快页面加载速度。

但我正在使用一些自动生成html(具体是django)。这种自动化方便了允许使用“Widgets”构建表单,“Widgets”输出渲染整个小部件所需的内容(额外的javascript,css,...)。问题是小部件想要立即将javascript输出到文档的中间,但我想确保在正文末尾加载所有javascript。

将以下小部件添加到表单后,您可以看到它呈现了一些<script>...</script>标记:

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

我建议的是,如果有人使用<div class=".lazy-js">...</div>一些css(.lazy-js { display: none; })和一些javascript(jQuery('.lazy-js').each(function(index) { eval(jQuery(this).text()); }),则可以有效地强制所有javascript加载到页面加载结束:

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

没关系我具体实现的所有细节(涉及的具体媒体),我正在寻找一个共识,即通过隐藏隐藏标签使用延迟加载的javascript的方法是否会造成安全性或其他相关的问题?< / p>

关于这一点最方便的部分之一是它遵循DRY原则而不是IMO,因为您不需要为页面中的每个实例破解特定的延迟加载。它只是“有效”。

UPDATE :我不确定django是否能够在</body>结束之前输出事物(通过花哨的模板继承或什么?)? / p>

2 个答案:

答案 0 :(得分:1)

我更喜欢一种工具,它允许我将“附加”内容添加到输出流(),将其附加到缓冲区,该缓冲区将在页面末尾输出,就在{ {1}}标记。

我不确定哪些商业工具支持这个(或django?)但这就是我构建框架的方式。

至于你关于安全性/其他问题的问题......脚本将在读取时进行处理(除非你输出带有</body>属性的脚本标签(在IE /更新的浏览器中)),除非它是身体感动,它不会改变行为或使其“懒惰”。

安全性明智,将内容从脚本标记中拉出来,并在其上调用defer会让您有可能执行您未计划执行的操作。 (不太可能,但可能)

答案 1 :(得分:0)

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.

然后我不会使用那个小部件。从客户端动态提供的客户端脚本是一种灾难,如果您或您的用户没有任何更明智的话,它将破坏安全性。例如,你怎么知道代码是否被泄露?