loading external JS libraries / modules in AngularJS - angularjs

I have a question regarding loading External JS files in Angular JS in terms of performance:
I have a small module which uses tinymce editor.
I have installed it via bower ('angular-ui-tinymce') and it works fine.
Since I'm using this library rarely, and it is being loaded on app start every time - is it better (in terms of performance) to load it in index.html async / defer like this? (to avoid being a blocking script?)
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-tinymce/0.0.19/tinymce.min.js" defer></script>
Is it possible to load external js files only when the user enters a specific module?
Thanks.

When you say "performance" in this case, you mean your bundling size I assume?
What you have to consider is if this is going to come up again down the road.
A handful of dependencies are best served when bundled together instead of several individual requests.
Even though it is not this case, if by any chance you were including dependencies that had to be configured during bootstrap they could not be asynchronously loaded.
So IMHO you want the best of both, you can always bundle and place your app on a CDN, free performance right there.

Related

Modules architecture/distribution

I was taking a look in this nice Angular best practices repository and I can't find a proper way to apply this pattern of modularization.
The author suggest importing all the other modules in the main app module, that seems to be a great idea for me, but in my perception it also means loading all the js files of the system when loading the page for the first time "into" the main module.
I'm looking this wrong? I'm I right? If I'm right, is there a workaround to avoid loaind all the js files? Should I be worried with the loading time of the js files?
Angular application is SPA, the page is loaded only once, all relevant JS files should be loaded at the time when the app is bootstrapped.
Angular doesn't officially support lazy loading to load additional module files on demand, doing this by patching the framework may cause more troubles than it may solve.
Bundling all modules with bundling systems (Webpack, Browserify, etc) into a single JS improves loading time and results in better performance than loading JS files selectively.

how to make angularjs website to load faster

**I am developing a site ,in which front-end is made with Angularjs **
Site name is http://limokit.com/limolog but the problem is that , it take minimum 30 seconds to open the site page on browser. How to reduce this loading time?
we used ngRoute to change the states , but do not getting the result which we wanted to achieve . We also converted all html and js as minified one but it is also not effecting the loading issue for first time.
At first glance it looks like you're loading individual js and css file separately. This can slow down the loading of the page greatly especially on slower connections. The common optimization to do here is to group all js files and css files together and serve one single js and one single css file on production. I don't know what you're using to serve the JS/CSS files but I use compressor for Django.
Also, to further debug this problem, it helps if you look at the network requests that your page is doing on page load in the Chrome inspector. You can glean a lot of information by seeing where your bottlenecks are on page load.
In your site you're having 63 requests and around 3MB size (uncached).
As mentioned in the other answer package everything in bundles. E.g. vendor.bundle.js, bundle.js and bundle.css and also minify these bundles.
I would use webpack or gulp for bundling.
For debugging you can look in the browser console networking tab at the lower right in Firefox you can see a link to load time statistics and also get a info about caching.
The following screenshot shows statistics to your site (left with cache, right uncached).
.
Ditch all frameworks and libraries such as Angular and Jquery and use JSvanilla. Plain javascript is much faster to run(around 160x according to many resources i read..i also know that from my own experience).
Frameworks makes your site crawl.

How do I load angular modules, that are common and dynamic between pages?

