【问题标题】:Django tag for compressing in-page javascript用于压缩页内 javascript 的 Django 标记
【发布时间】:2011-01-12 03:45:04
【问题描述】:

Django-compress 很棒,但它不提供任何用于压缩页内 javascript 的标签。

有一些解决方案吗?即使删除换行符(并在需要的地方添加“;”)也会很棒。

【问题讨论】:

    标签: javascript django-templates


    【解决方案1】:

    好的,我自己使用 JSCompressor 由 Michael Palmer (http://code.activestate.com/recipes/496882/) 完成的

    代码如下:

    from django import template
    
    def do_foldjs(parser, token):
        nodelist = parser.parse(('endfoldjs',))
        parser.delete_first_token()
        return FoldJSNode(nodelist)
    
    class FoldJSNode(template.Node):
        def __init__(self, nodelist):
            self.nodelist = nodelist
        def render(self, context):
            output = self.nodelist.render(context)
    
            try:
                compressor = JSCompressor(compressionLevel=2)
                return compressor.compress(output)
            except:
                return output
    
    
    import re
    
    
    
    class JSCompressor(object):
    
        def __init__(self, compressionLevel=2, measureCompression=False):
            '''
            compressionLevel:
            0 - no compression, script returned unchanged. For debugging only -
                try if you suspect that compression compromises your script
            1 - Strip comments and empty lines, don't change line breaks and indentation (code remains readable)
            2 - Additionally strip insignificant whitespace (code will become quite unreadable)
    
            measureCompression: append a comment stating the extent of compression
    
                @author: Michael Palmer
                @see: http://code.activestate.com/recipes/496882/
                @see: http://webscripts.softpedia.com/developer/Michael-Palmer-8459.html
                @see: http://webscripts.softpedia.com/script/Development-Scripts-js/JavaScript-code-compression--18221.html
            '''
            self.compressionLevel = compressionLevel
            self.measureCompression = measureCompression
    
        # a bunch of regexes used in compression
        # first, exempt string and regex literals from compression by transient substitution
    
        findLiterals = re.compile(r'''
            (\'.*?(?<=[^\\])\')             |       # single-quoted strings
            (\".*?(?<=[^\\])\")             |       # double-quoted strings
            ((?<![\*\/])\/(?![\/\*]).*?(?<![\\])\/) # JS regexes, trying hard not to be tripped up by comments
            ''', re.VERBOSE)
    
        # literals are temporarily replaced by numbered placeholders
    
        literalMarker = '@_@%d@_@'                  # temporary replacement
        backSubst = re.compile('@_@(\d+)@_@')       # put the string literals back in
    
        mlc1 = re.compile(r'(\/\*.*?\*\/)')         # /* ... */ comments on single line
        mlc = re.compile(r'(\/\*.*?\*\/)', re.DOTALL)  # real multiline comments
        slc = re.compile('\/\/.*')                  # remove single line comments
    
        collapseWs = re.compile('(?<=\S)[ \t]+')    # collapse successive non-leading white space characters into one
    
        squeeze = re.compile('''
            \s+(?=[\}\]\)\:\&\|\=\;\,\.\+])   |     # remove whitespace preceding control characters
            (?<=[\{\[\(\:\&\|\=\;\,\.\+])\s+  |     # ... or following such
            [ \t]+(?=\W)                      |     # remove spaces or tabs preceding non-word characters
            (?<=\W)[ \t]+                           # ... or following such
            '''
            , re.VERBOSE | re.DOTALL)
    
        def compress(self, script):
            '''
            perform compression and return compressed script
            '''
            if self.compressionLevel == 0:
                return script
    
            lengthBefore = len(script)
    
            # first, substitute string literals by placeholders to prevent the regexes messing with them
            literals = []
    
            def insertMarker(mo):
                l = mo.group()
                literals.append(l)
                return self.literalMarker % (len(literals) - 1)
    
            script = self.findLiterals.sub(insertMarker, script)
    
            # now, to the literal-stripped carcass, apply some kludgy regexes for deflation...
            script = self.slc.sub('', script)       # strip single line comments
            script = self.mlc1.sub(' ', script)     # replace /* .. */ comments on single lines by space
            script = self.mlc.sub('\n', script)     # replace real multiline comments by newlines
    
            # remove empty lines and trailing whitespace
            script = '\n'.join([l.rstrip() for l in script.splitlines() if l.strip()])
    
            if self.compressionLevel == 2:              # squeeze out any dispensible whitespace
                script = self.squeeze.sub('', script)
            elif self.compressionLevel == 1:            # only collapse multiple whitespace characters
                script = self.collapseWs.sub(' ', script)
    
            # now back-substitute the string and regex literals
            def backsub(mo):
                return literals[int(mo.group(1))]
    
            script = self.backSubst.sub(backsub, script)
    
            if self.measureCompression:
                lengthAfter = float(len(script))
                squeezedBy = int(100*(1-lengthAfter/lengthBefore))
                script += '\n// squeezed out %s%%\n' % squeezedBy
    
            return script
    

    注册:

    register = template.Library()
    register.tag('foldjs', do_foldjs)
    

    【讨论】:

      【解决方案2】:

      为什么你还有页面内的 Javascript?您可以(并且应该)始终将 Javascript 移动到外部文件,以便它们可以被浏览器缓存。当然,除非您将变量加载到 Javascript 中。在这种情况下,无论如何都不应该压缩太多。

      但是,如果您想实现混淆...那就完全不同了。

      【讨论】:

      • 有时您必须处理工作项目中的现有代码,而不是重构并将其完全移动到不同的文件中。不是所有东西都能满足程序员的完美主义。
      【解决方案3】:

      一个非常简单的选择是将缩小从 Django 中移出。 Google 的 mod_pagespeed Apache 模块做得非常好,尤其是在您必须处理遗留项目时。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-20
        • 1970-01-01
        • 1970-01-01
        • 2021-05-06
        • 2014-10-24
        • 1970-01-01
        相关资源
        最近更新 更多