PDA

View Full Version : Complicated app and the 'microloader'



jhoweaa
15 Apr 2014, 12:12 PM
In my attempt to get my Ext JS 4.2 application running under Ext JS 5, I've run into a bit of a roadblock relating to the new way applications are loaded using the microloader. I'm not quite sure how to re-work my application to make it work.

Our application is started from an index.jsp file. The JSP loads and the first thing it does is check to see if the user has a valid session. If the session is valid, it launches the application. The html in this branch of the JSP is basically the contents of a generated index.html with a bit of tweaking. In Ext JS 4.2 we have something like this:



<!DOCTYPE HTML>
<html>
<head>
<title>App Title</title>
<script type="text/javascript">
... some custom script setup
</script>
<!-- <x-compile> -->
<!-- <x-bootstrap> -->
<link rel="stylesheet" href="bootstrap.css">
<script src="ext/ext-dev.js"></script>
<script src="bootstrap.js"></script>
<!-- </x-bootstrap> -->
<script src="app.js"></script>
<!-- </x-compile> -->
</head>
<body/>
</html>


After reading the upgrade guide, I think I understand how I could rework this to use the microloader. However, the real problem for me comes when the user *isnt* authenticated. Right now, if that happens, the JSP generates different HTML which basically displays a login screen. The login screen is a very minimal Ext JS application in its own right. When a user isn't logged on, the current application generates the following HTML:



<!DOCTYPE HTML>
<html>
<head>
<title>Login</title>
<!-- <x-compile> -->
<!-- <x-bootstrap> -->
<link rel="stylesheet" href="bootstrap.css">
<script src="ext/ext-dev.js"></script>
<script src="bootstrap.js"></script>
<!-- </x-bootstrap> -->
<script src="login.js"></script>
<!-- </x-compile> -->
<head>
<body>
<div> ... login page code which gets updated by code from the 'login.js' file </div>
</body>
</html>


The login.js file looks something like this:



Ext.loader.setConfig('disableCaching', false);
Ext.require([
... required classes ...
]);
Ext.onReady(function() {
var loginForm = Ext.create('login card panel', ...);
loginForm.render('login-form-div');
});


So here's my problem. In one instance I would want the microloader to load my 'app.js' code, but in the other case I would want it to load my 'login.js' code. I'm not sure how to do that, or even if that is possible. My guess is that I might have to completely re-engineer how our application starts up, but I'm not sure how to do that at this point to be compatible with the loading process. A nice example to add to the development guides might be a description of different ways to deal with using an authenticated Ext JS application, something that requires some sort of login page which is different than the app itself. In our case we need something separate because the visibility of certain application features is governed by the type of user access the application.

Sorry to be long winded, but if you read this far and can offer any guidance on this subject, your help would be greatly appreciated. My guess is that I can probably engineer some sort of solution, but it would be nice to have a solution which fits the basic build/deployment structure used by Ext JS 5.

Thanks in advance for any help.

Jim

mitchellsimoens
18 Apr 2014, 6:18 AM
Why not handle when a user isn't logged in within your application that way you don't have to redirect the user or refresh the page? Set some flag or variable that tells the app the user isn't logged in.

jhoweaa
21 Apr 2014, 5:12 AM
The idea is to not load the main application until the user has authenticated. If a user doesn't have permission to use the application we don't want to download the code to the browser. If there was an easy way to download just the basic application and then download additional code after authentication that would work, but I don't see how to fit that in to the standard build process.

dongryphon
1 May 2014, 12:18 AM
The microloader provides a hook you can use to select which "build" to load. Check out the index.html of the Kitchen Sink example and you'll see something like this:



<script type="text/javascript">
var Ext = Ext || {};

Ext.beforeLoad = function(tags){
var theme = location.href.match(/theme=([\w-]+)/),
locale = location.href.match(/locale=([\w-]+)/);

theme = (theme && theme[1]) || 'crisp';
locale = (locale && locale[1]) || 'en';

Ext.manifest = theme + "-" + locale;
};
</script>

<script id="microloader" type="text/javascript" src="bootstrap.js"></script>


A normal app is a single build and single "app.js" but once you have multiple themes and/or locales (like Kitchen Sink with Hebrew - an RTL locale) things get interesting. In order to download the optimal set of bits we set up a "multi-build" for KS and a similar solution might work for your situation.

In the "app.json" file for Kitchen Sink you'll see something like this:



...

"locales": [
"en",
"he"
],

"builds": {
"classic": {
"theme": "ext-theme-classic"
},
"gray": {
"theme": "ext-theme-gray"
},
"access": {
"theme": "ext-theme-access"
},
"crisp": {
"theme": "ext-theme-crisp"
},
"neptune": {
"theme": "ext-theme-neptune"
},
"neptune-touch": {
"theme": "ext-theme-neptune-touch"
}
}


Basically the "builds" is keyed by build ids and each of them (cross-producted by themes and locales if specified) will be built using "sencha app each build". The above produces builds named "classic-en", "classic-he", "gray-en", ... "neptune-touch-en", and "neptune-touch-he" for a total of 12. Most apps won't likely want so many builds of course.

This is not yet documented in Cmd 5 but should be soon as the final command syntax has just recently been decided.

The idea with "builds" is that the base content of app.json is merged with the content of the build object (in KS case only "theme" is being set) and that final app.json is then saved along with the bundled code. I have not tested it, but you should be able to do something like this:



"builds": {
"login": {
"js": [{
"path": "login-app.js",
"bundle": true
}]
},

"main": {
"js": [{
"path": "app.js",
"bundle": true
}]
}
}


That should produce a "login" and "main" folder in your build directory as well as "login.json" and "main.json". Either in Ext.beforeLoad or in JSP you just need to get Ext.manifest equal to "login" or "main" and that manifest will be loaded.

Perhaps:



<script type="text/javascript">
var Ext = Ext || {};
Ext.manifest = "${manifestName}";
</script>


If I recall the JSP EL syntax. :) Alternatively you could send the JS object for the manifest directly and save an ajax call from the microloader. The goal is either by instance or by name you need to set Ext.manifest (which is just "app.json" by default).

jhoweaa
1 May 2014, 4:23 AM
Thanks for this great piece of information, it's definitely something I'll experiment with. Really looking forward to being able to see new documentation on Sencha Cmd 5 so I can figure out how to do the more complicated things with it.

Jim