I have a site that is developed by multiple developers that has multiple pages. Each "page" initializes angular by calling angular.module(etc).
My question is, all pages share some modules, and some pages use specific modules. What is the best practice to achieve this? Do I trust that developers will insert the correct modules that will be needed across the site (i.e. Google Analytics) or do I create one call that is shared my all pages that loads ALL the modules. And is there a way to do both? Such as, initilize the modules that are needed across all the pages and then, load specific modules dynamically on their respective pages.
I would make one global module that is loaded by each individual app, much like modules like 'ngAnimate' are loaded... the global module could then initialize functionality common to all pages, such as Google analytics.
This requires some policing on all developers involved, but this is a good practice via code reviews, etc.
example page:
angular.module('individualPage', [
'globalModule',
'customPageModule'
]).config(
// etc
);
global module:
angular.module('globalModule', [
'googleAnalytics'
]).config(
// etc
);
I have a site that is developed by multiple developers that has multiple pages. Each "page" initializes angular by calling angular.module(etc).
My question is:
All pages share some modules, and some pages use specific modules. What is the best practice to achieve this?
I do not know the best practice when dealing with multiple pages.
IMHO, creating multiple pages is a BAD practice nowadays. I think of
web applications(SPAs) that have different views and states not web
sites with disjointed pages. So if you choose to go the
SPA(single page application) way, you can load all you core/common
modules before the application bootstraps. Views/pages that need
specific modules can lazy load them using something like
oclazyload.
Do I trust that developers will insert the correct modules that will be needed across the site (i.e. Google Analytics) or do I create one call that is shared my all pages that loads ALL the modules.
I can't say much about the question of trust as I do not know your
developers well enough. In general, developers are never to be
trusted, they will do anything that seems to work, high five
themselves and call it a day. The idea is to "Trust but verify", you
don't have to wire tap their phones or read their emails but never
ever take your eyes off the main git or svn repository. Anywhere, If
you were to use oclazyload as I suggested above for a SPA, you would
only need to worry about dynamically loading 'view/page' specific
modules which the developers can configure themselves.
And is there a way to do both? Such as, initilize the modules that are needed across all the pages and then, load specific modules dynamically on their respective pages.
Yes, yes, there is ... SPA approach that I have already outlined
above. I would also recommend using angular-ui-router for the
states and views approach. The idea is to design your application
whilst thinking of it as a desktop or mobile thick client that has
state transitions and so forth.
I have a site that is developed by multiple developers that has multiple pages.
Each "page" initialises angular by calling angular.module(etc).
My question is, all pages share some modules, and some pages use specific modules.
What is the best practice to achieve this?
Do I trust that developers will insert the correct modules that will be needed across the site (i.e. Google Analytics)
or do I create one call that is shared my all pages that loads ALL the modules.
And is there a way to do both?
Such as, initialise the modules that are needed across all the pages and then, load specific modules dynamically on their respective pages.
I would start off by defining what a page is.
Are you talking about a SPA or a more traditional setup a la client transitions between pages with a regular <a href="/page"> and
the server serves the client a piece of HTML?
If the latter is true, then I would urge you to reconsider your underlying approach to your Angular application.
The best (or rather, preferred) way of doing things would be to serve the client a single piece of HTML, and then
transition between pages (from now on I will refer to them as states), by using either ngRoute, angular router (2), or
better yet - ui-router.
For the remainder of my answer I am going to assume that you are in fact working with a SPA.
What is the best practice to achieve this?
As it stands, I would go out on a limb and say that there is no best practice defined for the case you present.
There are a ton of ways to do it, none of which have been officially recommended by the core development team / community standard as far as I'm concerned.
You could go with webpack-angularjs-lazyload, requirejs (angular-requirejs-seed), requirejs (angularAMD), SystemJS among others. Pick your poison of preference!
Do I trust that developers will insert the correct modules that will be needed across the site (i.e. Google Analytics)
or do I create one call that is shared my all pages that loads ALL the modules.
If code contained in an angular.module is required across the site, I would attach it to the main application module.
Such as:
/** Define core functionality that _is_ essential to the application running as expected **/
angular.module('core-module', [ 'route-definitions', 'http-interceptors', 'google-analytics' ]);
/** Inject the core functionality into a bundle module **/
angular.module('main-bundle-module', [ 'core-module' ]);
/** Bootstrap the bundle module as your application **/
angular.bootstrap(/* DOM element */, ['main-bundle-module']);
Now, whenever someone creates a new module for a specific state, they will need to inject said module into the main-bundle-module (barring lazy loaded modules).
As such, the core functionality will always be supplied and available, in your case Google Analytics. In a sense, you just tore down
the trust barrier.
Taking a step back, lets for a moment assume that you are not working with a SPA - and you are in fact re-initialising the
angular application on each page transition (bad move). How would you ensure that the required functionality is always present?
Decorating the angular.module method.
Note: This is not officially supported, be wary of what you are doing. Also it defeats the purpose of modularisation in my opinion, but I'll
showcase the way(s) of doing it.
You could go two ways here I reckon:
Kill the execution of JS if the required module is not a part of the developers module definition.
"Bad cop."
This would catch the 'untrusted developer' in his/her tracks during development, so as to ensure they are following the project standard.
Assist the 'untrusted developer' by automating the task of requiring the module.
"Good cop." (well, sort of...)
This would ensure that the required module is always present, albeit in every module.
"Good Cop"
(function(angular) {
// The always required module(s).
var ALWAYS_REQUIRED = ['cs.core'];
// Keep a reference to the original angular.module function.
var originalFn = angular.module;
// Keep track of registered modules.
var registered = {};
angular.module = function (name, dependencies, configFunction) {
var loaded;
// Ensure that we are always working with an array of dependencies.
dependencies = dependencies || [];
// If the module has not already been registered
if (!registered[name]) {
// Ensure that the required modules are available.
ALWAYS_REQUIRED.forEach(function (required) {
if (dependencies.indexOf(required) === -1) {
dependencies.push(required);
}
});
// Register the module and store it in the registered object for future reference.
loaded = registered[name] = original(name, dependencies, configFunction);
} else {
// Do not re-register the module, simply load it as per 'angular.module('name_of_module')';
loaded = original(name);
}
// Return the loaded module.
return loaded;
};
})(angular);
"Bad Cop"
(function(angular) {
var ALWAYS_REQUIRED = ['cs.core'];
var originalFn = angular.module;
angular.module = function (name, dependencies, configFunction) {
ALWAYS_REQUIRED.forEach(function (required) {
if (dependencies.indexOf(required) === -1) {
throw new Error('You need to add ' + required + ' to ' + name + '\'s module dependencies!');
}
});
return originalFn(name, dependencies, configFunction);
};
})(angular);
That's two ways of killing the trust issue, but in doing so we've introduced code that;
Is not very pretty.
Is definitely not very well tested / battle proven.
Kills modularisation to boot.
And is there a way to do both?
Such as, initialise the modules that are needed across all the pages and then, load specific modules dynamically on their respective pages.
I would say the best way to do so is to:
Take the steps necessary to convert to a SPA.
Write some documentation for all your developers so as to bring them up to speed on the requirements of the project.
Create a standalone module containing the required core functionality and attach it to your ng-app/angular.bootstrap module.
Get ui-router, ui-router-extras and ocLazyLoad to allow for lazy loaded module/state/component definitions.
Have a look at some of the following links for inspiration/ideas on what fits your specific project:
ocLazyLoad-SystemJS-Router by #lookfirst
ng-jspm-seed#futureStateConfig by #kasperlewau
ocLazyLoad#with-your-router
ocLazyLoad+requirejs plunker
webpack vs browserify #stackoverflow
angular + webpack slides
tl;dr
Convert to a SPA.
Bootstrap the application with core functionality supplied.
Write some documentation for untrusted developers.
Better yet, build trust. :)
Lazy load state-specific modules when needed.
You can try browserify to load and build your javascript in single file.
With this you can easy minify the javascript code, and also you can load nodejs modules like events and more, but this is not your question about.

