通过 *.gwt.xml 精确控制 GWT 排列
Precise control of GWT permutations via *.gwt.xml
我需要精确指定 GWT 排列并控制其中的变化(每个排列支持 属性 值的组合)但很难找到详细的行为规范。
在我的实验过程中,我了解到我必须注意创建 set-属性 ... when-属性-is 循环,即使这些循环是 "stable" - 即他们不改变循环的任何部分,只是 "confirm" 它。这限制了我能做的,所以我决定尝试另一种方式 - 定义一个全新的 属性,(只是)例如:
<define-property name="precise.permutation" values="webkit,gecko,ie,unsupported"/>
...然后有类似的东西:
<set-property name="precise.permutation" value="webkit">
<!-- ... custom conditions ... -->
</set-property>
<set-property name="precise.permutation" value="gecko">
<!-- ... custom conditions ... -->
</set-property>
<set-property name="precise.permutation" value="ie">
<!-- ... custom conditions ... -->
</set>
<set-property name="precise.permutation" value="unsupported">
<!-- ... custom conditions ... -->
</set-property>
... 然后我尝试将此限制为所有但不支持的,这被用作示例但完全违反直觉,因为它使用与上面相同的 set-属性 标签:
<set-property name="precise.permutation" value="webkit,gecko,ie" />
我还必须折叠其他属性以确保它们不会导致额外的排列。
不幸的是,这似乎没有按预期工作(尝试使用 GWT 2.8 RC2)。即使 "unsupported" 排列没有出现(这是需要的),它的属性组合会重新出现在其他排列中(这是不需要的)。
有人可以帮我找到权威的 和完整的 文档,或者帮我解决这个问题吗?
谢谢!
我仍然没有找到详细的文档,但我已经做了很多实验并得出以下结论...
(注意:我的示例使用了我开发时使用的 Sencha GXT 中的一些概念)
用于定义 属性 及其可能的值,但不是实际使用哪些值的最终决定。在 *.gwt.xml 文件的层次结构中,每个 属性 应该只有一个这样的定义。
不会将 属性 设置为 A 值,而是创建一种规则,其中包含 [=67=67=POSSIBLE 值的集合=](最好是 <define-属性> 中定义的子集)。给定 属性 的 的最后声明获胜。当心!如果您在 (继承模块)之后使用 ,您 may/will 将覆盖您继承的任何规则。请注意,有条件规则和无条件规则。例如,
<set-property name="gxt.user.agent" value="ie10, ie11, gecko1_9, safari5, chrome"/>
... 将无条件声明,在确定排列时,属性 'gxt.user.agent' 可以具有任何一个列出的值。反之,
<set-property name="user.agent" value="safari">
<any>
<when-property-is name="gxt.user.agent" value="safari5" />
<when-property-is name="gxt.user.agent" value="chrome" />
</any>
</set-property>
当 "gxt.user.agent" 为 "safari5" 或 "chrome" 时,将声明 user.agent 只能为 "safari"。顺序似乎很重要,因此您需要在其依赖项规则之后声明依赖属性的规则。循环依赖将使编译失败。您可以创建许多条件规则,只要它们不相互矛盾即可。我还不知道如果他们这样做会发生什么,但我猜最后宣布的人会赢。
请注意,条件规则也可以指定多个可能的值。例如(仅供参考,可能不符合您的需求):
<!-- On desktops we do all browsers including IE -->
<set-property name="gxt.user.agent" value="safari5, chrome, gecko1_9, ie11">
<when-property-is name="gxt.device" value="desktop" />
</set-property>
<!-- ... but on tablets and phones we exclude IE -->
<set-property name="gxt.user.agent" value="safari5, chrome, gecko1_9">
<any>
<when-property-is name="gxt.device" value="tablet" />
<when-property-is name="gxt.device" value="phone" />
</any>
</set-property>
您可以使用 和 来创建complex/compound 条件。它们可以相互嵌套。
如何使用它来精确控制排列?你可能不需要这个,但它帮助我开始定义两个像这样的属性:
<define-property name="custom.use.case" values="case1, case2, ..."/>
<property-provider name="helix.product.mode"><![CDATA[
var useCase = ...; // JavaScript code to determine the use case
return useCase;
]]>
</property-provider>
<define-property name="custom.permutation" values="perm1, perm2, ..."/>
第一个 属性 定义用例。上面我有一种在运行时确定它的方法。你可能不会也可能会跳过它。它还可以作为定义其他所有内容的起点,因为我们可以根据用例定义所有其他属性。例如:
<!-- Case 1 restrictions -->
<set-property name="gxt.device" value="desktop">
<when-property-is name="custom.use.case" value="case1" />
</set-property>
<set-property name="gxt.user.agent" value="chrome, safari5, gecko1_9, ie11">
<when-property-is name="custom.use.case" value="case1" />
</set-property>
...
<!-- Case 2 restrictions -->
<set-property name="gxt.device" value="tablet, phone">
<when-property-is name="custom.use.case" value="case2" />
</set-property>
<set-property name="gxt.user.agent" value="chrome, safari5, gecko1_9">
<when-property-is name="custom.use.case" value="case2" />
</set-property>
...
<!-- Case 3 restrictions -->
<set-property name="gxt.device" value="tablet, phone">
<when-property-is name="custom.use.case" value="case3" />
</set-property>
<set-property name="gxt.user.agent" value="safari5">
<when-property-is name="custom.use.case" value="case3" />
</set-property>
...
etc.
接下来要做的是折叠 所有 custom.permutation 的属性 except,因为我们只想要 custom.permutation 驱动排列:
<collapse-property name="custom.use.case" values="*" />
<collapse-property name="gxt.device" values="*" />
<collapse-property name="gxt.user.agent" values="*" />
<collapse-property name="user.agent" values="*" />
<collapse-property name="user.agent.os" values="*" />
这种方法允许对 "permutations" 及其内部复杂性进行极其精细的控制,有些人称之为 "soft permutations"。每个可能的 "custom.permutation" 属性 值都会有一个排列。如果您很好地设置了上述规则,每个排列将只包含所需的 "soft permutations"。
请注意,实际排列和软排列都需要成本。拥有许多软排列(是否分组为实际排列)会影响编译性能和它们所在排列的运行时代码大小。不要忽略这一点,尤其是当您有许多属性时。实际排列具有更高的编译和链接时间成本(但与将许多软排列组合成分组的实际排列相比,拥有更多排列会减少每个排列的大小)。
如果使用 GXT,从第 4 版开始,您会注意到它添加了 gxt.device 属性,其中包含桌面、平板电脑和 phone 等值。这导致我们的编译时间在升级到 GXT 4 后增加了大约 6-7 倍,因为我们的排列失去了控制。从字面上看,有些最终是在 Mac OS 平板电脑上为 Internet Explorer 运行 制作的。您可以体会到对不存在的用例进行排列是多么浪费时间。通过实施上述内容,我们能够将 GWT 编译时间减少到原始时间的一半左右,或者比升级 GXT 4 后的编译时间快 10-12 倍。
我需要精确指定 GWT 排列并控制其中的变化(每个排列支持 属性 值的组合)但很难找到详细的行为规范。
在我的实验过程中,我了解到我必须注意创建 set-属性 ... when-属性-is 循环,即使这些循环是 "stable" - 即他们不改变循环的任何部分,只是 "confirm" 它。这限制了我能做的,所以我决定尝试另一种方式 - 定义一个全新的 属性,(只是)例如:
<define-property name="precise.permutation" values="webkit,gecko,ie,unsupported"/>
...然后有类似的东西:
<set-property name="precise.permutation" value="webkit">
<!-- ... custom conditions ... -->
</set-property>
<set-property name="precise.permutation" value="gecko">
<!-- ... custom conditions ... -->
</set-property>
<set-property name="precise.permutation" value="ie">
<!-- ... custom conditions ... -->
</set>
<set-property name="precise.permutation" value="unsupported">
<!-- ... custom conditions ... -->
</set-property>
... 然后我尝试将此限制为所有但不支持的,这被用作示例但完全违反直觉,因为它使用与上面相同的 set-属性 标签:
<set-property name="precise.permutation" value="webkit,gecko,ie" />
我还必须折叠其他属性以确保它们不会导致额外的排列。
不幸的是,这似乎没有按预期工作(尝试使用 GWT 2.8 RC2)。即使 "unsupported" 排列没有出现(这是需要的),它的属性组合会重新出现在其他排列中(这是不需要的)。
有人可以帮我找到权威的 和完整的 文档,或者帮我解决这个问题吗?
谢谢!
我仍然没有找到详细的文档,但我已经做了很多实验并得出以下结论...
(注意:我的示例使用了我开发时使用的 Sencha GXT 中的一些概念)
<set-property name="gxt.user.agent" value="ie10, ie11, gecko1_9, safari5, chrome"/>
... 将无条件声明,在确定排列时,属性 'gxt.user.agent' 可以具有任何一个列出的值。反之,
<set-property name="user.agent" value="safari">
<any>
<when-property-is name="gxt.user.agent" value="safari5" />
<when-property-is name="gxt.user.agent" value="chrome" />
</any>
</set-property>
当 "gxt.user.agent" 为 "safari5" 或 "chrome" 时,将声明 user.agent 只能为 "safari"。顺序似乎很重要,因此您需要在其依赖项规则之后声明依赖属性的规则。循环依赖将使编译失败。您可以创建许多条件规则,只要它们不相互矛盾即可。我还不知道如果他们这样做会发生什么,但我猜最后宣布的人会赢。
请注意,条件规则也可以指定多个可能的值。例如(仅供参考,可能不符合您的需求):
<!-- On desktops we do all browsers including IE -->
<set-property name="gxt.user.agent" value="safari5, chrome, gecko1_9, ie11">
<when-property-is name="gxt.device" value="desktop" />
</set-property>
<!-- ... but on tablets and phones we exclude IE -->
<set-property name="gxt.user.agent" value="safari5, chrome, gecko1_9">
<any>
<when-property-is name="gxt.device" value="tablet" />
<when-property-is name="gxt.device" value="phone" />
</any>
</set-property>
您可以使用
如何使用它来精确控制排列?你可能不需要这个,但它帮助我开始定义两个像这样的属性:
<define-property name="custom.use.case" values="case1, case2, ..."/>
<property-provider name="helix.product.mode"><![CDATA[
var useCase = ...; // JavaScript code to determine the use case
return useCase;
]]>
</property-provider>
<define-property name="custom.permutation" values="perm1, perm2, ..."/>
第一个 属性 定义用例。上面我有一种在运行时确定它的方法。你可能不会也可能会跳过它。它还可以作为定义其他所有内容的起点,因为我们可以根据用例定义所有其他属性。例如:
<!-- Case 1 restrictions -->
<set-property name="gxt.device" value="desktop">
<when-property-is name="custom.use.case" value="case1" />
</set-property>
<set-property name="gxt.user.agent" value="chrome, safari5, gecko1_9, ie11">
<when-property-is name="custom.use.case" value="case1" />
</set-property>
...
<!-- Case 2 restrictions -->
<set-property name="gxt.device" value="tablet, phone">
<when-property-is name="custom.use.case" value="case2" />
</set-property>
<set-property name="gxt.user.agent" value="chrome, safari5, gecko1_9">
<when-property-is name="custom.use.case" value="case2" />
</set-property>
...
<!-- Case 3 restrictions -->
<set-property name="gxt.device" value="tablet, phone">
<when-property-is name="custom.use.case" value="case3" />
</set-property>
<set-property name="gxt.user.agent" value="safari5">
<when-property-is name="custom.use.case" value="case3" />
</set-property>
...
etc.
接下来要做的是折叠 所有 custom.permutation 的属性 except,因为我们只想要 custom.permutation 驱动排列:
<collapse-property name="custom.use.case" values="*" />
<collapse-property name="gxt.device" values="*" />
<collapse-property name="gxt.user.agent" values="*" />
<collapse-property name="user.agent" values="*" />
<collapse-property name="user.agent.os" values="*" />
这种方法允许对 "permutations" 及其内部复杂性进行极其精细的控制,有些人称之为 "soft permutations"。每个可能的 "custom.permutation" 属性 值都会有一个排列。如果您很好地设置了上述规则,每个排列将只包含所需的 "soft permutations"。
请注意,实际排列和软排列都需要成本。拥有许多软排列(是否分组为实际排列)会影响编译性能和它们所在排列的运行时代码大小。不要忽略这一点,尤其是当您有许多属性时。实际排列具有更高的编译和链接时间成本(但与将许多软排列组合成分组的实际排列相比,拥有更多排列会减少每个排列的大小)。
如果使用 GXT,从第 4 版开始,您会注意到它添加了 gxt.device 属性,其中包含桌面、平板电脑和 phone 等值。这导致我们的编译时间在升级到 GXT 4 后增加了大约 6-7 倍,因为我们的排列失去了控制。从字面上看,有些最终是在 Mac OS 平板电脑上为 Internet Explorer 运行 制作的。您可以体会到对不存在的用例进行排列是多么浪费时间。通过实施上述内容,我们能够将 GWT 编译时间减少到原始时间的一半左右,或者比升级 GXT 4 后的编译时间快 10-12 倍。