gwt lazy loading - gwt

Is it possible in a large GWT project, load some portion of JavaScript lazy, on the fly?
Like overlays.
PS: Iframes is not a solution.

Check out GWT.runAsync as well as the Google I/O talk below, which goes into lazy loading of JavaScript in GWT projects.
http://code.google.com/p/google-web-toolkit/wiki/CodeSplitting
http://code.google.com/events/io/sessions/GoogleWavePoweredByGWT.html (around time 25:30)

I think this is what you are looking for.
<body onload="onloadHandler();">
<script type="text/javascript">
function onloadHandler() {
if (document.createElement && document.getElementsByTagName) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = './test.js';
var heads = document.getElementsByTagName('head');
if (heads && heads[0]) {
heads[0].appendChild(script);
}
}
}
function iAmReady(theName) {
if ('undefined' != typeof window[theName]) {
window[theName]();
}
}
function test() {
// stuff to do when test.js loads
}
</script>
-- test.js
iAmReady('test');
Tested and working in Firefox 2, Safari 3.1.2 for Windows, IE 6 and Opera 9.52. I assume up-level versions of those should work as well.
Note that the loading is asynchronous. If you attempt to use a function or variable in the loaded file immediately after calling appendChild() it will most likely fail, that is why I have included a call-back in the loaded script file that forces an initialization function to run when the script is done loading.
You could also just call an internal function at the bottom of the loaded script to do something once it has loaded.

GWT doesn't readily support this since all Java code that is (or rather may be) required for the module that you load is compiled into a single JavaScript file. This single JavaScript file can be large but for non-trivial modules it is smaller than the equivalent hand written JavaScript.
Do you have a scenario where the single generated JavaScript file is too large?

You could conceivably split your application up into multiple GWT modules but you need to remember that this will limit your ability to share code between modules. So if one module has classes that reference the same class that another module references, the code for the common class will get included twice.
Effectively the modules create their own namespace, similar what you get in Java if you load the same class via two separate class loaders. In fact because the GWT compiler only compiles in the methods that are referenced in your code (i.e it does dead code elimination), it is conceivable that one module will include a different subset of methods from the common class to the other module.
So you have to weigh up whether loading it all as one monolithic module and taking an upfront hit the first time round is better than having multiple modules whose cumulative code size might well be significantly greater than the single module approach.
Given that GWT is designed so that the user should only ever load the same version of a module once (it is cached thereafter), in most cases the one off upfront hit is preferable.

Try to load a big GWT application with the "one upfront" approach using a iPhone or an iPod touch...it will never load.
The module approach is a but more complexe to manage but better for smaller client devices.
Now, how do I load a module from my Java code without using an iFrame?
Erick

Related

Making ReasonML/Bucklescript output ES5 compatible code