AngularJS bootstrap methodology

I'm trying to manage the bootstrap process of a large AngularJS/Grails application. Here's what I've come up with, but I'm not so sure it's as clean as it could be, or as efficient. Thoughts?
Load angular-loader in a one-line minified /script
Load jquery explicity in another /script
Load a third-party async loader ($script) and all of the remaining dependencies
When the dependencies have loaded, call angular.bootstrap(document, ['myApp]);
Load my minified, concatenated app-specific javascript in another /script
This seems clunky. What alternatives might there be? I did consider RequireJS, but I don't like how intrusive it is, and I like using a grunt task to concat+uglify my app into a single script.
The general approach that I use is to load the basic components upfront and only load the controller and associated services on demand using RequireJS. Obviously, this is only applicable if you are dealing with large application.
As AngularJS does not natively support on-demand loading and delegate such task to async loader such as RequireJS, I encapsulated the logic need in something I call angularAMD.
Here is a sample site I created to illustrate how angularAMD works:
http://marcoslin.github.io/angularAMD/

Does Angular.JS have a module loader or do I need to use script tags?

I am using Angular JS. I wish to put unrelated code (ie, which is not a factory, service, controler, etc) in additional, separate modules, in a similar way one would with AMD or CommonJS.
At the time of writing, a search for 'Angular.JS make new module' using Google does not return any documentation on making Angular.JS modules.
I have a found a post on the Angular.JS Google Group that seems to indicate that instead of loading dependencies dynamically like other module systems, in Angular.JS dependencies must be inserted as additional script tags.
Is there any documentation on making Angular modules (which is not limited to controllers, services, or other angular concepts)?
Is the statement about script tags true? Do I need to manually add script tags for every module I may use?
Looking further into the various Angular boilerplate apps, apps manually load every part of their apps via script tags. Unlike other systems, Angular 'modules' don't take care of actually loading dependencies, they just inject them once already loaded.

Resources