GWT automatically obfuscates CSS name during compilation. I'm looking for way to externalize this CSS that was obfuscated by GWT after compilation, rather then inline it inside HTML.
Any suggestion? I still want to use the built-in compilation to obfuscate CSS, but I want to redirect the output to an external .css file. Is this possible? Does it needs a custom compiler linker? Any example on how to do this?
You can disable inlining of resources (all ClientBundle resources though) by adding the following to your gwt.xml:
<set-property name="ClientBundle.enableInlining" value="false" />
Related
I have a GWT 2.7 application where a lot of the styling is done in a CSS file referenced in the module XML file. I'd like to migrate this file to GSS so I can use some of the new functionality like variables and functions.
The GSS Migration Guide has instructions on migrating to GSS, but it appears to apply only to styles used through CSSResource objects. My understanding is that the only class selectors that can be accessed through CSSResources are those for which one declares accessors, and that all these class selectors will be obfuscated. This won't work for me because the selectors I want to use are unobfuscated ones that have mainly been added through UIObject.addStyleName and addStyleDependentName. I also don't want to have to add an accessor to an interface every time I want to add a new style.
As for the other three ways of using CSS files in a GWT project:
Using a <link> tag in the host HTML page.
Using the <stylesheet> element in the module XML file.
Using an inline <ui:style> element in a UiBinder template.
The first two don't seem to support GSS: even if I specify a GSS file it simply gets served directly to the browser without processing.
Is my only choice, then, to migrate to UIBinder? And if so, what's the minimal way to do this? (My current HTML host page is just the default host page with some additional stuff in the <head> element, so I feel like this ought to be straightforward).
Using a <ui:style> is the same as using CssResource. The .ui.xml file will generate the required ClientBundle and CssResource files, and those in turn will convert the GSS to css.
When you refer to <ui:style> content in a .ui.xml file, you do so as if you were caling an accessor on the interface, as {style.myStyleName} - because you are calling the accessor, but it is generated automatically. This may limit what you can do in your <ui:style> tag slightly. On the other hand, once you write CSS, your IDE can almost certainly add the accessors for you automatically, and if it doesn't, the failed recompile will list them so you can add them.
If instead you simply put a string literal "my-class-name" in your Java or HTML, the compiler has no way of knowing that "my-class-name" is the same or different everywhere in your app, and when to use one CssResource versus another. It also cannot rewrite those strings, so your CSS would remain unoptimized. Plus, now you can check for usages of a given css class name accessor - if no one uses it, delete it, then delete the CSS that uses it, to keep your .gss files smaller, and your application smaller.
You are correct in that <link> tags in the html, and <stylesheet> tags in the .gwt.xml do not result in running GSS. You do not need to use UiBinder (and I'm not a fan personally, but some people like it), but you do need to use the accessors, or there is no point to GSS as it stands.
If you want to avoid obfuscation and renaming, consider just running the closure-stylesheets directly, or something like LESS or SASS on your plain CSS file, which have no GWT integration, and so will work just fine with your string literals already in use. This will result in bigger compiled outputs, and remove your ability to find and remove unused CSS in an easy way.
As I discovered later on, it turns out that you can inject a GSS (or CSS) stylesheet as a CSSResource without the selectors being obfuscated. Simply add the following annotation to the stylesheet:
#external '*';
This will mark all selectors in the file as external, which means 1) that the CSSResource subinterface used as the type for the stylesheet resource will no longer be required to implement accessor methods corresponding corresponding to the class selectors in the stylesheet and 2) that the selectors in the stylesheet will be unobfuscated, so for example if you have a class .foo in the stylesheet you'll be able to apply it to entities using UIObject.addStyleName("foo").
This way you can easily get some of the major benefits of GSS (variables, functions, etc.) and CSSResource (injection into the page rather than serving another file) without having to make any changes to your workflow.
I am new in GWT. I want to ask some questions about UI binder:
<ui:with field='res' type='com.my.app.widgets.logoname.Resources'/>
(1) Refer to code above. What is the meaning of type? Is meant the file location?
(2) Why need to use external resource for the UI binder?
(3) When I write css, in java file should I need to write the "extends CssResource" word?
I really don't understand. Please help me to answer the question. Thanks.
<ui:with field='res' type='com.my.app.widgets.logoname.Resources'/>
Refer to code above. What is the meaning of type? Is meant the file location?
Here type is equivalent to below java code
Resources res = new com.my.app.widgets.logoname.Resources();
Why need to use external resource for the UI binder?
Sometimes your template will need to work with styles or other objects that come from outside of your template.
When I write css, in java file should I need to write the "extends CssResource" word?
Yes you have to use extends CssResource
For detailed explaination and samples please have a look at GWT UIBinder - Using an external resource.
Find a sample code here about GWT - Using UiBinder.
Here is the key points of using UIBinder:
The UiBinder is a framework designed to separate Functionality and View of User Interface.
The UiBinder framework allows developers to build gwt applications as HTML pages with GWT widgets configured throughout them.
The UiBinder framework makes easier collaboration with UI designers who are more comfortable with XML, HTML and CSS than Java source code
The UIBinder provides a declarative way of defining User Interface.
The UIBinder seperates the programmic logic from UI.
The UIBinder is similar to what JSP is to Servlets.
I'm trying to figure out exactly what css is included by the standard call to currentDesign.writeCssIncludes(pagecontext); found in headlibs.jsp. The documentation states simply that it is
Convenience method that writes the CSS include strings to the response.
Looking at what it seems to do, it will include /etc/designs/currentdesign.css which is built off the design components css, and /etc/designs/currentdesign/static.css, which is just a static file. But is this all that is will include?
In particular, what I'd like to do is include a clientLib-processed css file as part of my design. One way to do this is to manually build out the css include:
<link rel="stylesheet" href="<%= currentDesign.getPath() %>/myclientlib.css" />
But I'd prefer to let that get generated automatically, so that my designers have flexibility to structure the css files differently for different designs (i.e., for the "base" design they are fine with just a static.css file, but for the "fancy" design they want to use LESS css and break up the files more granularly). And it would be helpful to put design-specific css info with the components they affect, rather then needing to separate those.
You can use the <cq:includeClientLib> tag, combined with themes and/or categories, to mix and match bits of CSS.
But you may find it somewhat limiting; for instance, you can't specify a media attribute. If you need to do this, or your designers don't structure their CSS in a way that fits the themes/categories model, your fallback is the technique you've identified in your question, using <link> directly.
Update
An excellent question about themes! I have only seen them used in passing.
You can define a theme by just adding a new folder/node under /etc/designs/yourproject/clientlibs/themes, as a sibling to default.
You can pull in the clientlibs for a theme with the <cq:includeClientLibs> tag, perhaps under the control of some conditional logic. For instance, in one of my projects I have a theme called authoring which I only want to apply to the author instance; I pull it in with this code in headlibs.jsp:
<c:if test="${ (global['wcmmode'] eq 'EDIT') || (global['wcmmode'] eq 'PREVIEW') }">
<cq:includeClientLib theme="apps.myproject.authoring" />
</c:if>
I have not seen any documentation that would apply theme automatically to a particular subtree of the content tree, or based on the presence of a tag.
There is that cryptic statement "The theme name is extracted from the request." in the Adobe docs, which is backed up by this statement in the Sling docs, "ThemeResolverFilter Provides the Theme for the request. The theme is provided as a request attribute." So perhaps tacking &theme=apps.yourproject.foo onto a query string would apply that theme.
The list of CSS files is based on the property 'cq:designPath' of the page.
how can i take advantage of GWT's deferred binding mechanism for script resources (e.g. CSS, JavaScript)?
the <define-property ... /> and <set-property ... /> ( when used in conjunction with <when-property-is ... /> ) does not provide this functionality since they're used for Java types binding.
thanks in advance!
Since the is used for Java types, you can use that paradigm and wrap your css and js in java/gwt classes. The js will use the native js interface to wrap up the methods and the css can be included in a CssResource/ClientBundle class. Then just use the gwt.xml file to use whichever one you need for the conditions you have.
Are there any best practices for using Google Web Fonts in a Google Web Toolkit application? My initial inclination is to simply add the css reference directly in my .html file, a la
<link href='http://fonts.googleapis.com/css?family=Josefin+Sans:light,regular,bold' rel='stylesheet' type='text/css'>
But I'm not sure if this is the best way to do it. Is there any advantage to (or any way to) use ClientBundle here?
Google discourages the direct inclusion of css files on host pages for a mere fact that in this case GWT code has an external (detached) dependence. This only matters if you share a GWT module with other developers - note that this might happen in the future when your project gets refactored by some other people that took over the development. So it's still a good practice to make GWT modules with type-safe external dependencies.
As you know you can simply use one of the recommended ways:
Using a CssResource contained within a ClientBundle.
Using an inline <ui:style src="http://fonts.googleapis.com/css?family=Josefin"> element in a UiBinder template.