Merge lp:~tveronezi/juju-gui/uglify into lp:juju-gui/experimental
- uglify
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 235 | ||||
Proposed branch: | lp:~tveronezi/juju-gui/uglify | ||||
Merge into: | lp:juju-gui/experimental | ||||
Diff against target: |
664 lines (+398/-115) 11 files modified
.bzrignore (+1/-0) Makefile (+21/-3) app/index.html (+3/-3) app/modules-debug.js (+131/-0) app/modules.js (+7/-104) bin/merge-files (+75/-0) grunt.js (+1/-1) lib/merge-files.js (+137/-0) lib/server.js (+19/-2) package.json (+2/-1) test/index.html (+1/-1) |
||||
To merge this branch: | bzr merge lp:~tveronezi/juju-gui/uglify | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Benji York (community) | code | Approve | |
Review via email: mp+133116@code.launchpad.net |
Commit message
Description of the change
Resource minification/
* We should aggregate and minimize the js sources in order to improve the load speed of the application;
* We dont want to use the yui combo loader feature;
* The final product will provide three js files: one for the YUI dependencies, one for our custom js code and one for third part js like d3.
Thiago Veronezi (tveronezi) wrote : | # |
- 233. By Thiago Veronezi
-
using yui loop functions
Thiago Veronezi (tveronezi) wrote : | # |
https:/
File merge-files.js (right):
https:/
merge-files.js:25: function loop(arr, callback) {
Please ignore this method. I am using the Y.each version of it.
Thiago Veronezi (tveronezi) wrote : | # |
https:/
File merge-files.js (right):
https:/
merge-files.js:148:
I've already removed this blank line.
- 234. By Thiago Veronezi
-
generated combined files should go under /app/Error: listen EADDRINUSE
Thiago Veronezi (tveronezi) wrote : | # |
Please take a look.
- 235. By Thiago Veronezi
-
the combine code should go under the combine directory
- 236. By Thiago Veronezi
-
the combine code should go under the combine directory
Thiago Veronezi (tveronezi) wrote : | # |
Please take a look.
Thiago Veronezi (tveronezi) wrote : | # |
Thanks, Benji!
https:/
File Makefile (right):
https:/
Makefile:12: node_modules/grunt node_modules/
node_modules/
This line does not have more than 80 chars, but I changed it anyway.
On 2012/11/07 17:05:18, benji wrote:
> This line is too long.
https:/
Makefile:75: @cp app/assets/
app/assets/
On 2012/11/07 17:05:18, benji wrote:
> This line is too long.
Done.
https:/
Makefile:80: @cp app/assets/
app/assets/
On 2012/11/07 17:05:18, benji wrote:
> This line is too long.
Done.
https:/
File app/assets/
https:/
app/assets/
This is entirely ours.
On 2012/11/07 17:05:18, benji wrote:
> Is this code we wrote or was it imported from somewhere? If it was
written
> elsewhere, we need to specify its license and it would be nice to know
where it
> came from.
> I will forgo reviewing the code until I know the answers to the above.
https:/
File app/index.html (right):
https:/
app/index.html:72: <script src="/source/
What about '/assets/yui.js'? Id this ok?
On 2012/11/07 17:05:18, benji wrote:
> We have been calling these things "assets". If the change to "source"
was a
> considered one, then I am fine with it. If not, we should continue to
use the
> same terminology that we have been using.
https:/
File lib/server.js (right):
https:/
lib/server.js:50: server.
{
I want to hide the real path.
I can change it to '/assets/
On 2012/11/07 17:05:18, benji wrote:
> Why should the path exposed via HTTP ("source") be different than the
path on
> disk ("assets")?
- 237. By Thiago Veronezi
-
code review
Gary Poster (gary) wrote : | # |
Hi Thiago. Thank you for this nice step forward: it will be great when
we have this functionality, and the debug/developer story you've
arranged is nicer than I expected.
This is a preliminary review. As I mention, I want to review
merge-files.js more later, but I'm going to let Benji take a first pass
and send my notes so far to you sooner.
Gary
https:/
File Makefile (right):
https:/
Makefile:64: combinejs: $(NODE_TARGETS)
As I mentioned on IRC, this has the same problem we talked about with
sprite generation: every time you run the target it will try to compress
the files. Since install depends on this, and just about everything
depends on install, this can affect most make targets and be pretty
annoying.
One approach to solving this is http://
https:/
Makefile:89: @rm -Rf app/assets/
Good.
https:/
Makefile:107: combinejs
Good.
https:/
File app/assets/
https:/
app/assets/
I don't think this file belongs in app/assets. This is a build
component, and we never want to serve it as part of the application. I
suggest that we put it in the top directory, or in bin. I lean towards
bin.
This is as good a time as any to mention that I think this branch is a
great example of something that could have probably benefitted from a
pre-implementation call (and maybe a prototyping).
https:/
app/assets/
http://
Nice that you gave attribution. I personally don't think it is
necessary in this case. It was good to see as a reviewer, but it would
have been even better as part of your "cover letter" introduction to
your branch.
https:/
app/assets/
Why did you choose to do this rather than "YUI().use(..., function(Y)
{...});"?
You could even remove line 4. One approach:
require(
another approach:
var Y = require(
https:/
app/assets/
I have a number of comments I already suspect I want to make about this
file--here, for instance, I think I will request that you add a lot more
comments, and possibly refactor, and possibly reconsider your approach
to compartmentalizing the various parts of the file. However, I
conferred with Benji, and I am going to be lazy and see what he has to
say first, and then follow along afterwards. That way I can get my
other comments to you faster.
https:/
Thiago Veronezi (tveronezi) wrote : | # |
Thanks Gary.
https:/
File Makefile (right):
https:/
Makefile:64: combinejs: $(NODE_TARGETS)
On 2012/11/07 20:49:31, gary.poster wrote:
> As I mentioned on IRC, this has the same problem we talked about with
sprite
> generation: every time you run the target it will try to compress the
files.
> Since install depends on this, and just about everything depends on
install,
> this can affect most make targets and be pretty annoying.
> One approach to solving this is http://
Done.
https:/
Makefile:75: @cp app/assets/
app/assets/
On 2012/11/07 17:05:18, benji wrote:
> This line is too long.
Done.
https:/
Makefile:89: @rm -Rf app/assets/
On 2012/11/07 20:49:31, gary.poster wrote:
> Good.
Done.
https:/
Makefile:107: combinejs
On 2012/11/07 20:49:31, gary.poster wrote:
> Good.
Done.
https:/
File app/assets/
https:/
app/assets/
On 2012/11/07 20:49:31, gary.poster wrote:
> I don't think this file belongs in app/assets. This is a build
component, and
> we never want to serve it as part of the application. I suggest that
we put it
> in the top directory, or in bin. I lean towards bin.
> This is as good a time as any to mention that I think this branch is a
great
> example of something that could have probably benefitted from a
> pre-implementation call (and maybe a prototyping).
This branch had a pre-implementation call. I moved this file here
because Ben asked me to do it.
https:/
app/assets/
http://
On 2012/11/07 20:49:31, gary.poster wrote:
> Nice that you gave attribution. I personally don't think it is
necessary in
> this case. It was good to see as a reviewer, but it would have been
even better
> as part of your "cover letter" introduction to your branch.
This is not part of the global solution. This is here just to explain
why I use the "global" object.
https:/
app/assets/
On 2012/11/07 20:49:31, gary.poster wrote:
> Why did you choose to do this rather than "YUI().use(..., function(Y)
{...});"?
> You could even remove line 4. One approach:
> require(
> another approach:
> var Y = require(
I did it because I dont require any internal yui code. I use it to get
the Y.Object, Y.Array and Y.Loader objects.
I cannot remove the line 4. It is used by the line 82. When node
executes...
- 238. By Thiago Veronezi
-
code review
- 239. By Thiago Veronezi
-
trunk merge
- 240. By Thiago Veronezi
-
code review
- 241. By Thiago Veronezi
-
code review
Thiago Veronezi (tveronezi) wrote : | # |
Tkx Benji.
https:/
File Makefile (right):
https:/
Makefile:12: node_modules/grunt node_modules/
node_modules/
On 2012/11/07 22:00:47, benji wrote:
> On 2012/11/07 18:59:19, thiago wrote:
> > This line does not have more than 80 chars, but I changed it anyway.
> Correct, it has fewer than 80 characters but one of those characters
is a tab,
> which in most editors displays as 8 spaces, pushing the line over 80
displayed
> characters.
Ok
https:/
File app/assets/
https:/
app/assets/
On 2012/11/07 22:00:47, benji wrote:
> On 2012/11/07 18:59:19, thiago wrote:
> > This is entirely ours.
> Top-posting makes replying to comments difficult. Please reply below
the
> previous comment.
Ok
https:/
app/assets/
http://
On 2012/11/07 22:00:47, benji wrote:
> Even after reading the page at the other end of this link I don't know
what it
> has to do with the code here. Additional comments would help.
Done.
https:/
app/assets/
On 2012/11/07 22:00:47, benji wrote:
> I am surprised that we had to write this script. I would have
expected someone,
> somewhere to have already done this for us.
Not really. People usually use the comboloader for yui applications. I
had a lot of fun writing it though.
https:/
app/assets/
compressor.minify({
On 2012/11/07 22:00:47, benji wrote:
> object literal style
How should it be?
https:/
app/assets/
On 2012/11/07 22:00:47, benji wrote:
> This function would benefit from a name.
This is not a function. This is an object: a list of all the yui
requirements we need to load.
https:/
app/assets/
http://
On 2012/11/07 22:00:47, benji wrote:
> I am not sure what this comment is trying to communicate. Is it that
I can find
> an explanation of the YUI loader mechanism at the given URL?
Nop. It uses the reqs object that we created in the previous block and
figures out the js files that contain it.
I will add it as comment here.
https:/
app/assets/
On 2012/11/07 22:00:47, benji wrote:
> object literal sty...
- 242. By Thiago Veronezi
-
making lint happy
Thiago Veronezi (tveronezi) wrote : | # |
Please take a look.
- 243. By Thiago Veronezi
-
missing commit
Thiago Veronezi (tveronezi) wrote : | # |
https:/
File Makefile (right):
https:/
Makefile:12: node_modules/grunt node_modules/
node_modules/
Missing commit. You should see this line break in the next commit.
- 244. By Thiago Veronezi
-
code review
- 245. By Thiago Veronezi
-
code review
- 246. By Thiago Veronezi
-
moving the functions to the lib directory
Thiago Veronezi (tveronezi) wrote : | # |
Please take a look.
Thiago Veronezi (tveronezi) wrote : | # |
https:/
File bin/merge-files (right):
https:/
bin/merge-files:20: global.YUI = require('yui').YUI;
Please ignore this entry. I moved it to the lib/merge-files.js file.
=== modified file 'bin/merge-files'
--- bin/merge-files 2012-11-09 12:54:56 +0000
+++ bin/merge-files 2012-11-09 13:00:19 +0000
@@ -14,12 +14,7 @@
'use strict';
-// We need the yui name to be available in all modules (as a global
variable).
-// This only happens if we remove the 'var' keyword or add it to the
"global"
-// variable.
-global.YUI = require('yui').YUI;
-
-YUI().use(['yui'], function(Y) {
+require(
var merge = require(
syspath = require('path'),
paths,
- 247. By Thiago Veronezi
-
code review
Gary Poster (gary) wrote : | # |
This is looking good, Thiago. Thank you!
As we discussed, I'm OK with holding off on tests. The last non-trivial
thing I'd like to see is removing the code that writes properties. I
give two possible approaches below.
I'm happy to have a call if it helps, or leave it to you, as you prefer.
Thanks!
Gary
https:/
File Makefile (right):
https:/
Makefile:82: @./bin/
I really would like to see this (and the corresponding line in 87 and
the corresponding "write-properties" script) go.
My preferred approach, which we talked about yesterday, would be to make
the server always have both the debug version (debug.html?) and the
production version (index.html) available, by having the server
dynamically change the js files that index.html points to.
Alternatively, server.js would accept an argument to turn on debug mode.
By default, it would run in prodcution mode.
https:/
File app/modules-
https:/
app/modules-
An idea (as in, do this if you agree): it would be nice to have a
comment at the top of this file saying that it is only used for the
debug (developer) views of the application, and pointing to the
mechanism that is used (e.g., in server.js) to serve this file rather
than the other one.
Maybe it's overkill. I'd do it, but I'd be fine with accepting
disagreement.
https:/
File app/modules.js (right):
https:/
app/modules.js:4: ignoreRegistered: true,
Is there a setting we can use to say "never download anything from the
internet, ever"? If so, I suggest we use that both for this and the
debug modules file.
Is it bootstrap: false? Or is this already handled somehow?
https:/
File bin/merge-files (right):
https:/
bin/merge-files:1: #!/usr/bin/env node
These changes look great to me. Thanks.
https:/
bin/merge-files:4: * We should aggregate and minimize the js sources in
order to improve the load
suggestion: delete "should". (We are doing it. :-) )
https:/
bin/merge-files:8: * to run from only static files and we want to be
able to run behaind a
"behind" (I realize these are probably my fault. sorry :-) )
https:/
File bin/write-
https:/
bin/write-
As I said, I'd like to delete.
https:/
File lib/merge-files.js (right):
https:/
lib...
Thiago Veronezi (tveronezi) wrote : | # |
https:/
File Makefile (right):
https:/
Makefile:82: @./bin/
On 2012/11/09 13:57:38, gary.poster wrote:
> I really would like to see this (and the corresponding line in 87 and
the
> corresponding "write-properties" script) go.
> My preferred approach, which we talked about yesterday, would be to
make the
> server always have both the debug version (debug.html?) and the
production
> version (index.html) available, by having the server dynamically
change the js
> files that index.html points to.
> Alternatively, server.js would accept an argument to turn on debug
mode. By
> default, it would run in prodcution mode.
Using the server approach for now.
Thanks for this idea. Really good.
https:/
File app/modules-
https:/
app/modules-
On 2012/11/09 13:57:38, gary.poster wrote:
> An idea (as in, do this if you agree): it would be nice to have a
comment at the
> top of this file saying that it is only used for the debug (developer)
views of
> the application, and pointing to the mechanism that is used (e.g., in
server.js)
> to serve this file rather than the other one.
> Maybe it's overkill. I'd do it, but I'd be fine with accepting
disagreement.
Done.
https:/
File bin/merge-files (right):
https:/
bin/merge-files:1: #!/usr/bin/env node
On 2012/11/09 13:57:38, gary.poster wrote:
> These changes look great to me. Thanks.
Done.
https:/
bin/merge-files:4: * We should aggregate and minimize the js sources in
order to improve the load
On 2012/11/09 13:57:38, gary.poster wrote:
> suggestion: delete "should". (We are doing it. :-) )
Done.
https:/
bin/merge-files:8: * to run from only static files and we want to be
able to run behaind a
On 2012/11/09 13:57:38, gary.poster wrote:
> "behind" (I realize these are probably my fault. sorry :-) )
Done.
https:/
File bin/write-
https:/
bin/write-
On 2012/11/09 13:57:38, gary.poster wrote:
> As I said, I'd like to delete.
Done.
https:/
File lib/merge-files.js (right):
https:/
lib/merge-
On 2012/11/09 13:57:38, gary.poster wrote:
> Another option (up to you): remove this comment, and do the export of
each
> function as you define it ("expose.minify = function(file) {...}" for
instance)
> or immediately after you define it.
Done.
https:/
- 248. By Thiago Veronezi
-
code review
- 249. By Thiago Veronezi
-
add comments about 'bootstrap=false'
Thiago Veronezi (tveronezi) wrote : | # |
https:/
File app/modules.js (right):
https:/
app/modules.js:4: ignoreRegistered: true,
On 2012/11/09 13:57:38, gary.poster wrote:
> Is there a setting we can use to say "never download anything from the
internet,
> ever"? If so, I suggest we use that both for this and the debug
modules file.
> Is it bootstrap: false? Or is this already handled somehow?
We agreed that it wont be possible to use it. I've added comments about
this know issue in the "merge-files" file.
- 250. By Thiago Veronezi
-
add comments about 'bootstrap=false'
Thiago Veronezi (tveronezi) wrote : | # |
Please take a look.
Gary Poster (gary) wrote : | # |
Hi Thiago. This looks good to me.
Per our discussions:
- We are foregoing tests on the lib functions. You can see now how you
would do them. You might do a follow-up branch with tests or might not.
I would be happy to see that change. However, I won't stop you from
landing this without them.
- We are foregoing the "bootstrap=false" change that forces us to keep
from downloading files. It would be a nice seatbelt but it had problems
that you documented.
Thank you!
Gary
https:/
File Makefile (right):
https:/
Makefile:83: @node server.js debug
yay, much nicer, thanks
https:/
File app/modules-
https:/
app/modules-
Great.
Benji York (benji) : | # |
- 251. By Thiago Veronezi
-
trunk merge
Thiago Veronezi (tveronezi) wrote : | # |
*** Submitted:
Resource minification/
* We should aggregate and minimize the js sources in order to improve
the load speed of the application;
* We dont want to use the yui combo loader feature;
* The final product will provide three js files: one for the YUI
dependencies, one for our custom js code and one for third part js like
d3.
R=benji, gary.poster
CC=
https:/
Preview Diff
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2012-10-31 09:16:13 +0000 |
3 | +++ .bzrignore 2012-11-09 20:53:21 +0000 |
4 | @@ -20,3 +20,4 @@ |
5 | yuidoc |
6 | app/assets/manifest.appcache |
7 | app/assets/sprite |
8 | +app/assets/javascripts/generated/ |
9 | |
10 | === modified file 'Makefile' |
11 | --- Makefile 2012-11-06 13:16:34 +0000 |
12 | +++ Makefile 2012-11-09 20:53:21 +0000 |
13 | @@ -9,10 +9,15 @@ |
14 | node_modules/mocha node_modules/d3 node_modules/graceful-fs \ |
15 | node_modules/should node_modules/jshint node_modules/expect.js \ |
16 | node_modules/express node_modules/yui node_modules/yuidoc \ |
17 | - node_modules/grunt node_modules/node-spritesheet |
18 | + node_modules/grunt node_modules/node-spritesheet \ |
19 | + node_modules/node-minify |
20 | TEMPLATE_TARGETS=$(shell bzr ls -k file app/templates) |
21 | SPRITE_SOURCE_FILES=$(shell bzr ls -R -k file app/assets/images) |
22 | SPRITE_GENERATED_FILES=app/assets/sprite/sprite.css app/assets/sprite/sprite.png |
23 | +COMPRESSED_FILES=app/assets/javascripts/generated/all-app-debug.js \ |
24 | + app/assets/javascripts/generated/all-app.js \ |
25 | + app/assets/javascripts/generated/all-third.js \ |
26 | + app/assets/javascripts/generated/all-yui.js |
27 | DATE=$(shell date -u) |
28 | APPCACHE=app/assets/manifest.appcache |
29 | |
30 | @@ -37,7 +42,7 @@ |
31 | @ln -sf `pwd`/node_modules/yui ./app/assets/javascripts/ |
32 | @ln -sf `pwd`/node_modules/d3/d3.v2* ./app/assets/javascripts/ |
33 | |
34 | -install: appcache $(NODE_TARGETS) app/templates.js yuidoc spritegen |
35 | +install: appcache $(NODE_TARGETS) app/templates.js yuidoc spritegen combinejs |
36 | |
37 | gjslint: virtualenv/bin/gjslint |
38 | @virtualenv/bin/gjslint --strict --nojsdoc --jslint_error=all \ |
39 | @@ -61,11 +66,22 @@ |
40 | |
41 | spritegen: $(SPRITE_GENERATED_FILES) |
42 | |
43 | +$(COMPRESSED_FILES): node_modules/yui node_modules/d3/d3.v2.min.js $(JSFILES) |
44 | + @rm -Rf app/assets/javascripts/generated/ |
45 | + @mkdir app/assets/javascripts/generated/ |
46 | + @./bin/merge-files |
47 | + |
48 | +combinejs: $(COMPRESSED_FILES) |
49 | + |
50 | prep: beautify lint |
51 | |
52 | test: install |
53 | @./test-server.sh |
54 | |
55 | +debug: install |
56 | + @echo "Customize config.js to modify server settings" |
57 | + @node server.js debug |
58 | + |
59 | server: install |
60 | @echo "Customize config.js to modify server settings" |
61 | @node server.js |
62 | @@ -75,6 +91,7 @@ |
63 | @make -C docs clean |
64 | @rm -Rf bin/sprite/ |
65 | @rm -Rf app/assets/sprite/ |
66 | + @rm -Rf app/assets/javascripts/generated/ |
67 | |
68 | $(APPCACHE): manifest.appcache.in |
69 | @cp manifest.appcache.in $(APPCACHE) |
70 | @@ -91,4 +108,5 @@ |
71 | appcache-force: appcache-touch appcache |
72 | |
73 | .PHONY: test lint beautify server install clean prep jshint gjslint \ |
74 | - appcache appcache-touch appcache-force yuidoc spritegen yuidoc-lint |
75 | + appcache appcache-touch appcache-force yuidoc spritegen yuidoc-lint \ |
76 | + combinejs |
77 | |
78 | === modified file 'app/index.html' |
79 | --- app/index.html 2012-11-01 13:21:53 +0000 |
80 | +++ app/index.html 2012-11-09 20:53:21 +0000 |
81 | @@ -69,9 +69,9 @@ |
82 | <div id="vp-right-border"></div> |
83 | </div> |
84 | <!-- javascript away --> |
85 | - <script src="/juju-ui/assets/javascripts/yui/yui/yui-debug.js"></script> |
86 | - <script src="/juju-ui/modules.js"></script> |
87 | - <script src="/config.js"></script> |
88 | + <script src="/assets/yui.js"></script> |
89 | + <script src="/assets/all-third.js"></script> |
90 | + <script src="/assets/modules.js"></script> |
91 | <script> |
92 | YUI(GlobalConfig).use(["juju-gui"], function(Y) { |
93 | app = new Y.juju.App(juju_config); |
94 | |
95 | === added file 'app/modules-debug.js' |
96 | --- app/modules-debug.js 1970-01-01 00:00:00 +0000 |
97 | +++ app/modules-debug.js 2012-11-09 20:53:21 +0000 |
98 | @@ -0,0 +1,131 @@ |
99 | +// This file is used for development only. In order to use it you should call |
100 | +// the "make debug" command. This command passes the "debug" argument to the |
101 | +// "lib/server.js". |
102 | +GlobalConfig = { |
103 | + filter: 'debug', |
104 | + // Set "true" for verbose logging of YUI |
105 | + debug: false, |
106 | + |
107 | + // Use Rollups |
108 | + combine: false, |
109 | + |
110 | + groups: { |
111 | + d3: { |
112 | + modules: { |
113 | + 'd3': { |
114 | + 'fullpath': '/juju-ui/assets/javascripts/d3.v2.min.js' |
115 | + } |
116 | + } |
117 | + }, |
118 | + juju: { |
119 | + modules: { |
120 | + // Primitives |
121 | + |
122 | + 'svg-layouts': { |
123 | + fullpath: '/juju-ui/assets/javascripts/svg-layouts.js' |
124 | + }, |
125 | + |
126 | + 'reconnecting-websocket': { |
127 | + fullpath: '/juju-ui/assets/javascripts/reconnecting-websocket.js' |
128 | + }, |
129 | + |
130 | + // Views |
131 | + 'juju-view-utils': { |
132 | + fullpath: '/juju-ui/views/utils.js' |
133 | + }, |
134 | + |
135 | + 'juju-charm-panel': { |
136 | + fullpath: '/juju-ui/views/charm-panel.js' |
137 | + }, |
138 | + |
139 | + 'juju-notifications': { |
140 | + fullpath: '/juju-ui/views/notifications.js' |
141 | + }, |
142 | + |
143 | + 'juju-view-environment': { |
144 | + fullpath: '/juju-ui/views/environment.js' |
145 | + }, |
146 | + |
147 | + 'juju-view-service': { |
148 | + fullpath: '/juju-ui/views/service.js' |
149 | + }, |
150 | + |
151 | + 'juju-view-unit': { |
152 | + fullpath: '/juju-ui/views/unit.js' |
153 | + }, |
154 | + |
155 | + 'juju-view-charm-collection': { |
156 | + fullpath: '/juju-ui/views/charm.js' |
157 | + }, |
158 | + |
159 | + 'juju-view-charm': { |
160 | + fullpath: '/juju-ui/views/charm.js' |
161 | + }, |
162 | + |
163 | + 'juju-templates': { |
164 | + fullpath: '/juju-ui/templates.js' |
165 | + }, |
166 | + |
167 | + 'juju-views': { |
168 | + use: [ |
169 | + 'juju-templates', |
170 | + 'juju-notifications', |
171 | + 'juju-view-utils', |
172 | + 'juju-view-environment', |
173 | + 'juju-view-service', |
174 | + 'juju-view-unit', |
175 | + 'juju-view-charm', |
176 | + 'juju-view-charm-collection' |
177 | + ] |
178 | + }, |
179 | + |
180 | + // Models |
181 | + 'juju-endpoints': { |
182 | + fullpath: '/juju-ui/models/endpoints.js' |
183 | + }, |
184 | + |
185 | + 'juju-charm-models': { |
186 | + requires: ['juju-charm-id'], |
187 | + fullpath: '/juju-ui/models/charm.js' |
188 | + }, |
189 | + |
190 | + 'juju-models': { |
191 | + requires: [ |
192 | + 'model', 'model-list', 'juju-endpoints', 'juju-charm-models'], |
193 | + fullpath: '/juju-ui/models/models.js' |
194 | + }, |
195 | + |
196 | + // Connectivity |
197 | + 'juju-env': { |
198 | + requires: ['reconnecting-websocket'], |
199 | + fullpath: '/juju-ui/store/env.js' |
200 | + }, |
201 | + |
202 | + 'juju-notification-controller': { |
203 | + fullpath: '/juju-ui/store/notifications.js' |
204 | + }, |
205 | + |
206 | + 'juju-charm-store': { |
207 | + requires: ['juju-charm-id'], |
208 | + fullpath: '/juju-ui/store/charm.js' |
209 | + }, |
210 | + |
211 | + 'juju-controllers': { |
212 | + use: ['juju-env', 'juju-charm-store', |
213 | + 'juju-notification-controller'] |
214 | + }, |
215 | + |
216 | + // App |
217 | + 'juju-gui': { |
218 | + fullpath: '/juju-ui/app.js', |
219 | + requires: [ |
220 | + 'juju-controllers', |
221 | + 'juju-views', |
222 | + 'juju-models', |
223 | + 'juju-view-charm-search' |
224 | + ] |
225 | + } |
226 | + } |
227 | + } |
228 | + } |
229 | +}; |
230 | |
231 | === modified file 'app/modules.js' |
232 | --- app/modules.js 2012-11-01 13:30:58 +0000 |
233 | +++ app/modules.js 2012-11-09 20:53:21 +0000 |
234 | @@ -1,69 +1,11 @@ |
235 | GlobalConfig = { |
236 | - // Uncomment for debug versions of YUI. |
237 | - filter: 'debug', |
238 | - // Uncomment for verbose logging of YUI |
239 | debug: false, |
240 | - |
241 | - // Use Rollups |
242 | - combine: false, |
243 | + // YUI will not download the modules. They are supposed to be already loaded. |
244 | + ignoreRegistered: true, |
245 | |
246 | groups: { |
247 | - d3: { |
248 | - modules: { |
249 | - 'd3': { |
250 | - 'fullpath': '/juju-ui/assets/javascripts/d3.v2.min.js' |
251 | - } |
252 | - } |
253 | - }, |
254 | juju: { |
255 | modules: { |
256 | - // Primitives |
257 | - |
258 | - 'svg-layouts': { |
259 | - fullpath: '/juju-ui/assets/javascripts/svg-layouts.js' |
260 | - }, |
261 | - |
262 | - 'reconnecting-websocket': { |
263 | - fullpath: '/juju-ui/assets/javascripts/reconnecting-websocket.js' |
264 | - }, |
265 | - |
266 | - // Views |
267 | - 'juju-view-utils': { |
268 | - fullpath: '/juju-ui/views/utils.js' |
269 | - }, |
270 | - |
271 | - 'juju-charm-panel': { |
272 | - fullpath: '/juju-ui/views/charm-panel.js' |
273 | - }, |
274 | - |
275 | - 'juju-notifications': { |
276 | - fullpath: '/juju-ui/views/notifications.js' |
277 | - }, |
278 | - |
279 | - 'juju-view-environment': { |
280 | - fullpath: '/juju-ui/views/environment.js' |
281 | - }, |
282 | - |
283 | - 'juju-view-service': { |
284 | - fullpath: '/juju-ui/views/service.js' |
285 | - }, |
286 | - |
287 | - 'juju-view-unit': { |
288 | - fullpath: '/juju-ui/views/unit.js' |
289 | - }, |
290 | - |
291 | - 'juju-view-charm-collection': { |
292 | - fullpath: '/juju-ui/views/charm.js' |
293 | - }, |
294 | - |
295 | - 'juju-view-charm': { |
296 | - fullpath: '/juju-ui/views/charm.js' |
297 | - }, |
298 | - |
299 | - 'juju-templates': { |
300 | - fullpath: '/juju-ui/templates.js' |
301 | - }, |
302 | - |
303 | 'juju-views': { |
304 | use: [ |
305 | 'juju-templates', |
306 | @@ -77,51 +19,12 @@ |
307 | ] |
308 | }, |
309 | |
310 | - // Models |
311 | - 'juju-endpoints': { |
312 | - fullpath: '/juju-ui/models/endpoints.js' |
313 | - }, |
314 | - |
315 | - 'juju-charm-models': { |
316 | - requires: ['juju-charm-id'], |
317 | - fullpath: '/juju-ui/models/charm.js' |
318 | - }, |
319 | - |
320 | - 'juju-models': { |
321 | - requires: [ |
322 | - 'model', 'model-list', 'juju-endpoints', 'juju-charm-models'], |
323 | - fullpath: '/juju-ui/models/models.js' |
324 | - }, |
325 | - |
326 | - // Connectivity |
327 | - 'juju-env': { |
328 | - requires: ['reconnecting-websocket'], |
329 | - fullpath: '/juju-ui/store/env.js' |
330 | - }, |
331 | - |
332 | - 'juju-notification-controller': { |
333 | - fullpath: '/juju-ui/store/notifications.js' |
334 | - }, |
335 | - |
336 | - 'juju-charm-store': { |
337 | - requires: ['juju-charm-id'], |
338 | - fullpath: '/juju-ui/store/charm.js' |
339 | - }, |
340 | - |
341 | + // 'juju-controllers' is just an alias for the modules defined by 'use' |
342 | + // If we use "requires: ['juju-controllers']" that means |
343 | + // "requires: ['juju-env', 'juju-charm-store', |
344 | + // 'juju-notification-controller']" |
345 | 'juju-controllers': { |
346 | - use: ['juju-env', 'juju-charm-store', |
347 | - 'juju-notification-controller'] |
348 | - }, |
349 | - |
350 | - // App |
351 | - 'juju-gui': { |
352 | - fullpath: '/juju-ui/app.js', |
353 | - requires: [ |
354 | - 'juju-controllers', |
355 | - 'juju-views', |
356 | - 'juju-models', |
357 | - 'juju-view-charm-search' |
358 | - ] |
359 | + use: ['juju-env', 'juju-charm-store', 'juju-notification-controller'] |
360 | } |
361 | } |
362 | } |
363 | |
364 | === added file 'bin/merge-files' |
365 | --- bin/merge-files 1970-01-01 00:00:00 +0000 |
366 | +++ bin/merge-files 2012-11-09 20:53:21 +0000 |
367 | @@ -0,0 +1,75 @@ |
368 | +#!/usr/bin/env node |
369 | + |
370 | +/** |
371 | + * We aggregate and minimize the js sources in order to improve the load speed |
372 | + * of the application. |
373 | + * |
374 | + * We don't want to use the yui combo loader feature because we want to be able |
375 | + * to run from only static files and we want to be able to run behind a |
376 | + * firewall without access to the internet. |
377 | + * |
378 | + * The final product will provide three js files: one for the YUI dependencies, |
379 | + * one for our custom js code and one for third party js like d3. |
380 | + * |
381 | + * Known issues: |
382 | + * (1) If we set "bootstrap=false" in the GlobalConfig object, yui disables the |
383 | + * loader object. It means it wont even try to download modules. We cannot |
384 | + * do it because the loader also manages the "use" property which defines |
385 | + * aliases for some of your modules ('juju-views' and 'juju-controllers'). |
386 | + * (2) During development, we've noticed that some of the yui modules weren't |
387 | + * included in the list of yui files (lang/datatype-date-format_en-US, |
388 | + * parallel, app-transitions-native, gallery-markdown, loader-base). For |
389 | + * some reason, the loader does not resolve the names of the files for |
390 | + * these modules. We need to add them manually in this file. |
391 | + */ |
392 | + |
393 | +'use strict'; |
394 | + |
395 | +require('yui').YUI().use(['yui'], function(Y) { |
396 | + var merge = require('../lib/merge-files.js'), |
397 | + syspath = require('path'), |
398 | + paths, |
399 | + reqs; |
400 | + |
401 | + // First we find all of the paths to our custom Javascript in the app |
402 | + // directory. We need to tell the function to ignore the "assets" directory |
403 | + // and the debug version of the modules file. I need to use |
404 | + // "syspath.join(process.cwd(), ...)" or else I have... "Error: Cannot find |
405 | + // module './app/config.js'" from node's internal module.js file. |
406 | + paths = merge.readdir(syspath.join(process.cwd(), './app'), |
407 | + [syspath.join(process.cwd(), './app/assets'), './app/modules-debug.js']); |
408 | + |
409 | + // Get the name of all the YUI modules that our custom js files use directly. |
410 | + reqs = merge.loadRequires(paths); |
411 | + |
412 | + // For some reason the loader does not get these requirements. |
413 | + // (Known issue #2) |
414 | + reqs.push('lang/datatype-date-format_en-US'); |
415 | + reqs.push('parallel'); |
416 | + reqs.push('app-transitions-native'); |
417 | + reqs.push('gallery-markdown'); |
418 | + reqs.push('loader-base'); |
419 | + |
420 | + // Get all of the YUI files and their dependencies, and combine them. |
421 | + merge.combine(merge.getYUIFiles(reqs), |
422 | + './app/assets/javascripts/generated/all-yui.js', true); |
423 | + |
424 | + // Combine third party js libraries |
425 | + merge.combine([ './app/assets/javascripts/d3.v2.min.js', |
426 | + './app/assets/javascripts/reconnecting-websocket.js', |
427 | + './app/assets/javascripts/svg-layouts.js' ], |
428 | + './app/assets/javascripts/generated/all-third.js', true); |
429 | + |
430 | + // Now we only need to generate the file that is used to tell YUI where all |
431 | + // the dependencies are. We either use a debug version or the production |
432 | + // version. The debug version is simply pointers to the individual files. |
433 | + // The production version aggregates all of the files together. |
434 | + |
435 | + // Creating the combined file for the modules-debug.js and config.js files |
436 | + merge.combine([ './app/modules-debug.js', './app/config.js' ], |
437 | + './app/assets/javascripts/generated/all-app-debug.js', false); |
438 | + |
439 | + // Creating the combined file for all our files. Note that this includes |
440 | + // app/modules.js in the rollup, which is why that file still needs exist. |
441 | + merge.combine(paths, './app/assets/javascripts/generated/all-app.js', true); |
442 | +}); |
443 | \ No newline at end of file |
444 | |
445 | === modified file 'grunt.js' |
446 | --- grunt.js 2012-10-30 11:36:00 +0000 |
447 | +++ grunt.js 2012-11-09 20:53:21 +0000 |
448 | @@ -11,7 +11,7 @@ |
449 | |
450 | }, |
451 | files: { |
452 | - 'bin' : 'app/assets/images/*' |
453 | + 'bin': 'app/assets/images/*' |
454 | } |
455 | } |
456 | } |
457 | |
458 | === added file 'lib/merge-files.js' |
459 | --- lib/merge-files.js 1970-01-01 00:00:00 +0000 |
460 | +++ lib/merge-files.js 2012-11-09 20:53:21 +0000 |
461 | @@ -0,0 +1,137 @@ |
462 | +'use strict'; |
463 | + |
464 | +// We need the yui name to be available in all modules (as a global variable). |
465 | +// This only happens if we remove the 'var' keyword or add it to the "global" |
466 | +// variable. |
467 | +global.YUI = require('yui').YUI; |
468 | + |
469 | +YUI().use(['yui'], function(Y) { |
470 | + var fs = require('fs'), |
471 | + syspath = require('path'), |
472 | + compressor = require('node-minify'); |
473 | + |
474 | + function minify(file) { |
475 | + var execution = new compressor.minify( |
476 | + { type: 'uglifyjs', |
477 | + fileIn: file, |
478 | + fileOut: file, |
479 | + callback: function(err) { |
480 | + if (err) { |
481 | + console.log(err); |
482 | + } |
483 | + }}); |
484 | + } |
485 | + exports.minify = minify; |
486 | + |
487 | + // It combines the files defined by "files" into a single (compressed or not) |
488 | + // js file. |
489 | + function combine(files, outputFile, shouldMinify) { |
490 | + var str = []; |
491 | + Y.Array.each(files, function(file) { |
492 | + console.log('file -> ' + file); |
493 | + str.push(fs.readFileSync(file, 'utf8')); |
494 | + }); |
495 | + fs.writeFileSync(outputFile, str.join('\n'), 'utf8'); |
496 | + if (shouldMinify) { |
497 | + minify(outputFile); |
498 | + } |
499 | + } |
500 | + exports.combine = combine; |
501 | + |
502 | + // It gets the name of all the files under 'path', recursively. It ignores |
503 | + // files and directories included in the "ignore" array. These will |
504 | + // typically be set to ignore our assets and our module file. |
505 | + function readdir(path, ignore) { |
506 | + var result = [], // These are the filenames we will return. |
507 | + dirs = [], // These are the directories into which we will recurse. |
508 | + files = fs.readdirSync(path); |
509 | + |
510 | + Y.Array.each(files, function(value) { |
511 | + var fileName, file; |
512 | + fileName = path + '/' + value; |
513 | + file = fs.statSync(fileName); |
514 | + if (file.isFile()) { |
515 | + if (syspath.extname(fileName).toLowerCase() === '.js') { |
516 | + if (ignore && ignore.indexOf(fileName) >= 0) { |
517 | + console.log('SKIPPING FILE -> ' + fileName); |
518 | + } else { |
519 | + result.push(fileName); |
520 | + } |
521 | + } |
522 | + } else if (file.isDirectory()) { |
523 | + console.log('DIRECTORY -> ' + fileName); |
524 | + if (ignore && ignore.indexOf(fileName) >= 0) { |
525 | + console.log('SKIPPING DIRECTORY -> ' + fileName); |
526 | + } else { |
527 | + dirs.push(fileName); |
528 | + } |
529 | + } |
530 | + }); |
531 | + // We have read all the filenames and all the directory names. Now |
532 | + // it is time to recurse into the directories that we have collected. |
533 | + Y.Array.each(dirs, function(directory) { |
534 | + // This is the best Javascript offers for appending one array to |
535 | + // another. |
536 | + result.push.apply(result, readdir(directory)); |
537 | + }); |
538 | + return result; |
539 | + } |
540 | + exports.readdir = readdir; |
541 | + |
542 | + // It reads the YUI 'requires' attribute of all our custom js files |
543 | + // (as assembled by readdir) and returns the YUI modules on which we |
544 | + // directly depend. |
545 | + function loadRequires(paths) { |
546 | + var originalAdd, modules, yuiReqs; |
547 | + modules = {}; |
548 | + |
549 | + originalAdd = YUI.add; |
550 | + // This is a trick to get the 'requires' value from the module |
551 | + // definition. |
552 | + YUI.add = function(name, fn, version, details) { |
553 | + if (details && details.requires) { |
554 | + modules[name] = details.requires; |
555 | + } |
556 | + }; |
557 | + |
558 | + Y.Array.each(paths, function(path) { |
559 | + // It triggers the custom 'add' method above |
560 | + require(path); |
561 | + }); |
562 | + YUI.add = originalAdd; |
563 | + |
564 | + // Getting all the YUI dependencies that we need |
565 | + yuiReqs = []; |
566 | + Y.Object.each(modules, function(requires) { |
567 | + Y.Array.each(requires, function(value) { |
568 | + if (!modules[value]) { |
569 | + // This is not one of our modules but a yui one. |
570 | + if (yuiReqs.indexOf(value) < 0) { |
571 | + // avoid duplicates |
572 | + yuiReqs.push(value); |
573 | + } |
574 | + } |
575 | + }); |
576 | + }); |
577 | + return yuiReqs; |
578 | + } |
579 | + exports.loadRequires = loadRequires; |
580 | + |
581 | + // Using the example http://yuilibrary.com/yui/docs/yui/loader-resolve.html |
582 | + // Given a list of direct YUI requirements, return the filenames of these |
583 | + // modules and their dependencies (indirect and direct). |
584 | + function getYUIFiles(reqs) { |
585 | + var loader, out; |
586 | + // The loader automatically handles following our dependencies. |
587 | + loader = new Y.Loader({ |
588 | + // The base tells the loader where to look for the YUI files. We |
589 | + // look directly in the npm YUI package, but we could just as well look |
590 | + // in the symbolic link app/assets/javascripts/yui. |
591 | + base: './node_modules/yui/', |
592 | + ignoreRegistered: true, |
593 | + require: reqs}); |
594 | + out = loader.resolve(true); |
595 | + return out.js; |
596 | + } |
597 | + exports.getYUIFiles = getYUIFiles; |
598 | +}); |
599 | |
600 | === modified file 'lib/server.js' |
601 | --- lib/server.js 2012-10-02 11:29:56 +0000 |
602 | +++ lib/server.js 2012-11-09 20:53:21 +0000 |
603 | @@ -5,6 +5,7 @@ |
604 | fs = require('fs'), |
605 | path = require('path'), |
606 | config = require('../config').config.server, |
607 | + debugMode = (String(process.argv[2]).toLowerCase() === 'debug'), |
608 | public_dir = config.public_dir, |
609 | Templates = require('./templates.js'), |
610 | view = require('./view.js'); |
611 | @@ -46,8 +47,24 @@ |
612 | }); |
613 | }); |
614 | |
615 | -server.get('/config.js', function(req, res) { |
616 | - res.sendfile('app/config.js'); |
617 | +server.get('/assets/all-third.js', function(req, res) { |
618 | + res.sendfile('app/assets/javascripts/generated/all-third.js'); |
619 | +}); |
620 | + |
621 | +server.get('/assets/modules.js', function(req, res) { |
622 | + if (debugMode) { |
623 | + res.sendfile('app/assets/javascripts/generated/all-app-debug.js'); |
624 | + } else { |
625 | + res.sendfile('app/assets/javascripts/generated/all-app.js'); |
626 | + } |
627 | +}); |
628 | + |
629 | +server.get('/assets/yui.js', function(req, res) { |
630 | + if (debugMode) { |
631 | + res.sendfile('app/assets/javascripts/yui/yui/yui-debug.js'); |
632 | + } else { |
633 | + res.sendfile('app/assets/javascripts/generated/all-yui.js'); |
634 | + } |
635 | }); |
636 | |
637 | server.get('*', function(req, res) { |
638 | |
639 | === modified file 'package.json' |
640 | --- package.json 2012-10-30 11:33:21 +0000 |
641 | +++ package.json 2012-11-09 20:53:21 +0000 |
642 | @@ -30,7 +30,8 @@ |
643 | "graceful-fs": "1.1.x", |
644 | "rimraf": "2.0.x", |
645 | "grunt": ">=0.2.0", |
646 | - "node-spritesheet": ">=0.2.3" |
647 | + "node-spritesheet": ">=0.2.3", |
648 | + "node-minify": "0.5.0" |
649 | }, |
650 | "optionalDependencies": {} |
651 | } |
652 | |
653 | === modified file 'test/index.html' |
654 | --- test/index.html 2012-11-01 13:12:28 +0000 |
655 | +++ test/index.html 2012-11-09 20:53:21 +0000 |
656 | @@ -4,7 +4,7 @@ |
657 | <meta charset="utf-8"> |
658 | <link rel="stylesheet" href="assets/mocha.css"> |
659 | <script src="../app/assets/javascripts/yui/yui/yui-debug.js"></script> |
660 | - <script src="../app/modules.js"></script> |
661 | + <script src="../app/modules-debug.js"></script> |
662 | <script src="assets/chai.js"></script> |
663 | <script src="assets/mocha.js"></script> |
664 | <script src="utils.js"></script> |
Reviewers: mp+133116_ code.launchpad. net,
Message:
Please take a look.
Description: aggregation js
Resource minification/
* We should aggregate and minimize the js sources in order to improve
the load speed of the application;
* We dont want to use the yui combo loader feature;
* The final product will provide three js files: one for the YUI
dependencies, one for our custom js code and one for third part js like
d3.
https:/ /code.launchpad .net/~tveronezi /juju-gui/ uglify/ +merge/ 133116
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/6821090/
Affected files: debug.js
M .bzrignore
M Makefile
A [revision details]
M app/index.html
A app/modules-
M app/modules.js
M grunt.js
M lib/server.js
A merge-files.js
M package.json
A properties-dev.js
A properties-prod.js
M test/index.html