模板具有内联JS时缩小Flask应用程序?

时间:2015-09-05 23:36:41

标签: python flask minify bundling-and-minification

部署应用程序之前的常规约定是缩小所有资产(css,html,js)。这通常假设所有资产都在一个独立的文件中(即所有js代码都在/js/mycode.js,这使得资产缩小更容易。

但是,我写了一堆jinja2模板,其中包含<script>个标签,并且他们使用模板的变量。这对于快速编写UI非常有用,但是我想知道将所有这些迁移到一个js文件中的最佳方法是什么,以便我可以在以后进行缩小?

例如,我有很多具有内联js的模板:

<div class="some_content">
    <button>{{mytext}}</button>
</div>
<script>
    $(".some_content button").click(function() {
        $(this).text("{{new_text}}");
        $.post("{{url_for('doit', name=name)}}", function() {
            console.log('Done!');
        });
    });
</script>

我知道我可以将js代码填充到一个文件中,然后执行{% include 'mycode.js' %},但我会将所有js代码导入到模板中。有些模板具有继承性,因此执行include语句会导致文件多次将整个脚本加载到页面中(不好)。而且我不确定包含这样的脚本如何适用于缩小。

有没有一种好方法可以将所有内联JS代码移动到外部文件中,而不会失去jinja2模板变量的好处,这样我就可以缩小我的javascript?或者更确切地说,什么是缩小我所有内联JS的好方法?

2 个答案:

答案 0 :(得分:4)

你可以使用jinja-assets-compressor。

https://github.com/jaysonsantos/jinja-assets-compressor

<强> app.py

from jac.contrib.flask import JAC
from flask import Flask, render_template
import jinja2
from jac import CompressorExtension

app = Flask(__name__)
app.config['COMPRESSOR_DEBUG'] = app.config.get('DEBUG')
app.config['COMPRESSOR_OUTPUT_DIR'] = './static'
app.config['COMPRESSOR_STATIC_PREFIX'] = '/static'
jac = JAC(app)

env = jinja2.Environment(extensions=[CompressorExtension])
env.compressor_output_dir = './static'
env.compressor_static_prefix = '/static'
env.compressor_source_dirs = './static_files'


@app.route("/")
def hello():
    return render_template('index.html', name='rublex')

if __name__ == "__main__":
    app.run()

<强>的index.html

<!doctype html>
<html class="no-js" lang="">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="x-ua-compatible" content="ie=edge">
        <title>Flask test</title>
    </head>
    <body>
      <h1>Hello World</h1>
      <button onclick="sayHi()">Say Hi</button>

        {% compress 'js' %}
        <script>
            function sayHi() {
              alert('{{ name }}');
            }
        </script>
        {% endcompress %}
    </body>
</html>

输出JS

<script type="text/javascript" src="/static/62280e86f267fdbbd0cd10bb7b5ae3dc.js"></script>

function sayHi(){alert('rublex');}

答案 1 :(得分:0)

如果你只想要简单的内联 js-minification,没有输出文件......这就是我所做的:

花了一些时间让一个简单的自定义 jinja2 标签/节点工作,但希望这可以帮助任何可能需要这样的东西的人。这可能不是最好的方法,但效果很好。这运行与 jinja-assets-compressor 相同的“js-compressor”:

<块引用>

rjsmin - rJSmin 是一个用 Python 编写的 javascript 压缩器,基于 Douglas Crockford 的 jsmin.c 的语义。

在您的 jinja2 代码中包含此代码片段:

JSMinifyExtension

from jinja2 import nodes as j2_Nodes
from jinja2.ext import Extension as j2_Extension

import rjsmin  # https://pypi.org/project/rjsmin/

class JSMinifyExtension(j2_Extension):
    # simple js-minify for jinja2 
    # by joedf (2021) - https://stackoverflow.com/a/66018269/883015

    # a set of names that trigger the extension.
    tags = {"jsminify"}

    def __init__(self, environment):
        super(JSMinifyExtension, self).__init__(environment)
        self._body_content = ""

    def parse(self, parser):
        tag = parser.stream.current.value
        lineno = next(parser.stream).lineno

        body = parser.parse_statements(['name:end{}'.format(tag)], drop_needle=True)
        self._body_content = body[0].nodes[0].data

        return j2_Nodes.CallBlock(self.call_method('_jsminify'), [], [], []).set_lineno(lineno)

    def _jsminify(self, caller):
        minified = rjsmin.jsmin(self._body_content, keep_bang_comments=False)
        return minified

您可以像这样将此扩展加载到您的 jinja2 环境中:

My_Example_Jinja_Env = Environment( extensions=['jinja2.ext.do', JSMinifyExtension] )

并像这样使用你的模板:

{% jsminify %}
function mySpecialFunction() {
    return 42;
}
{% endjsminify %}