[xwiki-devs] [Proposal] Canonical Javascript/CSS code organization
Hi devs, I’d like to propose the following official future organization for our javascript/CSS code. Note1: When I say “javascript” below, it should be understood as js + css (possibly less too). Note2: I started writing this email and then I realized Marius had already implemented it for 2 Extensions/Modules: the Platform Tree and the Platform Job modules. I was happy to discover this since it validated the idea I had ;) Maybe Marius has already sent an email to propose all this, in which cas I apologize for the duplication! So here’s the idea: * We should locate Java, REST and Javascript APIs in the Extension they relate to. For example the Model Module should hold the current Reference API but also the Javascript API to create, resolve and serialize references (i.e. what’s currently in entityReference.js). * Thus when an Extension adds or modify its Java API, it should keep in sync the other APIs too. And these APIs should be made available to the XWiki runtime only when those Extensions are loaded into the runtime. * The Javascript APIs should be packaged as webjar resources inside the JAR for the Extension (i.e. located in META-INF/resources/webjars/* in the JAR). Note: An Extension could deliver a singe JAR or several if we wish to separate the Java API from the Javascript API for example (this is what we currently have for the Platform Job and Platform Tree Webjars for ex). * The Javascript APIs should be declared using requirejs, using a define(), as in: define(['jquery', 'JobRunner', 'jsTree', 'tree-finder'], function($, JobRunner) { … } Note: In order to pass simple names to the define() and handle conditional minification, Marius has created a require-config.js in the tree webjar’s module: /*! #set ($minified = '.min') #if ($request.minify == 'false') #set ($minified = '') #end */ require.config({ paths: { jsTree: "$!services.webjars.url('jstree', 'jstree.min')", JobRunner: '$!services.webjars.url("org.xwiki.platform:xwiki-platform-job-webjar", "jobRunner${minified}")', 'tree-finder': '$!services.webjars.url("org.xwiki.platform:xwiki-platform-tree-webjar", "finder${minified}")', tree: '$!services.webjars.url("org.xwiki.platform:xwiki-platform-tree-webjar", "tree${minified}")' }, shim: { jsTree: { deps: ['jquery'] } } }); * The Javascript APIs should be accessed using requirejs, using a require(), as in: require(["$!services.webjars.url('org.xwiki.platform:xwiki-platform-tree-webjar', 'require-config.min.js', {'evaluate': true})"], function() { … } Note: We’ll need to better handle the minification part in this example so that it’s optional and can be controlled by minify=true|false in the query string, but that’s easy to do. * Unit tests should be provided using Jasmine inside the Extension * The requireJS deps should be kept in sync with the Maven deps. WDYT? If we agree about this then I’m proposing that we document it in the DevGuide at http://platform.xwiki.org/xwiki/bin/view/DevGuide/FrontendResources (which will need to be rewritten as it’s currently aging). The next step would be to find a way to move all our JS code under requirejs. I’ve been researching this but I’m far from being able to propose a solution at this time. I’ll need to brainstorm with our JS experts ;) Thanks -Vincent
On Sat, Aug 1, 2015 at 11:08 PM, [email protected] <[email protected]> wrote:
Hi devs,
I’d like to propose the following official future organization for our javascript/CSS code.
Note1: When I say “javascript” below, it should be understood as js + css (possibly less too). Note2: I started writing this email and then I realized Marius had already implemented it for 2 Extensions/Modules: the Platform Tree and the Platform Job modules. I was happy to discover this since it validated the idea I had ;) Maybe Marius has already sent an email to propose all this, in which cas I apologize for the duplication!
So here’s the idea:
* We should locate Java, REST and Javascript APIs in the Extension they relate to. For example the Model Module should hold the current Reference API but also the Javascript API to create, resolve and serialize references (i.e. what’s currently in entityReference.js). * Thus when an Extension adds or modify its Java API, it should keep in sync the other APIs too. And these APIs should be made available to the XWiki runtime only when those Extensions are loaded into the runtime. * The Javascript APIs should be packaged as webjar resources inside the JAR for the Extension (i.e. located in META-INF/resources/webjars/* in the JAR). Note: An Extension could deliver a singe JAR or several if we wish to separate the Java API from the Javascript API for example (this is what we currently have for the Platform Job and Platform Tree Webjars for ex). * The Javascript APIs should be declared using requirejs, using a define(), as in:
define(['jquery', 'JobRunner', 'jsTree', 'tree-finder'], function($, JobRunner) { … }
Note: In order to pass simple names to the define() and handle conditional minification, Marius has created a require-config.js in the tree webjar’s module:
/*! #set ($minified = '.min') #if ($request.minify == 'false') #set ($minified = '') #end */ require.config({ paths: { jsTree: "$!services.webjars.url('jstree', 'jstree.min')", JobRunner: '$!services.webjars.url("org.xwiki.platform:xwiki-platform-job-webjar", "jobRunner${minified}")', 'tree-finder': '$!services.webjars.url("org.xwiki.platform:xwiki-platform-tree-webjar", "finder${minified}")', tree: '$!services.webjars.url("org.xwiki.platform:xwiki-platform-tree-webjar", "tree${minified}")' }, shim: { jsTree: { deps: ['jquery'] } } });
* The Javascript APIs should be accessed using requirejs, using a require(), as in:
require(["$!services.webjars.url('org.xwiki.platform:xwiki-platform-tree-webjar', 'require-config.min.js', {'evaluate': true})"], function() { … }
Note: We’ll need to better handle the minification part in this example so that it’s optional and can be controlled by minify=true|false in the query string, but that’s easy to do.
* Unit tests should be provided using Jasmine inside the Extension
"should be provided inside the Extension" (using Jasmine is a detail)
* The requireJS deps should be kept in sync with the Maven deps.
WDYT?
I agree this looks better from runtime/extension point of view. However it will make working on these resources a lot more painful (right now you modify it and just refresh).
If we agree about this then I’m proposing that we document it in the DevGuide at http://platform.xwiki.org/xwiki/bin/view/DevGuide/FrontendResources (which will need to be rewritten as it’s currently aging).
The next step would be to find a way to move all our JS code under requirejs. I’ve been researching this but I’m far from being able to propose a solution at this time. I’ll need to brainstorm with our JS experts ;)
Thanks -Vincent
_______________________________________________ devs mailing list [email protected] http://lists.xwiki.org/mailman/listinfo/devs
-- Thomas Mortagne
Hi Thomas, On 2 Aug 2015 at 12:15:37, Thomas Mortagne ([email protected](mailto:[email protected])) wrote:
On Sat, Aug 1, 2015 at 11:08 PM, [email protected] wrote:
Hi devs,
I’d like to propose the following official future organization for our javascript/CSS code.
[snip]
WDYT?
I agree this looks better from runtime/extension point of view. However it will make working on these resources a lot more painful (right now you modify it and just refresh).
That’s a good point. BTW I have a similar problem today: for example we provide two versions of xwiki.js, one xwiki-min.js and one xwiki.js. However both versions are minified. We should provide a non minified one for when we pass minify=false in the query string. We could do something like: * Bundle 2 versions in the JAR: a minified one and a non-minified one. * At runtime, somehow group all js files located in all webjars into a single minified js file (yuicompressor). We’re doing this for JSX so we should be able to implement this for webjars too. Something like a JVM JIT for JS files. * When the WebJarsResourceReferenceHandler is used to access a webjar resource, if minify=false is specified in the URL, copy the non-minified resource somewhere on the filesystem (probably in the data dir for now) and return it. If the resource already exists on the FS, serve it from there and don’t extract it from the JAR. This would allow devs to make changes to that version and see the result, and also to debug easily JS in the browser. [snip] Thanks -Vincent
Hi, Reminder: since we will start using more and more require.js, we need a solution for optimizing [1] the requireJS javascript code because otherwise we will end up with way too many HTTP requests for each individual requireJS module. Thanks, Eduard ---------- [1] http://requirejs.org/docs/optimization.html On Sun, Aug 2, 2015 at 1:55 PM, [email protected] <[email protected]> wrote:
Hi Thomas,
On 2 Aug 2015 at 12:15:37, Thomas Mortagne ([email protected] (mailto:[email protected])) wrote:
On Sat, Aug 1, 2015 at 11:08 PM, [email protected] wrote:
Hi devs,
I’d like to propose the following official future organization for our javascript/CSS code.
[snip]
WDYT?
I agree this looks better from runtime/extension point of view. However it will make working on these resources a lot more painful (right now you modify it and just refresh).
That’s a good point. BTW I have a similar problem today: for example we provide two versions of xwiki.js, one xwiki-min.js and one xwiki.js. However both versions are minified. We should provide a non minified one for when we pass minify=false in the query string.
We could do something like: * Bundle 2 versions in the JAR: a minified one and a non-minified one. * At runtime, somehow group all js files located in all webjars into a single minified js file (yuicompressor). We’re doing this for JSX so we should be able to implement this for webjars too. Something like a JVM JIT for JS files. * When the WebJarsResourceReferenceHandler is used to access a webjar resource, if minify=false is specified in the URL, copy the non-minified resource somewhere on the filesystem (probably in the data dir for now) and return it. If the resource already exists on the FS, serve it from there and don’t extract it from the JAR. This would allow devs to make changes to that version and see the result, and also to debug easily JS in the browser.
[snip]
Thanks -Vincent _______________________________________________ devs mailing list [email protected] http://lists.xwiki.org/mailman/listinfo/devs
Hi, On Sun, Aug 2, 2015 at 1:55 PM, [email protected] <[email protected]> wrote:
Hi Thomas,
On 2 Aug 2015 at 12:15:37, Thomas Mortagne ([email protected] (mailto:[email protected])) wrote:
On Sat, Aug 1, 2015 at 11:08 PM, [email protected] wrote:
Hi devs,
I’d like to propose the following official future organization for our javascript/CSS code.
[snip]
WDYT?
I agree this looks better from runtime/extension point of view. However it will make working on these resources a lot more painful (right now you modify it and just refresh).
That’s a good point. BTW I have a similar problem today: for example we provide two versions of xwiki.js, one xwiki-min.js and one xwiki.js. However both versions are minified. We should provide a non minified one for when we pass minify=false in the query string.
This is actually a bad naming issue, IMO. Maybe we could rename xwiki-min.js to xwiki-all-min.js (or something along those lines). This way xwiki-min.js will actually end up being the minified version of the xwiki.js file (which will both have to be shipped in the corresponding webjar) and xwiki-all-min.js will be the aggregated + minified version of all the various js files that we aggregate when minify != false, thus removing the confusion. Thanks, Eduard
We could do something like: * Bundle 2 versions in the JAR: a minified one and a non-minified one. * At runtime, somehow group all js files located in all webjars into a single minified js file (yuicompressor). We’re doing this for JSX so we should be able to implement this for webjars too. Something like a JVM JIT for JS files. * When the WebJarsResourceReferenceHandler is used to access a webjar resource, if minify=false is specified in the URL, copy the non-minified resource somewhere on the filesystem (probably in the data dir for now) and return it. If the resource already exists on the FS, serve it from there and don’t extract it from the JAR. This would allow devs to make changes to that version and see the result, and also to debug easily JS in the browser.
[snip]
Thanks -Vincent _______________________________________________ devs mailing list [email protected] http://lists.xwiki.org/mailman/listinfo/devs
Hi, On Sun, Aug 2, 2015 at 12:08 AM, [email protected] <[email protected]> wrote:
Hi devs,
I’d like to propose the following official future organization for our javascript/CSS code.
Note1: When I say “javascript” below, it should be understood as js + css (possibly less too). Note2: I started writing this email and then I realized Marius had already implemented it for 2 Extensions/Modules: the Platform Tree and the Platform Job modules. I was happy to discover this since it validated the idea I had ;) Maybe Marius has already sent an email to propose all this, in which cas I apologize for the duplication!
So here’s the idea:
* We should locate Java, REST and Javascript APIs in the Extension they relate to. For example the Model Module should hold the current Reference API but also the Javascript API to create, resolve and serialize references (i.e. what’s currently in entityReference.js). * Thus when an Extension adds or modify its Java API, it should keep in sync the other APIs too. And these APIs should be made available to the XWiki runtime only when those Extensions are loaded into the runtime. * The Javascript APIs should be packaged as webjar resources inside the JAR for the Extension (i.e. located in META-INF/resources/webjars/* in the JAR). Note: An Extension could deliver a singe JAR or several if we wish to separate the Java API from the Javascript API for example (this is what we currently have for the Platform Job and Platform Tree Webjars for ex). * The Javascript APIs should be declared using requirejs, using a define(), as in:
define(['jquery', 'JobRunner', 'jsTree', 'tree-finder'], function($, JobRunner) { … }
Note: In order to pass simple names to the define() and handle conditional minification, Marius has created a require-config.js in the tree webjar’s module:
/*! #set ($minified = '.min') #if ($request.minify == 'false') #set ($minified = '') #end */ require.config({ paths: { jsTree: "$!services.webjars.url('jstree', 'jstree.min')", JobRunner: '$!services.webjars.url("org.xwiki.platform:xwiki-platform-job-webjar", "jobRunner${minified}")', 'tree-finder': '$!services.webjars.url("org.xwiki.platform:xwiki-platform-tree-webjar", "finder${minified}")', tree: '$!services.webjars.url("org.xwiki.platform:xwiki-platform-tree-webjar", "tree${minified}")' }, shim: { jsTree: { deps: ['jquery'] } } });
* The Javascript APIs should be accessed using requirejs, using a require(), as in:
require(["$!services.webjars.url('org.xwiki.platform:xwiki-platform-tree-webjar', 'require-config.min.js', {'evaluate': true})"], function() { … }
What I don`t fully understand when using some javascript code that is presented this way is if the caller would have to use 2 nested require() calls, like: require(["$!services.webjars.url('org.xwiki.platform:xwiki-platform-tree-webjar', 'require-config.min.js', {'evaluate': true})"], function() { // At this point, require-config.min.js is executed and I can now use the short versions that consider the minify parameter. require(['tree', "$services.webjars.url('some.other:module-I-may-need-that-is-not-configured', 'file')"], function(tree) { // Finally, I can use the js code available in the tree variable. tree.profit(); }); } I`m not sure what exactly we get by doing this and if it`s worth the effort. Thanks, Eduard
Note: We’ll need to better handle the minification part in this example so that it’s optional and can be controlled by minify=true|false in the query string, but that’s easy to do.
* Unit tests should be provided using Jasmine inside the Extension * The requireJS deps should be kept in sync with the Maven deps.
WDYT?
If we agree about this then I’m proposing that we document it in the DevGuide at http://platform.xwiki.org/xwiki/bin/view/DevGuide/FrontendResources (which will need to be rewritten as it’s currently aging).
The next step would be to find a way to move all our JS code under requirejs. I’ve been researching this but I’m far from being able to propose a solution at this time. I’ll need to brainstorm with our JS experts ;)
Thanks -Vincent
_______________________________________________ devs mailing list [email protected] http://lists.xwiki.org/mailman/listinfo/devs
On Thu, Aug 6, 2015 at 5:08 PM, Eduard Moraru <[email protected]> wrote:
Hi,
On Sun, Aug 2, 2015 at 12:08 AM, [email protected] <[email protected]> wrote:
Hi devs,
I’d like to propose the following official future organization for our javascript/CSS code.
Note1: When I say “javascript” below, it should be understood as js + css (possibly less too). Note2: I started writing this email and then I realized Marius had already implemented it for 2 Extensions/Modules: the Platform Tree and the Platform Job modules. I was happy to discover this since it validated the idea I had ;) Maybe Marius has already sent an email to propose all this, in which cas I apologize for the duplication!
So here’s the idea:
* We should locate Java, REST and Javascript APIs in the Extension they relate to. For example the Model Module should hold the current Reference API but also the Javascript API to create, resolve and serialize references (i.e. what’s currently in entityReference.js). * Thus when an Extension adds or modify its Java API, it should keep in sync the other APIs too. And these APIs should be made available to the XWiki runtime only when those Extensions are loaded into the runtime. * The Javascript APIs should be packaged as webjar resources inside the JAR for the Extension (i.e. located in META-INF/resources/webjars/* in the JAR). Note: An Extension could deliver a singe JAR or several if we wish to separate the Java API from the Javascript API for example (this is what we currently have for the Platform Job and Platform Tree Webjars for ex). * The Javascript APIs should be declared using requirejs, using a define(), as in:
define(['jquery', 'JobRunner', 'jsTree', 'tree-finder'], function($, JobRunner) { … }
Note: In order to pass simple names to the define() and handle conditional minification, Marius has created a require-config.js in the tree webjar’s module:
/*! #set ($minified = '.min') #if ($request.minify == 'false') #set ($minified = '') #end */ require.config({ paths: { jsTree: "$!services.webjars.url('jstree', 'jstree.min')", JobRunner: '$!services.webjars.url("org.xwiki.platform:xwiki-platform-job-webjar", "jobRunner${minified}")', 'tree-finder': '$!services.webjars.url("org.xwiki.platform:xwiki-platform-tree-webjar", "finder${minified}")', tree: '$!services.webjars.url("org.xwiki.platform:xwiki-platform-tree-webjar", "tree${minified}")' }, shim: { jsTree: { deps: ['jquery'] } } });
* The Javascript APIs should be accessed using requirejs, using a require(), as in:
require(["$!services.webjars.url('org.xwiki.platform:xwiki-platform-tree-webjar', 'require-config.min.js', {'evaluate': true})"], function() { … }
What I don`t fully understand when using some javascript code that is presented this way is if the caller would have to use 2 nested require() calls, like:
require(["$!services.webjars.url('org.xwiki.platform:xwiki-platform-tree-webjar', 'require-config.min.js', {'evaluate': true})"], function() { // At this point, require-config.min.js is executed and I can now use the short versions that consider the minify parameter. require(['tree', "$services.webjars.url('some.other:module-I-may-need-that-is-not-configured', 'file')"], function(tree) { // Finally, I can use the js code available in the tree variable. tree.profit(); }); }
I`m not sure what exactly we get by doing this and if it`s worth the effort.
You either use two (nested) calls to require or you duplicate the require config. Your choice. If you don't have additional dependencies (so no require config) then two nested require calls can be shorter. Thanks, Marius
Thanks, Eduard
Note: We’ll need to better handle the minification part in this example so that it’s optional and can be controlled by minify=true|false in the query string, but that’s easy to do.
* Unit tests should be provided using Jasmine inside the Extension * The requireJS deps should be kept in sync with the Maven deps.
WDYT?
If we agree about this then I’m proposing that we document it in the DevGuide at http://platform.xwiki.org/xwiki/bin/view/DevGuide/FrontendResources (which will need to be rewritten as it’s currently aging).
The next step would be to find a way to move all our JS code under requirejs. I’ve been researching this but I’m far from being able to propose a solution at this time. I’ll need to brainstorm with our JS experts ;)
Thanks -Vincent
_______________________________________________ devs mailing list [email protected] http://lists.xwiki.org/mailman/listinfo/devs
_______________________________________________ devs mailing list [email protected] http://lists.xwiki.org/mailman/listinfo/devs
participants (4)
-
Eduard Moraru -
Marius Dumitru Florea -
Thomas Mortagne -
vincent@massol.net