There are javascript obfuscators around like http://www.javascriptobfuscator.com/Default.aspx. They work on simple javascript code. But would they work on more complicated front-end AngularJS code which may have several files for controllers, services, modules?
What tools do the experienced programmers on StackOverflow use for obfuscating their AngularJS code? Or you don't at all because it is impossible to obfuscate front-end code?
You can use tools like Uglify or the Closure Compiler to minify and obfuscate AngularJS code, but it can get tricky because of Angular's ability to inject dependencies based on the name of the variable used (which will all be changed when you minify or obfuscate the code).
You'll need to use the array form of defining your modules, controllers, etc. It's explained in the "Notes on Minification" section in step 5 of the Angular tutorial: https://docs.angularjs.org/tutorial/step_05
Basically, if you're currently using the shorthand method of dependency injection, ie:
myApp.controller('myController', function($scope, $http) { ... });
you need to change it to the more verbose array based method:
myApp.controller('myController', ['$scope', '$http', function($scope, $http) { ... }]);
This way you're telling angular what objects to inject into your function using strings, which won't be changed during minification, instead of relying on names of the $scope and $http variables themselves.
There is a command line tool called ngmin that will automatically make these changes for you if you don't want to modify your codebase: https://github.com/btford/ngmin
The 'Conceptual Overview' section of the ngmin readme also has a good explanation of this problem.
Related
var myapp=angular.module('myAppln',[]);
I am new to angularjs. Why should we use [] in angular.module()? Could anybody please explain.
This is used for injecting dependency. Dependency Injection or DI is a software design pattern in which components are given their dependency instead of hard coding them within the component. This is also helpful in making dependency configurable and make components resuable & maintainable.
Components such as services & directives are defined using injectable factory
For example when define a service in angularjs we do like this way
var abc = angular.module('ngAppName',[]);
abc.factory('serviceName',['$http',function($http){
// Rest of code goes here
}])
angular.module('ngAppName',[])
It is more or less entry point for angular application & here we do not have any dependency so this is an empty array.
But take a look when we are defining our custom service.Here this service has dependency on $http which is predefined service offered by angular for ajax call.Our custom service(serviceName) has dependency on this $http, which we are injecting here
Another example with angular route
abc.config(['$routeProvider',function($routeProvider){
// Rest of code goes her
}])
The $routeProvider is what creates the $route service and it is provided by angularjs. While creating route we have to depend on $routeProvider. So we have injected it our code.
Hope this will be helpful for you.
if you go further in Angular.js then you will read that you can pass injectors and other stuff to module. So here api return in a manner that it receaves array of options. when you wont have any you just pass it blank []
Actually [] is an array with the dependencies that are required by the module.
I have just started working in angular.js and I have created separate angular applications (using ng-app) for separate modules of my application for modularity sake so that change in one module does not bring down the whole application.
Now, i am running into a issue of redirecting from a search form common across all modules to a particular page (in a specific module). I thought of saving the value in $rootScope, but while debugging, I found that $rootScope is per ng-app, so, it will not work.
Am I wrong in designing the application into separate angular applications and should I move everything back into one ng-app? or is my application structure correct and I should look for another way of passing value?
EDIT: - I think I did not provide enough detail earlier.
My application is structured as follows:
module1
- controller\controller-module1.js
- service\service-module1.js
- css\module1.css
- view\ <multiple html files>
module2
- same structure
I was actually using the service-module to make REST calls to the server till now, rather than sharing data.
All the modules are defined with their separate dependencies in app.js:
angular.module('Module1App', ['Module1App.controller','Module1App.service']);
angular.module('Module2App', ['Module2App.controller','Module2App.service']);
controllers and service of each module are defined in their respective controllers-module.js and service-module.js, which reside in different directories as per the structure above.
So, to include the controller and service of a particular module(of, say, module1), I declare the following in a view of that module
<script src="/APP_GUI/modules/common/service/services-common.js"></script>
<script src="/APP_GUI/modules/reports/service/services-module1.js"></script>
<script src="/APP_GUI/modules/common/controller/controllers-common.js"></script>
<script src="/APP_GUI/modules/reports/controller/controllers-module1.js"></script>
So, if I have to move all ng-controllers (defined in separate directories as per the module structure above) into one ng-app (app.js above), I will basically end up including all the controller.js and service.js in all the html views, which will basically mean that if there is an error in any one of the js files, my entire application will be down (i have tried it out).
So, unless I have misunderstood something, I cannot move all ng-controllers under a single app.js.
I am going to try out using shared services to share data.
Please let me know in case anybody has something to say on my conclusion.
I don't think using many ng-app is a good approach. I suggest you using many ng-controller in separate file instead.
You can keep variables inside objects instead of using $scope, which most tutorials you'll find online don't explain.
For example:
/// Define the app
app = angular.module('MyApp',[]);
///Add a cotroller
app.controller('MyFirstController', ['$scope', function($scope){
/// using 'this' you can write local properties
this.firstLocalProperty = 'first Value is acessible only in MyFirstController';
this.secondLocalProperty = 'second Value is acessible only in MyFirstController';
$scope.firstSharedAppProperty = 'This is Shared between all controllers in app';
}]);
app.controller('MySecondController', ['$scope', function($scope){
/// here you can use shared and local properties, you may access shared things in $scope
this.fistProperty = $scope.firstSharedAppProperty;
}]);
You'll see that
> MySecondController.firstProperty
'This is Shared between all controllers in app'
but
> MyFirstController.firstProperty
'first Value is acessible only in MyFirstController'
MyFirstController.firstProperty keeps it's original value because it's not shared.
Basically, you should use different controllers for different templates instead of using different modules. Using controllers, you may share items between them in the $scope variable. Or you can keep variables private using this reference inside objects.
Take a look in this article and you may understand better this way.
You should be using multiple controllers and then using a common service shared between your services. Services in angular are singletons, so they can be shared over and over and over again, and will be common across the board, including between applications if you inject the shared functionality as another application.
var app = angular.module('firstApp');
app.service('myService', function(){
var self = this;
return{
getValue: function(){return self.value},
setValue: function(value){self.value=value}
}
});
app.controller('firstController', ['myService', function(myService){.....}]);
app.controller('secondController', ['myService', function(myService){....});
var secondApp = angular.module('otherApp',['firstApp']);
secondApp.controller('otherController', ['myService', function(myService){.....}]);
more importantly, if its doing anything more than just storing values you can inject functionality for better testing!
Apologies if this question sounds too obvious.
I've recently starting exploring and learning AngularJS. I've gone through some good tutorials -
Official Docs
w3cSchool
Some cool site
.. and there are a few other that I've seen.
I'm not saying that I've read/studied all the documents.
Question starts here -
Now, coming to the question, I see that the definition of a Controller is different in one place and it's different in some other -
One definition uses a sort of array notation (not sure of the official term) for injection:
app.controller("MyCtrl", ['$scope', function($scope){
$scope.someData = "Array notation";
}]);
And there's this, with no array:
app.controller("MyCtrl", function($scope){
$scope.someData = "non-array notation";
});
Not saying this is the only thing that I'm trying to understand but yes, I'd definitely love to understand the difference.
Is there a major difference between the two?
Thanks a lot.
Note: I did search for similar questions in SO but couldn't find what I was looking for. Sorry.
The difference is that when the second is minified, the parameter name will be minified and angular will no longer be able to inspect the arguments to figure out which dependencies to inject. The array syntax with the dependency in a string means that it is minification safe.
There is a library called ng-annotate which will change the second example into the first example so that the code is again minification safe.
There is not much difference between the two approaches. Both code works same way. But if you use the second code then it will confuse you after you minify your code.
Look for an example:-
app.controller("MyCtrl", function(a){ ... });//$scope is changed to a
And your code won't work as AngularJs code uses $scope variable as it doesn't take first, second, third, and so on parameters.
So, the first code is safer than second as if when you minify the code, it will still takes same variable i.e. $scope.
Look for an example:
app.controller("MyCtrl", ['$scope', function(a){...}]);//a refers to $scope
So, the above code works fine when you minify the code as $scope is injected in place of a.So, if you pass multiple parameters then ordering matters in this example.
Look at the following:
app.controller("MyCtrl", ['$scope','$timeout' ,function(a,t){...}]);
where a is injected as $scope and t is injected as $timeout.
So if you change the orders of parameters passed as
app.controller("MyCtrl", ['$timeout','$scope', function(a,t){...}]); where a is $timeout and t is $scope.
So, ordering matters in this example but in your second example code ordering won't matter as name matters like $scope, $timeout.
There's also another way to inject variables if you use your first example code like below:
MyCtrl.$inject = ['$scope'];
For multiple parameters,
MyCtrl.$inject = ['$scope','$timeout'];
So, there are mainly three kinds of annotation:
Implicit Annotation - your first example code
$inject Property Annotation - the $inject method
Inline Array Annotation - your second example code
You can learn more about it here
There is a difference when it comes to minification. If you were to minify your file, as you may do to increase performance this is when you may run into issues if you used option two.
Since Angular infers the controller's dependencies from the names of arguments to the controller's constructor function, if you were to minify the JavaScript code for the controller, all of its function arguments would be minified as well, and the dependency injector would not be able to identify services correctly.
So in essence you are better off using the first option, small bit more typing involved but it's safer and will not break if you minify your code :-)
This is quite a short tutorial but explains it nicely.
I have a great and complex AngularJS project, so making manually the changes the all the codes would have been a big pain. But I solved using babel-plugin-angularjs-annotate.
Install the plugin:
$ npm install babel-plugin-angularjs-annotate --save-dev
and then add the plugin to the .babelrc file:
{
"presets": ["#babel/preset-env"],
"plugins": ["angularjs-annotate"]
}
I am using AngularJS for a SPA, and I am using browserify to build my application. Now the question came up whether we should write Angular services in the classical way, or simply require them.
As Angular services are singletons, this could be easily done with require as well: Simply expose an object literal, and you're done. Factories are also possible, simply expose a function. And so on ...
The only disadvantage I can currently think of is that I am not able to access other real Angular services from such a file (like, e.g., $http), but with browserify in the background this does not seem to be that important. E.g., you could easily use Node.js's http module for that, thanks to browserify.
So what do you think of this? What are other advantages and disadvantages for this?
PS: Please note that I'm not asking for whether this is good or bad, as this is probably mainly subjective. I'm rather interested which opportunities appear, or which risks I have to deal with.
One disadvantage to doing this is writing unit tests. It will be difficult to mock your dependencies if you are simply requiring them rather than using Angular's dependency injection.
This is somewhat of a dealbreaker for me because one of the many benefits of using Angular is the testability of the framework.
It's bad.
Just use browserify to initially load in all the modules you need.
you miss out on $httpBackend
your code becomes harder to follow, ie, there is very rarely a point to reuse that directives controller
you miss out on $http interceptors
you miss it in being able to modify and interact with other injectables.
The only thing I'd use browserify/webpack/requirejs for in an angular app is two things:
creating js bundle
injecting templates as strings into the angular template cache as a module.
Personally this kind of approach is just a pointless complication.
If you require things like $http you won't have any way to inject dummy/mocks of those services during testing.
Although somewhere you will do the wiring between your super-duper service that needs $http and the place you need it.
The first thing that came into my mind is resolvers in routes. You can even have some helper methods to deal with declaring the same dependencies many times.
Imagine this module:
function SuperResource($http, pathExpression) {}
exports.SuperResource = SuperResource;
exports.superResourceFactory = function(pathExpression) {
return [
'$http',
function() {
return new SuperResource($http, pathExpression);
}];
};
Somewhere you will do:
var myModule = require('./myModule.js');
resolvers: {
usersResource: myModule.superResourceFactory('/users')
}
Or even you could have a user modules that defines the user resource:
var myModule = require('./myModule');
exports.userFactory = ['$http', function() {
return new myModule.SuperResource($http, pathExpression);
}
Yes, these are angular specific helpers in an otherwise angular free code, but at least they're isolated in their own method/name.
I'm learning AngularJS and in all tutorials and screencasts I always saw to use angular writing code all in a unique file, example directives, controllers, factories etc...
Logically for large applications, you will split out the code, make it maintainable and flexible in multiple files and also we should be careful about how many <script> tags we have to require to let our JavaScript files run correctly.
I would like to know which is the best practice to require files when needed, importing less javascript files possible in my view. I took a look at RequireJs but it seems a bit complicated to use it. Is there some tool more efficient and easy to use? Or any good resource to get started?
A small example can be that I have a sort of plugin that has been built using directives, controllers and factories:
app-|
--Controllers
|_ pluginController.js
--Directives
|_ pluginDirective.js
--Factories
|_ pluginFactory.js
Instead of requiring all three files how do you make it work?
Here' a great example of how to use RequireJS and AngularJS together. It's a fork of the Angular Seed project and it should hopefully point you in the right direction. It comes with RequireJS baked right in. I definitely recommend learning RequireJS!
I would advice you to read up on dependency injection in the Angular documentaion. It all depends on how you set things up to be honest. If you want to use your service/factory in your controller then you would add the factory as a dependency in your controller or directive. See example below :
Angular.module('{YOUR MODULE NAME}').controller('{YOUR CONTORLLER NAME}', ['$scope', '{FACTORY NAME}',
function($scope,{FACTORY NAME}) {
}]
To invoke the directive within your controller, you would simply could simple add the directive to your controller template. This is a basic example, to learn more read about dependancy injectioninvoke
To be clear that I understand - e.g. I want to use "angularFileUpload" module, I need to add it to my module dependency list -
angular
.module('kids', ['angularFileUpload'
])
and load the script?
<script src="angularjs/plugins/angular-file-upload/angular-file-upload.min.js" type="text/javascript"></script>
Thanks for help.