I use ExtJS together with Grails. I have already two ExtJS applications in that project and now I want to add a third one.
The new application runs fine in development mode, but when I am starting it in production mode and then try to open it in the browser the screen stay white and the chrome console tells me that the bootstrap.js is missing in the production build folder. Which is true, there is no such file.
First I looked for a configuration to add this file when building in prod, but then I noticed that in the other two working application, that I already have, there is no bootstrap.js file either in the production build. Instead there are microloader.js files. Unfortunately I wasn't the one who set those ext applications up,so I don't know the reason for that.
Then another difference I noticed between my new not working application to the two working ones was in the index.gsp files.
The new one:
<g:if env="production">
<base href="../path">
<script id="microloader" data-app="1234..." type="text/javascript"
src="bootstrap.js"></script>
</g:if>
<g:else>
<base href="..path">
<script id="microloader" data-app="1234..." type="text/javascript"
src="bootstrap.js"></script>
</g:else>
And one of the working ones:
<g:if env="production">
<base href="../path/">
<script id="microloader" data-app="4321..." src="microloader.js"></script>
</g:if>
<g:else>
<base href="../path/">
<script id="microloader" data-app="4321..." type="text/javascript" src="bootstrap.js">
</script>
</g:else>
Changing the new index.gsp accordingly only leads to microloader.js being missed instead of the bootstrap.js
Another thing that I noticed is that the index.html which is created in the build folders look different.
The old ones look very plain and basic and in the new one there is lots of code, which seems to be equivalent with the code that is in the microloader.js files in the working apps.
I have the following assumptions:
If the file is called bootstrap.js or microloader.js doesn't matter, it just a different name, but the same thing.
Because we use the index.gsp files the index.html files in the production build folders aren't used.
Somewhere there is a configuration in the old applications that tells the application to use the microloader.js instead of the code in the index.html, which I am missing in the new one.
Is here maybe anyone who had a similar problem or has any idea how to solve this problem?
I am using ExtJS 7.5.1 in the old and the new applications. But the new one uses the modern toolkit instead of the old ones who are using the classic toolkit.
Grails 2.5.6 is used.
Please let me know, if you need any other info.
Thank you very much in advance.
I was able to figure it out. My third assumption was correct and the second one probably as well. Per default the microloader.js is added to the index.html. Since in my case I use the index.gsp, we have to add a configuration to tell sencha, that it writes the microloader into a seperate file. The configuration is in the app.json and looks like this:
"production": {
"output": {
"microloader": {
"embed": false
},
"appCache": {
"enable": false,
"path": "cache.appcache"
}
},
"loader": {
"cache": "${build.timestamp}"
},
"cache": {
"enable": true
},
"compressor": {
"type": "yui"
}
}
The important bit here is this:
"microloader": {
"embed": false
},
When this configuration is added and we run "sencha app build" again, then there will be a seperate file microloader.js
And then I can change the new index.gsp to look like the index.gsp files of the old applications.
I hope this will help someone in the future.
Best regards
Related
I want to split the app.js file generated by Extjs into app specific code & extjs specific code.The intention is to reduce the size of app.js & app will load much faster.
I have read some links, but as I am new to extjs I want some ready code(if available) like in some .xml files etc.
The app won't load faster because the app still requires the ExtJS code and your own code before it can do anything.
Furthermore, gzip compression works better if everything is in one file, so if you have enabled compression of static contents, your two-file app will load slower than before. And if you haven't, you definitely should, it will cut loading time in half or even less.
That said, you can always include more javascript files using multiple <script> tags:
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Verwarming HollandVilla</title>
<script type="text/javascript" src="ext-modern-all.js"></script>
<script type="text/javascript" src="verwarming.js"></script>
But you cannot split the compiled app.js into a part which only contains your code and another part which only contains ExtJS code, because in app.js both domains are mixed and mangled.
But you can still split the app.js before any occurrence of Ext.define()., and then check that both javascript files are still syntactically valid. If yes, you didn't change anything semantically, so the app should work as before.
If you really get the loading time down, please post your results, because I have not yet found anyone who verified the expected results by experiment.
Beside of what Alexander wrote, you can split the application and the framework code using the "output" definition. In the following example this is done for the production build:
"production":{
"output":{
// Split the framework from the application.
"framework":{
"enable":true
}
},
"compressor":{
// Enable compressor (other options: closure, strip)
"type": "yui"
}
}
Additionally the compression is activated (here: yui).
The "Sencha Compiler Reference" and the documentation about the "Resource Management" could also help you:
https://docs.sencha.com/cmd/guides/advanced_cmd/cmd_compiler_reference.html
https://docs.sencha.com/cmd/guides/resource_management.html
any cordova application is just a native web view and a www folder that contains the entire functionality in HTML javascript and css, so the app is entirely exposed, how can i make it as difficult as possible for anybody to read the app source code?
Yes you can. There is a cordova-plugin to crypt the html, js, and css files. You find it here: Cordova crypt file plugin
You are really concerned about it my advice is use a professional service to protect your code. E.g. Jscrambler
I found it, the problem with angular when got minified is that minification breaks dependency injection.
one solution is to use the string injection based syntax that maps every injected parameter to a string that never gets affected by minification.
example:
angular.module('app', []).controller(['$scope', function($scope) {
//code
}]);
another solution, is to use ngAnnotate i prefer to use it with gulp task runner
var gulp = require('gulp');
var ngAnnotate = require('gulp-ng-annotate');
var concat = require('gulp-concat');
var uglify= require('gulp-uglify');
gulp.task('task1', function () {
return gulp.src('src/js/*.js')
.pipe(concat('bundle.js'))
.pipe(ngAnnotate())
.pipe(uglify())
.pipe(gulp.dest('dist'));
});
Another good feature is to hide the location paths of your important scripts. I found a great npm plugin for this https://www.npmjs.com/package/location-hide
It turns
<script src="test/folder/sample.js" type="text/javascript"></script>
<link href="test/stylesheet/perfect-scrollbar.css" rel="stylesheet">
into
<script src="TNANIuTOLZfmLYwaPDIYhcZDVOWKodqYhysaTeQHFPDhYlDLCOtxZqYmkKAhaSwSgbsYOWlpBzVSBtMZKSfwRqvPSqWVlBBuzHR" type="text/javascript"></script>
<link href="gyXeFnOEvZbgTjLvdZRnsyrfhaXqffkDjcdATTouqpIenCalLRXKamuXEtiKbPGCsNrdQIaqTMTNWsLyLFuxygKytaruWzSjKYMq" rel="stylesheet">
And it generate new jquery include codes like this to include your scripts with javascript in a external file
$('[src=\'TNANIuTOLZfmLYwaPDIYhcZDVOWKodqYhysaTeQHFPDhYlDLCOtxZqYmkKAhaSwSgbsYOWlpBzVSBtMZKSfwRqvPSqWVlBBuzHR\']').attr("src", "test/folder/sample.js")
$('[href=\'gyXeFnOEvZbgTjLvdZRnsyrfhaXqffkDjcdATTouqpIenCalLRXKamuXEtiKbPGCsNrdQIaqTMTNWsLyLFuxygKytaruWzSjKYMq\']').attr("src", "test/stylesheet/perfect-scrollbar.css")
Also I would suggest you that you include all of your external javascript codes in 1 single js file. This file you place in the root of your index file that you can make this
<script src="./allinone_external_file.js" type="text/javascript"></script>
Then make right htaccess that nobody can acces this file. You can also make a fake import script for the source code that every body can see. But this file is only a redirect for the real external js file. you make this multiple times as example + use other obfuscation tools. This will protect you from people searching exploits with your javascript codes. I know its no big deal and maybe you can see the jquery include codes if you know how. But anyway it´s a great protection.
I advise to use babili library (https://github.com/babel/babili)
and form your app so that distribution using electron is made from obfuscated code not from source.
For example package.json contains scripts like this:
"main": "release/app.js",
"scripts": {
"debug": "node ./node_modules/electron/cli.js ./app/app.js",
"build": "./node_modules/.bin/babili app -d release -D",
"test": "./node_modules/.bin/electron ./release/app.js",
"pack": "./node_modules/.bin/build --dir --ia32"
}
.babelrc
{
"presets": ["es2015"]
}
BTW babel supports also ES6/7 obfuscation
I am trying to run an ExtJs application without using SenchaCmd. These are the scripts I load in the index HTML file:
<script type="text/javascript" language="javascript" src="dev/ext-all-debug.js"></script>
<script type="text/javascript" language="javascript" src="dev/all.js"></script>
The all.js file contains all the views, controllers, stores and models concatenated into one file using a gulp task (including app.js and Application.js files). The problem is that after these 2 files are loaded, The Ext Loader is still trying to load the required Controllers/Views one by one.
I tried adding the following code into the Application.js file but nothing changed:
constructor: function() {
this.callParent(arguments);
Ext.Loader.setConfig({enabled:false});
},
Any ideas? Why is the Ext.loader trying to load all the requires if they are included in the all.js file? Thanks.
What version of Ext JS? If you're using 5.0.1 the "ext-all-debug.js" file in the root of the ext directory will not work - you want the one in the "build" directory...
I think I know why the Ext.Loader didn't work as expected...
The concatenated files need to be in the right order because on each Ext.define the loader is searching for the dependencies specified in the requires section and if the dependencies are not loaded it will try to load them.
It works recursively until the dependency tree is loaded.
There is a Grunt plugin doing this: https://www.npmjs.com/package/grunt-sencha-dependencies
However I am still not satisfied of the development workflow with ExtJs because when using "app watch", in dev mode, you could be loading hundreds of JS files on a page refresh if your app is big enough and this impacts the performance quite a bit.
Good day. Sorry but I've stumbled upon a problem that I can't seem to figure out for the past couple of hours. I downloaded this printing class to be able to print a Form that I have in my web application. I copied the Ext.ux.Printer folder in my scripts folder inside resources. The file path looks like: resources/scripts/Ext.ux.Printer and the resources folder is on the same level as the app folder.
My Loader looks like:
Ext.Loader.setConfig({
enabled: true,
paths: {
'Ext.ux.Printer': 'resources/scripts/Ext.ux.Printer/Printer'
}
});
And the Application looks like:
Ext.application({
requires: [
'Ext.Loader',
'Ext.layout.container.Absolute',
'resources.scripts.Notification',
'Ext.layout.container.Column',
'Ext.ux.Printer.Printer'
], //models, views, controllers, follow after
and I try to use it in my code as such:
Ext.ux.Printer.print(form);
However, I am given an Uncaught TypeError: Cannot read property 'Printer' of undefined whenever I try to execute the line of code above.
Can anyone help me? I'm a beginner in ExtJS4 and I'm just trying to follow examples I see around the internet - it is possible that I tried to appropriate my code incorrectly with something I saw online.
Any help is very much appreciated, thank you.
UPDATE 1
Upon discussion with Guilherme Lopes below we did the following steps:
Import the js files by adding it as a js resource in Sencha Architect. Make sure that the file path is correct.
Check the includeAfterAppJS checkbox. Due to a bug in Architect, sometimes the JS Files are added in before the ExtJS.
Open index.htmluse ext-all.js instead of ext-dev.js. Note that Sencha Architect overwrites/resets this file every time you save your project. A quick fix is to go to project settings and uncheck updating index.html.
Try Ext.ux.Print.print(form);
By the developer instructions, you should import the script files using your main html document, the same way you do with ExtJS classes (if you are not using the bootstrap).
These lines should be added after you import the ExtJS library:
<script type="text/javascript" src="Printer.js"></script>
<script type="text/javascript" src="renderers/Base.js"></script>
The library currently comes with renderers for Ext.grid.GridPanel, and Ext.tree.ColumnTree.
These can be included as required:
<script type="text/javascript" src="renderers/GridPanel.js"></script>
<script type="text/javascript" src="renderers/ColumnTree.js"></script>
And your calls to Ext.ux.Printer should start working.
If you are using Architect, add your external JS files clicking on: + => Resources => JS Resource
And then change the URL to the path you need (do this for every file you wish to add)
* I would just uncheck the x-compile and x-bootstrap
We have an extjs application where the structure we laid out doesn't exactly match the structure Sencha recommends. In our structure we don't have an app.js but we do have a js where we mention the autoload and launch function, example as below along with the folder structure.
What we are looking is to minify all the JS files in admin folder and create one JS to be used in production, we tried looking at the Sencha CMD but of no luck. Can some one please point us for the exact steps for minifying our application for production use.
Ext.Loader.setConfig({
enabled: true,
paths: {
'Admin': '../../script/js/ace/admin',
'Ext.ux': '../../script/js/ext4/ux'
}
});
Ext.require('Admin.view.Administration');
Ext.application({
name: 'Admin',
appFolder: '../../script/js/ace/admin',
launch: function()
{
Ext.QuickTips.init();
var me = this;
Ext.create('Admin.view.Administration', {
renderTo: 'contentPanel'
});
}
});
We tried Cmd by generating JSB3 file, I know its deprecated in 4.2.1 but with the structure we have we felt that was the only option.
we tried the below command, but no jsb3 file got generated
sencha build admin.jsb3 <path to the admin js folder>
Thanks in advance, any pointers are really appreciated.
I posted this in Sencha forum, but I am expecting a much simpler option then they have provided.
Edit
we have multiple apps, and in most cases we try to use the js from other app folders.
For example in the below image we have utilities and admin apps, from utilities app we use SourceStore and the autoloader is defined as below to access the required
Ext.Loader.setConfig({
enabled: true,
paths: {
'Admin': '../../script/js/ace/admin',
'Utilities': '../../script/js/ace/utilities',
'Ext.ux': '../../script/js/ext4/ux'
}
});
If you let Sencha CMD to generate a skeleton application for you and then merge your existing code with it, then it will be really easy.
Otherwise you can try the old JSBuilder from Sencha as well.
I'd highly recommend checking out grunt with the grunt_sencha_dependencies plugin. Here's a tutorial.
At a high level, what you do is:
1) Run the sencha_dependencies plugin to generate a list of dependencies.
2) Pass the outputs to the uglify plugin to concat and minify the javascript.
3) Use grunt's copy task to replace to update your index.html with the minified output.
edit: I've dealt with Sencha CMD and it is awful. I would not wish it on my worst enemy. Grunt is just way easier.
I recommend you using JAWR. Basically you define in the jawr.properties file your bundles, and say which file or folder belongs to which bundle. A bundle is actually a bunch of JS files that are minified into another single one and can be requested separately in your servlets/JSP files. Besides, you can define dependencies between bundles (which by default are independent), so that when you include a bundle, other bundles are automatically included in your page. To include a bundle you use the special tag <jwr> in your servlet. Besides, you can enable the debug mode, so that when you develop, you can debug your code.
How it works: you add a servlet to your web.xml file to be loaded on start-up, which is also the stage when these bundles are generated (transparent to you).
Some tips:
Check this tutorial
Because in ExtJS the order in which the files are used is important, you should consider it when you define your bundles.
If you are willing to give Sencha CMD another shot, you could try using the sencha compile command.
sencha compile --classpath=folders-your-using,separated-by-commas concatenate --yui --output-file=output.js
--classpath is the folders you want to include.
--yui is the compressor
--output-file is the name of the javascript output.
I would recommend reading the sencha cmd guides. They can be a little intense, but sencha command packs so many tools in it that it probably deserves to be: http://docs.sencha.com/cmd/5.x/advanced_cmd/cmd_reference.html