i am trying to build app that uses multiple "modules" under same
application. Is this possible to do or do i have to build new app for
every "module"?
My app has "default" module which uses gwt.js as its gwt-script. Now if
i would like to split my application into parts is it possible under
same application/project?
Lets say, that my app has now all its code in "default" module and it
uses gwt.js as its gwt-script like i told. Now what if i would likt to
build login-app for my application Do i have to build entire new
application or is this possible to build inside of my current
application? Does gwt put all the code in same .js file or does it
split all modules in their own files?
my current "module" is loaded on page like this:
<meta name='gwt:module' content='com.company.gwt.app'>
<script language="javascript" src="gwt.js"></script>
And entrypoint of app is defined in app.gwt.xml like this:
<module>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Specify the app entry point class. -->
<entry-point class='com.company.gwt.client.EntryPoint'/>
</module>
A module is different from an EnrtyPoint
you can have severals modules (gwt libs) used by a same entry point (a
gwt application)
So what you want exactly do ?
What i want to do is put multiple entry points in the same app. I can
define multiple entrypoints in my xml file (app.gwt.xml) like this:
<module>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Specify the app entry point class. -->
<entry-point class='com.company.gwt.client.EntryPoint'/>
<entry-point class='com.company.gwt.client.Login'/>
<entry-point class='com.company.gwt.client.Shop'/>
</module>
but how do i define which one is loaded on my single html page?
Does gwt put all my entrypoints in the same js (gwt.js) or does every
entry point get its own js?
Thanx!
I wrote a registry where each entry-point adds itself during
onModuleLoad, later any entry point can lookup the other running in
that root. The registry has to be two-layered, it is a hashmap by
RootPanel.getBodyElement for hashmaps of name, EntryPoint instance.
All my Entrypoints have a single panel in the RootPanel, I simply
switch them between visible/invisible. Works fine
If you have a "Login" widget, and a "Shop" widget, then you can switch
them in and out of the same "page" without them being in different
EntryPoint classes. And, if you make the logic for each a "module",
including whatever client side model each may have, related RPC code,
etc, you can then easily inherit Shop and Login in a new module,
intended to combine those other modules - and all the logic will be
there, and will be nicely encapsulated per module.
Why do you want to use separate entry point classes over
inheritance?
I ask because at this point GWT will create the JS files as one large
block, if they reference each other (if you map them together, as the
"registry" approach seems to describe). So the same code download is
present, you are just working against the grain. I suppose either way
would work, but I am still not understanding what advantage multiple
entry points achieves?
Basically he said you can do that pretty nicely right now by using the
History support, but that he agreed with me about being skeptical of
what a "big" app is (if you are using HTTP compression and OBF and so
on). Put your modules on different pages and using GWT History
support just forward to another module seamlessly. This way not only
can you separate out modules, host pages, entry points, etc, if you
need to, but you also get a final "app" that users can browse through,
forward and back while crossing app boundaries and not know it.
BTW for me, a big app is 380kb with OBF but without compression
(because it's not my server), without images, for a user on dial-up
(maybe not even on 56kbps) who is paying by the minute.
So how do I split my 380kb into smaller chunks using History support?
Ian
--
Ian
http://roughian.com
I asked Bruce this specific question though, because it comes up often
on the forums and it's certainly a legitimate issue (especially if you
are talking in concrete terms, such as 380k). Bruce said it was pretty
much seamless using history, explaining it as you simply cross the
boundary to the next part of your app, treating it as the "next" app.
I also asked if they had any plans to further address this area,
anything new, and he said no, he thought History pretty well handled
it.
In his demo he used History to go through a GWT app, into another GWT
app, and then back (using the back button) all the way out to a
different completely non GWT app.
So though I am short on details, because I have not personally run
into this, I think it is just basic History usage? I will try to come
up with an example over the next few days, but I think it is just a
matter of changing the history token programmatically (user clicks on
something where you want to have it cross boundaries into a new app, a
different tab or such), and then redirecting or forwarding the user to
the next app with history in tact (so they can go back if they
choose).
On Feb 23, 11:41 pm, "Ian Bambury" <ianbamb...@gmail.com> wrote:
> Charlie? Anyone know?
>
> On 21/02/07, Ian Bambury <ianbamb...@gmail.com> wrote:
>
>
>
> > That is great news, just use History support?
>
> > BTW for me, a big app is 380kb with OBF but without compression
> > (because it's not my server), without images, for a user on dial-up
> > (maybe not even on 56kbps) who is paying by the minute.
>
> > So how do I split my 380kb into smaller chunks using History support?
>
> > Ian
>
On Feb 26, 12:01 pm, "Bruce Johnson" <b...@google.com> wrote:
> I'll try to distill it down to the a few main points, then we can tackle
> subsequent questions if this isn't clear enough.
>
> 1) Strive to combine code at the Java level instead of thinking in terms of
> multiple, separately-compiled modules. The best way to optimize for size is
> to combine modules together at the Java source level so that the compiler
> can optimize and obfuscate them together. The compiler has the most
> information about what you're trying to do, so more of the really cool
> global optimizations can be leveraged when you "stay in Java" as long as
> possible. This will essentially always be better than trying to include
> separately-compiled modules into the same page.
>
> 2) Never feel obligated to keep your GWT app to a single page. GWT history
> support works across pages. To see what I mean, do the following:
> - Run the KitchenSink demo athttp://code.google.com/webtoolkit/documentation/examples/kitchensink/...
> -http://groups.google.com/group/Google-Web-Toolkit/browse_thread/threa...
> -http://groups.google.com/group/Google-Web-Toolkit/browse_thread/threa...
>
> -- Bruce
"whenever you fear your app is becoming "too big" for a single page,
all you need to do is split it into multiple pages such that each page
has a unique module with a unique entry point. History smooths all the
page junction points"
OK, let's see if I've got it right...
"The best way to optimize for size is to combine modules together because GWT can use really cool optimisation techniques."
Right! So I combine the modules, yeah?
Wait a minute, Charlie says "use multiple modules to reduce the size"
Right, so loads of pages, loads of modules, loads of entry points, and everything is cool, hip, and groovey.
"They don't call it a Kitchen Sink Demo?"
"No, they got the metric system over there, they wouldn't know what the **** a Kitchen Sink is. But you're not French, so have a look at it."
OK, let's have a look, then. Multiple pages, loads of modules, more entry points that a Texas whorehouse, yeah?
Well, no. One page, one module, and one entry point.
Why, Bruce, why? Well because "this will essentially always be better than trying to include separately-compiled modules into the same page"
But you said...OK, I'm confused, but this is a History-based thread, let's forget that for a while. Tell me about History.
"History is the answer to apps that are 'too big'"
Yippee! Example?
"Le Kitchen Sink Demo"
Ah.
"Click through the first few vertical hyperlinks on the left side; observe that you are accumulating history events as you do this. Go to google.com and search for anything ;"
OK, done that. How is this demonstrating application size reduction?
"At this point, you've left Le Kitchen Sink and you're on a completely other page"
I was wondering about that.
"Click back 3 times to back into KitchenSink again; notice your history continues to work as if you'd never left the app"
Apart from losing everything I typed in, the tabs being reset, and the checkboxes and radio buttons losing state, that is perfectly true, yes.. All very clever, but how does this reduce the size of my *.cache.html files?
"Big apps should have history support"
OK...because?
"If you have an app that's big enough to be "too big" for a single page, then the app is big enough to have some sort of history support"
Is it really. Well I never. And presumably the converse is true, or why mention it: if it's not big enough to be "too big" then it's not big enough to have any sort of history support. There's logic for you. This is very interesting but it's not reducing the size of my *.cache.html files, is it? Is it possible for you to get to the point, please, my friend.
"history is a really important usability feature"
I know.
"History smooths all the page junction points"
That's nice. I hate rough page junction points. I always have. A rough junct...sorry, carry on.
"The compiler is smart enough to eliminate code you don't use from each page's entry point(s)."
So I think I've nearly got it now. Just one more thing, sir... What do I do to reduce the size of my app's files?
And as for "Apart from losing everything I typed in, the tabs being
reset, and the
checkboxes and radio buttons losing state, that is perfectly true,
yes.." Actually no, not at all, that is precisely why you would use
History.
As I said to begin with I do not personally have an example because I
have not had this problem - I was just trying to pass along what Bruce
said (and I think his comments were helpful, you appear to have taken
them a bit differently.)
> google.comand search for anything
The step 1 that Bruce outlined, as I read it, was get all your stuff
into one module and let the compiler do the optimizations. The other
steps were if that still ends up "too big", change directions and
split it into different modules. These were not contradictory, they
were two different approaches.
And as for "Apart from losing everything I typed in, the tabs being
reset, and the
checkboxes and radio buttons losing state, that is perfectly true,
yes.." Actually no, not at all, that is precisely why you would use
History.
As I said to begin with I do not personally have an example because I
have not had this problem - I was just trying to pass along what Bruce
said (and I think his comments were helpful, you appear to have taken
them a bit differently.)
There are a load of totally different issues running haywire here, so
let me try and address each:
First, terms and definitions:
HISTORY: Large apps should probably 'have it', but this by no means
helps, addresses, or is even tangentially related to reducing the
latency and/or bandwidth issues for large GWT apps.
MULTIPLE MODULES: You can have multiple modules, and have GWT compile
the lot down to 1 'web app'. However, only one of those modules may
have an entry point. Using 'library modules' is NO PROBLEM IN GWT - if
you use 1% of a module's features (say, only 1 simple widget from the
gwt-wl extension), GWT simply only compiles in that 1%, and the
remaining 99% simply never arrives. Hence, do NOT try to squash
multiple modules into a single one to reduce footprint, it doesn't do
jack except make your project an unmaintainable turd. Just Don't.
MULTIPLE MODULES WITH MULTIPLE ENTRYPOINTS: Usually this refers to the
idea that you 'lazy load' parts of the app: Have 2 or more essentially
completely separate (and thus separately compiled) gwt apps, and let
one open the other, say, in an iframe. This almost never works. While
you may address app load latency with this tactic, the total number of
bytes transferred increases significantly (the 'second' app reloads a
lot of logic already loaded in the first, and there's no practical way
to avoid that from happening). If you mean having multiple entrypoints
in 1 or more modules and compiling all this to 1 gwt app: That can NOT
BE DONE, period.
FOOTPRINT REDUCTION: This is the central idea that the 'app takes too
long to load'. Unfortunately, that is totally pointless information.
That's because there are a couple of, wholly separate, issues.
1. RUNNING BANDWIDTH: This refers to bandwidth that a client needs in
order to comfortably work with the GWT app once it's already loaded.
If, for example, you have some huge grid that gets updated every 5
seconds, that's a phat pipe requirement right there. That's something
GWT can't help you with directly, you'll just have to get smarter
about caching stuff. Entirely your show, there are no libraries here
that help you much. This applies only to apps that use GWT-RPC (or
RequestBuilder) a lot. Check e.g. gpokr, which has low running
bandwidth, but it is there (the chat and cards data is continuously
sent).
2. INITIAL BANDWIDTH: This refers to the number of kilobytes that gets
sent down the pipe to someone with a clean cache. Note that GWT is
very smart with caching (if nothing changed, then only a tiny file is
reloaded, the rest can come from browser cache, and usually does). GWT
apps fall somewhere in the 150k to 900k load, which is ridiculously
small for large webapps. Even a huge GWT app ends up being relatively
small. In short: Don't worry about it. Where this doesn't work, check
if you have huge tables in code someplace, and load those in a
different, more dynamic way. Splitting up the code base to lazy-load
is difficult and usually fruitless. To figure out exactly how much
bandwidth is used by your app, get firebug (getfirebug.com) for
firefox and check the 'net' tab for a nice overview of what gets
loaded when a user navigates to your GWT app.
3. INITIAL LATENCY: This refers to the amount of time the browser is
effectively idling, waiting for a request or two to make their way
across e.g. an atlantic cable. The primary reason for latency problems
is having a metric buttload of images. The solution for this is
'ClippedImage', a neat trick available in GWT 1.4. Read all about it
at Robert's blog here: http://roberthanson.blogspot.com/2007/02/gwt-clippedimage-optimizing-image.html.
To solve this, make stuff as monolithic as you can: A single image
instead of a tonne, a single CSS sheet, a single huge JS file with all
the libraries you've used in there, etcetera. GWT 1.4 will help. Also
check the *.gwt.xml format for including external js files in the
monolothic gwt-generated JS. Check the net tab of firebug, again, to
see latency delays in action. And see Robert's blog, he explains why
monolithizing stuff works so well in making the app load faster.
4. LOAD FREEZE: While GWT is actually running, the web browser is
effectively frozen. If you actually 'render' ALL of your web-app's
content (create the panels, buttons, labels, images, checkboxes,
choiceboxes, grids, tables, textboxes, forms, blablabla) then the
browser can take many seconds just hanging there. The solution to this
problem is simple: lazy rendering. The idea being that you render
stuff only when it gets actually drawn. Check the kitchen sink.
MISCONCEPTIONS:
There are at least 4 DFHAJSFHASwtfAreAllTheseLettersForSDFJASDJHD.html
files generated during compilation. Well, those letters are hashes of
all relevant methods of that particular compilation run (the idea
being, if nothing changes, the browser grabs the cached version
instead, but if you change something, that the changes propagate
immediatly without all your users having to clear cache first. It's a
nifty system. Say 'oooooooh!' and move on). The rub is: Each of those
files is a specific version for a specific browser. One of them is for
IE, one for safari/webkit, one for opera, and one for the firefox/
gecko. ONLY ONE OF THOSE is downloaded by each client, not ALL OF
THEM. Yet again, see your local firebug net tab to confirm this.
Now please stop being a buffoon, though I admit your, um, inspired
writing at least deserves points for trying to write an enjoyable
flame.
And be more specific in what your problem is.
Just to explain what I mean: Say to register as a new user, you just
fill in an email address. Then, the 'activation link' mail that gets
sent to you takes you to a page where you fill in your name, preferred
password, etcetera, and from there on you go straight to the 'logged
in' homepage. Thus this app really has 4 different 'entry points':
1. No cookie at all: Some sort of 'hey, welcome, how's life, my app
r00lz, join up, puhlease' thing.
2. A cookie, which after an RPC call doesn't appear to be valid, OR a
cookie of the type: The guy logged out manually but he's been here
before (note that you need to make these cookies yourself with e.g.
Cookies.setCookie). Here you show a 'log in' thing.
3. Cookie is there, and valid, go straight to already logged in page.
4. The guy clicked the activation link.
In all cases you can just start at the main entrypoint. Case #1, #2
and #3 are differentiated by way of cookies and some tactical RPC
calls.
Case #4 can be differentiated by checking the location URL
(WindowUtils has it, I think). e.g. while GWT is a totally static
show; it's just html and js files, you can still make a link of the
type:
http://www.myserver.com/mygwtapp.html?actkey=1239420948
- just that the server doesn't do anything with that actkey. Still,
it's in the URL (unless your apache or tomcat or jetty or whatnot is
configured to redirect, so don't do that) which you can query on the
client side (read: in GWT). Thus GWT can get at that 'actkey' thing,
realize what's going on (clicked activation link), and GWT-RPC or
RequestBuild your way out of it, and show the right screen.
Note that for this one app with 4 different entry use cases, you can
address it all with just 1 actual 'entrypoint' which does some checks
on the URL and on the cookies.
> at Robert's blog here:http://roberthanson.blogspot.com/2007/02/gwt-clippedimage-optimizing-....
On Mar 1, 8:00 pm, "Ian Bambury" <ianbamb...@gmail.com> wrote:
> Bruce says: History is the answer to apps that are "too big".
>
Bruce was... well, not wrong, but for the sake of argument let's say
that he was. In the sense that with what you are doing, don't look at
history. If you absolutely must go with multiple separately compiled
GWT apps that are patched up together, history is one way to
communicate back and forth, but, yuck. That's the absolute last
resort.
>
> Example? I can't do this. And what use is it? I would have said that one
> module WAS one web app.
>
Any GWT app - you 'include' com.google.gwt.user.User, don't you?
Actually, "User" is just a combotarget that includes 8 or 9 other web
apps (search the source tree for User.gwt.xml, check it out). The use
is obviously the same use for GWT itself: The ability to partition
your code. If you e.g. have an admin interface and a client interface,
you can toss the common bits into a 'common' project, the client bits
in a client project, and the admin bits in an admin project, with the
client and admin projects 'including' the common project.
Normally in JS land that sucks, because it implies the bits that are
included but unused take up valuable bandwidth/latency, but in GWT,
the compiler just doesn't add whatever isn't used. Joy.
> Well, I would have thought that every module would have to have at least
> one entry point or how else do you get into it? Plus I've got modules with
> more than one entry point which work quite happily.
You don't, you just use the classes. com.google.gwt.user.User has no
entry point. Neither does the gwt-wl extension. Neither does that
'common' hypothetical project I mentioned before.
>
> Well, the KS is held up as an example of lazy loading and it doesn't do
> this, it creates content on the fly within one module and doesn't use
> iframes for it.
>
KS does lazy building/rendering, not lazy loading. However, sometimes
'lazy building' or 'lazy rendering' is called 'lazy loading' which is
confusing, but there you have it.
>
> Sorry,http://write.roughian.comloads into iframes. It works. The iframe
> pages run off the main page cache.html files, and the nocache.html file gets
> a 304. Anything in it that appears when you click a tab is loaded in an
> iframe.
>
It doesn't "work" in the sense that it doesn't actually make your app
load any faster. You can make it fysically be not buggy, obviously.
It's the last resort and it's not pretty. Don't.
> Maybe for you, and maybe you don't care about people on dial-up who pay by
> the minute. Not everywhere in the world has access to DSL and not everyone
> can afford it. 900kb at 28.8kbps is in the region of 6 minutes. It may be
> ridiculously small to you but it takes a long time for them.
You're talking out your ass. For one, which idiot would want to use a
heavy web app @ 29.8 kbs? This is 2007! Check out digg (3MB homepage),
or gmail, and you'll find that 1MB is on the low end.
If you have 'special needs', why in @%#$*(#$'s name are you using a
wrapper toolkit? OBVIOUSLY you'll have to hand code the javascript
with painstaking detail if you want the absolute least amount of code
download. You'll probably multiply dev times (and buggyness) by a
factor 10 while you're at it, but, hey. I want a pony too.
What you want; Splitting the module up will not be kind to dailuppers
or by-the-minute folk, because it's actually MORE SHIT TO DOWNLOAD.
It's just that the downloads are spread out more instead of having to
be done up front, which might create the impression that the app is
somewhat more responsive. It might be slightly less if they don't do
anything after the page load, but don't you think it makes waaay more
sense to make a separate (probably not GWT based) 'view' page where
you can get some simple views on the data suitable for e.g. the tiny
display of a mobile phone? Trying to make one GWT app work for
everything is retarded.
>
> Cheers,
>
Indeed. At this point I'd just like to state that everyone has been
either answering your exact question point blank (which confused you),
or advising you, STRONGLY, *NOT* to try to split up your app in twain
and use some sort of iframes arrangement with communication through
history tokens. Given that those who gave that advice are far more
skilled at using GWT than you, please take a moment to think of a term
that adequately covers your current insistence on ignoring it. I've
already given it a shot but your negative reaction to said term seems
to indicate I may have been way off the mark. So I'll let you come up
with your own term for your current behaviour.
Cheers!
Only fair guys are admitted on this forum :) no battle on this forum.
Only guys in the same way for making the GWT technology growing and
growing more and more and crunching the old manner to deal with ajax
process :)
Cheers.
Luciano
On Mar 2, 12:04 am, "Ian Bambury" <ianbamb...@gmail.com> wrote:
> On 01/03/07, Reinier Zwitserloot <reini...@gmail.com> wrote:
>
> > On Mar 1, 8:00 pm, "Ian Bambury" <ianbamb...@gmail.com> wrote:
> > > Bruce says: History is the answer to apps that are "too big".
>
> > Bruce was... well, not wrong, but for the sake of argument let's say
> > that he was. In the sense that with what you are doing, don't look at
> > history.
>
> Reinier, I can only go by what is said. If someone from the Google GWT
> development team says that History is the answer to the problem of large (my
> definition of 'large') GWT applications, then I'm sure that you would be one
> of the first to call me a fool (or worse) for deciding that I was going to
> ignore the advice he seemed to be offering.
>
> > If you absolutely must go with multiple separately compiled
> > GWT apps that are patched up together, history is one way to
> > communicate back and forth, but, yuck. That's the absolute last
> > resort.
>
> I don't have multiple separately compiled GWT apps that are patched up
> together, I have one application which is larger than I would like. The one
> using iframes was developed just as a proof of concept. I also have another
> which loads into iframes and then attaches code to the DOM of the parent
> frame. It is also just an experiment.
>
> > > Example? I can't do this. And what use is it? I would have said that one
> > > module WAS one web app.
>
> > Any GWT app - you 'include' com.google.gwt.user.User, don't you?
> > > Sorry,http://write.roughian.comloadsinto iframes. It works. The iframe