While using ReasonML and Bucklescript, is it possible to configure Bucklescript so it won't generate export statements? I'd prefer if the generated code could be used as is in a browser, that is, being ES5 (or ES6) compatible.
Edit: OK, while trying out the tool chain a bit more, I realize just turning off the export is not enough. See example below:
function foo(x, y) {
return x + y | 0;
}
var Test = /* module */[
/* foo */foo
];
exports.Test = Test;
This code will pollute global namespace if exports is removed, and is simply broken from an ES5 compatibility viewpoint.
Edit 2: Reading on Bucklescript's blog, this seems not possible:
one OCaml module compiled into one JavaScript module (AMDJS, CommonJS, or Google module) without name mangling.
Source.
BuckleScript can output modules in a number of different module formats, which can then be bundled up along with their dependencies using a bundler such as webpack or rollup. The output is not really intended to be used as a stand-alone unit, since you'd be rather limited in what you could do in any case, as the standard and runtime libraries are separate modules. And even something as trivial as multiplication will involve the runtime library.
You can configure BuckleScript to output es6 modules, which can be run directly in the browser as long as your browser supports it. But that would still require manually extracting the standard and runtime libraries from your bs-platform installation.
The module format is configured through the package-specs property in bsconfig.json:
{
...
"packages-specs": ["es6-global"] /* Or "es6" */
}
Having said all that, you actually can turn off exports by putting [###bs.config { no_export }] at the top of the file. But this is undocumented since it's of very limited use in practice, for the above mentioned reasons.

Scala template engine for creating js files

I want to create js files using a template engine with Scala. Is it possible with the popular templating engines for Scala, namely Play and Scalate? If possible, than what are the pros and cons for using either of them?
Just create view with .js ext, i.e.: app/views/myScript.scala.js and dummy content:
#(message: String)
alert("#message");
Then add an action into your controller:
def myScript = Action {
// use views.js... NOT views.html... !
Ok(views.js.myScript.render("Whoha! I'm dynamic JS in Scala :)"))
}
or in Java version:
public Result myScript(){
// use views.js... NOT views.html... !
return ok(views.js.myScript.render("Yey! I'm dynamic JS in Java :)"));
}
Add the route to this action:
GET /my-script controllers.Application.myScript()
So you can use this route directly:
<script src="/my-script"></script>
note, that Play should return valid Content-Type:text/javascript; charset=utf-8 in the response, anyway depending on version you are using it may be required to enforce this manually within your action (use browser's inspection tool to check the response type)
It really depends on what you want to achieve, i.e. how sophisticated your JavaScript code will be, but, unless it's something really small and simple, I'd suggest using the Scala.js. This way you basically will write some Scala code that will compile into JavaScript, and that compiled JavaScript you should be able to include into your Play application.
Advantages of writing Scala vs JavaScript should be pretty obvious (type safety, using lots of the existing Scala libraries). Disadvantage would be some delays for Scala -> JavaScript compilation, and also lack of the same seamless integration of Scala.js and Play, like Play has with its own templating engine. It's up to you to decide if the extra work to make these 2 work together worth it.

zend framework own functions and classes

Now I have some experience in using the Zend Framework. I want to go deeper in the topic and rewrite some old php projects.
What is the best place to save own functions and classes?
And how do I tell Zend where they are? Or is there already a folder for own stuff? May I have different folders for different files?
For example I want to save a php document with the name math_b.php which includes several special functions to calculate and another one date_b.php which has abilities for datetime stuff. Is that possible or shall I have different files for every function?
I would also like to reuse the functions in other projects and then just copy the folders.
There is no single "right" answer for this. However, there are several general guidelines/principles that I commonly employ.
Do not pollute global scope
Namespace your code and keep all functions is classes. So, rather than:
function myFunction($x) {
// do stuff with $x and return a value
}
I would have:
namespace MyVendorName\SomeComponent;
class SomeUtils
{
public static function myFunction($x)
{
// do stuff with $x and return a value
}
}
Usage is then:
use MyVendorName\SomeComponent\SomeUtils;
$val = SomeUtils::myFunction($x);
Why bother with all this? Without this kind of namespacing, as you bring more code into your projects from other sources - and as you share/publish your code for others to consume in their projects - you will eventually encounter name conflicts between their functions/variables and yours. Good fences make good neighbors.
Use an autoloader
The old days of having tons of:
require '/path/to/class.php';
in your consumer code are long gone. A better approach is to tell PHP - typically during some bootstrap process - where to find the class MyVendor\MyComponent\MyClass. This process is called autoloading.
Most code these days conforms to the PSR-0/PSR-4 standard that maps name-spaced classnames to file-paths relative to a file root.
In ZF1, one typically adds the ./library folder to the PHP include_path in ./public/index.php and then add your vendor namespace into the autoloaderNameSpaces array in ./application/config.ini:
autoloaderNameSpaces[] = 'MyVendor';
and places a class like MyVendor\MyComponent\MyClass in the file:
./library/MyVendor/MyComponent/MyClass.php
You can then reference a class of the form MyVendor\MyComponent\MyClass simply with:
// At top of consuming file
use MyVendor\MyComponent\MyClass;
// In the consuming page/script/class.
$instance = new MyClass(); // instantiation
$val = MyClass::myStaticMethod(); // static method call
Determine the scope of usage
If I have functionality is required only for a particular class, then I keep that function as a method (or a collection of methods) in the class in which it is used.
If I have some functionality that will be consumed in multiple places in a single project, then I might break it out into a single class in my own library namespace, perhaps MyVendor.
If I think that a function/class will be consumed by multiple projects, then I break it out into its own project with its own repo (on Github, for example), make it accessible via Composer, optimally registering it with Packagist, and pay close attention to semantic versioning so that consumers of my package receive a stable and predictable product.
Copying folders from one project into another is do-able, of course, but it often runs into problems as you fix bugs, add functionality, and (sometimes) break backward-compatibility. That's why it is usually preferable to have those functions/classes in a separate, semantically-versioned project that serves as a single source-of-truth for that code.
Conclusion
Breaking functionality out into separate, namespaced classes that are autoloaded in a standard way gives plenty of "space" in which to develop custom functionality that is more easily consumed, more easily re-used, and more easily tested (a large topic for another time).

How to access data across modules in GWT?

I have two GWT modules with its own entry point, ModuleA and ModuleB. I am using Window.assign() to move from ModuleA to ModuleB. One Variable value is set in ModuleA. How to access the same value from ModuleB?
Thanks in advance.
I have written a couple of answers which could help you to deal with this.
Since you cannot share pure java between two compiled modules: GWT: How to share a java Object (ie: EventBus) between two modules, I suggest to export methods using jsni: How to communicate two modules in GWT. But I would use gwt-exporter or gwt-query to avoid writing js by hand which normally is a source of mistakes: Calling GWT Java function from JavaScript
Note, that these solutions only work in the case both modules are loaded in the same html.
If you want to pass a value to a different page downloading the actual, you can append those values to the new url and read it in the second application:
// Module A
Window.Location.assign("module_B.html?msg=whatever");
// Module B
String msg = Window.Location.getParameter("msg");
IMO the best way would be to implement the observer/observable pattern in pure JavaScript in your host page, and use JSNI in your application to register handlers/fire events.

How do I associate a CoffeeScript file with a view?

Just installed rails 3.1 rc1 and am trying to grok the best way to manage javascript with the new asset pipeline
By default all coffeescript is compiled into a single application.js file, this is a good thing.
Each seperate coffee script file is appended to the js file and wrapped in an anonymous function which is executed via the call method
A common scenario would be to use some jquery to turn various forms into ajax forms, update UI, etc...
Many of these scripts will be specific to a controller or action, I am trying to grok the 'conventional' way to handle this,
since everything is wrapped in an anonymous function how do I only execute just
the code for a particular controller / action, by default all of the anonymous functions are being executed
I did play around with some hacks where I load the controller and action name into js variables and then in
coffeescript check those to conditionally run code, I don't like that very much
my initial thought was that each coffee file would contain a js namespace/object and I would call the specific ones from the view,
going to spike this using the default_bare = true configuration
see How can I use option "--bare" in Rails 3.1 for CoffeeScript?
EDIT
Looking around some more: this looks like it might be the correct approach - "Can't find variable" error with Rails 3.1 and Coffeescript
There are two common approaches:
Make behavior conditional on the presence of a particular element. For instance, code to run a signup sheet should be prefaced with something like
if $('#signup').length > 0
Make behavior conditional on a class on the body element. You can set the body class using ERB. This is often desirable for stylesheets as well. The code would be something like
if $('body').hasClass 'user'
gistyle is a simple gem that helps you running action-specific javascript codes.
By following its setup, you set some data attributes in your body element, representing the current controller and action names. Then it will only call that action when the corresponding view is loaded.