简体   繁体   English

使用Twig作为Symfony2中JavaScript的Assetic过滤器

[英]Using Twig as an Assetic filter for JavaScript in Symfony2

Is there a way to use Twig as an Assetic filter? 有没有办法使用Twig作为Assetic过滤器?

What I want to do is have Twig parse my JavaScript files as Twig templates, and then pass them to Assetic so that they get combined and minified in production. 我想要做的是让Twig将我的JavaScript文件解析为Twig模板,然后将它们传递给Assetic,以便它们在生产中得到组合和缩小。

You might be scratching your head thinking why I would want to do this in the first place, so let me jump to an example. 你可能会想到我为什么要这样做,所以让我跳到一个例子。


I am making a game engine in JavaScript and I need to have two versions of several 'classes'. 我正在使用JavaScript制作游戏引擎,我需要有两个版本的几个“类”。 One version for the user and another for the editor. 用户的一个版本和编辑器的另一个版本。 An example of one of these classes would be the singleton World . 其中一个类的一个例子是单身世界

The user version of this class might look like this: 此类的用户版本可能如下所示:

var World = function()
{
    // bunch of 'private' variables and functions inside closure
    var _initialised = false;
    var _worldData;
    ...

    // public functions
    this.init = function(){...}
    this.update = function(){...}
    ...
}

The editor version of this class might look this: 此类的编辑器版本可能如下所示:

var World = function()
{
    // bunch of 'private' variables and functions inside closure
    var _initialised = false;
    var _worldData;
    ...

    // bunch of new private variables and functions for editing
    var _editorserver;
    ...

    // public functions
    this.init = function(){...}
    this.update = function(){...}
    ...

    // public functions that edit the world
    this.addEntity = function(){...}
    this.removeEntity = function(){...}
    ...
}

With classical OO inheritance we could define World as one class and then extend it with another class EditableWorld . 使用经典的OO继承,我们可以将World定义为一个类,然后使用另一个类EditableWorld扩展它。 However with Prototypal inheritance in JavaScript only the public functions would be inherited and if you even tried to extend the existing instance you would not be able to access the variables and functions inside the closure. 但是,在JavaScript中使用Prototypal继承只会继承公共函数,如果您甚至尝试扩展现有实例,则无法访问闭包内的变量和函数。

In comes Twig to the rescue! Twig来救援!

With Twig we could add several blocks to any class in a file, and then create another file defining the same class with some extensions and then include that file. 使用Twig,我们可以向文件中的任何类添加几个块,然后创建另一个文件,定义具有一些扩展名的相同类,然后包含文件。

So let's look at our base World class again as a Twig template. 让我们再看一下我们的基础World类作为Twig模板。

// world.js.twig
var World = function()
{
    // bunch of 'private' variables and functions inside closure
    var _initialised = false;
    var _worldData;
    ...

    {% block extended_privates %}{% endblock %}

    // public functions
    this.init = function(){...}
    this.update = function(){...}
    ...

    {% block extended_publics %}{% endblock %}
}

And our extended version. 而我们的扩展版本。

// editableworld.js.twig
{% extends "EngineBundle::world.js.twig" %}
var World = function()
{
    // bunch of 'private' variables and functions inside closure
    var _initialised = false;
    var _worldData;
    ...

    {% block extended_privates %}
    // bunch of new private variables and functions for editing
    var _editorserver;
    ...
    {% endblock %}

    // public functions
    this.init = function(){...}
    this.update = function(){...}
    ...

    {% block extended_publics %}
    // public functions that edit the world
    this.addEntity = function(){...}
    this.removeEntity = function(){...}
    ...
    {% endblock %}
}

Now here's the rub: how do you I get Assetic to use Twig as a filter so that I can do something like this: 现在这里有一个问题:你如何让Assetic使用Twig作为过滤器,这样我就可以这样做:

// user version of twig template
// gameengine.html.twig

{% javascripts filter="js_twig_filter"
"@EngineBundle/Resources/public/js/world.js.twig"
%}
<script src="{{ asset_url }}" type="text/javascript"></script>
{% endjavascripts %}

// editor version of twig template
// gameeditor.html.twig

{% javascripts filter="js_twig_filter"
"@EngineBundle/Resources/public/js/editableworld.js.twig"
%}
<script src="{{ asset_url }}" type="text/javascript"></script>
{% endjavascripts %}

One immediate solution that might come to your head is to forgo closures altogether and just make all my variables and functions public and just prefix the ones that should have been private with an underscore. 一个可能出现在你脑海中的直接解决方案是完全放弃闭包,只是将我的所有变量和函数公开,并将前缀应该是私有的前缀加上前缀。 However for me this isn't a valid solution as I'm not merely creating a library. 但对我来说,这不是一个有效的解决方案,因为我不仅仅是创建一个库。 The game engine needs to close off all of it's internals from the end user to stop all but determined users who would want to tamper with the running engine (and for those users I have server validation in place to make sure illegal actions from the compromised clients don't get sent to other clients via the server). 游戏引擎需要关闭来自最终用户的所有内部构件,以阻止所有想要篡改正在运行的引擎的用户(对于那些我已经进行服务器验证的用户,以确保来自受感染客户端的非法操作)不要通过服务器发送给其他客户端)。

Thanks for sticking around and I hope someone can help me (I've been banging my head against the wall for a few days now trying alternative ideas before I thought of this possible solution). 感谢你坚持下去,我希望有人可以帮助我(在我想到这个可能的解决方案之前,我已经在墙上撞了几天,现在尝试了另外的想法)。

You need to render (in the controller) all the *.js.twig files first and save them as *.js files (using file_put_contents() function somewhere in the Resources tree). 您需要首先渲染(在控制器中)所有* .js.twig文件,并将它们保存为* .js文件(使用资源树中某处的file_put_contents()函数)。 Then load the *.js files into your assetic filters. 然后将* .js文件加载到资产过滤器中。

Besides, you have a lot of libraries/languages/helpers that support OOP in JavaScript elegantly (like CoffeeScript, Backbone.js, Underscore.js, etc.) 此外,你有很多图书馆/语言/助手,优雅地支持JavaScript中的OOP(如CoffeeScript,Backbone.js,Underscore.js等)

Good luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM