I'm writing a complex, multi-component app using AngularJS. Currently, the main components are ready and I want to improve the performance of the app.
After a short investigation on the field, I found some very useful resources:
11 Tips to Improve AngularJS Performance
Improving AngularJS wep app performance example
AngularJS Performance in large applications
Anyway, I need some additional advises on a few topics:
1. Script and Services/Factories loading
currently, all scripts are loaded at the bottom of the <body></body> tag inside index.html. Therefore, when the user loads directly a ui-route or we simply reload given page, all the scripts are loaded again. I want to load the scripts only in states that use the given script.
Services/Factories/etc. are loaded the same way. This causes pages which do NOT need the given e.g. Service to load it and this is slowing the performance, because of the big data load. I need to initialize/load them only when they are needed in the current state.
2. Translation/Localization
I'm using Angular Translate - i18n Reference, but when I'm translating the page elements I must use e.g. <button>{{btnName | translate}}</button. This technique and the overall usage of filters is pointed as one of the biggest performance drawbacks. The page has a lot of elements so this really might slow the loading. Is there any better solution or any workaround?
3. Overall
I've read the multiple threads on ng-repeat and its track by feature, so I assume it done, but I'm still not 100% sure that I understand the $digest ($apply) cycles correctly.
I read some comments that we should "avoid bind anything directly to a function", but I don't quite get it.
Any additional comments or advises relative to AngularJS and its performance are welcome!
Thank you :)
Reading the above, it looks like you already tried to optimize AngularJS itself. However, there is no mention of optimizations on your build process. I guess it would be wise for you to investigate Grunt or Gulp. With these tools you can concatenate and minify all your JavaScript to a single minified file. This way you only have a one-time payload while initialising your site.
Check this https://medium.com/#dickeyxxx/best-practices-for-building-angular-js-apps-266c1a4a6917
Related
I am relatively new to web design and the world of jquery, javascript and php. I guess this question would also suit css style sheets as well. Is it better to have everything stuffed into one "external document"? Or does this not affect the run time speeds?
Also to go along with this. Is it wrong, or less efficient, to use php in places where jquery / javascript could be implemented? Which of the two languages is generally faster?
The way you should look at it would be to load the minimum resources required initially which would be needed on page load, not everything. Make sure you group all of these resources together into a single file, and minify them.
Once your page is loaded, you can thereafter load other resources on demand. For e.g a modal, which does not need to be immediately visible can be loaded at a later point of time, when user does some action, and it needs to be shown. This is called lazy loading. But when you do load any module on demand, make sure you load all of its resources together and minified as well.
It's important to structure your code correctly and define the way you batch files together for concatenation and minification. It will help you save on performance by optimizing the number of calls made to the server.
About PHP and JavaScript, I would say in general JavaScript is faster than PHP, but it depends on your application, as one runs on the server and other on the client. So if you are doing too heavy and memory intensive operations, the browser might limit your capabilities. If that is not a problem, go ahead with JavaScript.
There's a lot of different factors that come into play here. Ultimately, it is better to call the least amount of resources possible to make the site run faster. Many sites that check page speed will dock points if you call a ton of resources. However, you don't want to go insane condensing and try to cram everything into a single file either... The best way to approach it is to use as few files as possible while maintaining a logical organization.
For example, maybe you're using a few different JS libraries... well merging those all into one would eventually get confusing and hard to update so it makes sense to keep them all separate. However, you can keep all your custom JS where you call those libraries in one separate file. This can even be applied to images. Let's say you're uploading 5 different social media icons and 5 different hover states for them. Well, instead of making the site call 10 different files, use a sprite and just call one.
You can also do things like use google's hosted libraries: https://developers.google.com/speed/libraries/ Many sites use these and therefore many users already have these resources cached which means they don't need to freshly load the libraries when visiting your site. It's very helpful for things like jQuery.
Another thing to keep in mind is minifying those files. Any library you use should have a minified version and you should use that as opposed to a full version. While you should keep unminified copies of your work around, whatever ends up on the live site should be minified to help with page speed. Here are a few resources for that: https://cssminifier.com/ https://javascript-minifier.com/ If you're using WP, there's tons of plugins out there that have similar functions like WP Fastest Cache.
You php/js/jquery question I can't really weigh in on too heavily. As mentioned, the base difference between php and JS ist whether the requests are client-side or server-side. Personally, I use whatever is prevalent in the project and whatever works best for your changes. For example, if you're working with variables and transferring data, PHP can be a really great
As far as I know, Aurelia does not support server-side rendering as mentioned here.
But the question is: is it possible to do this with some hacks/workarounds?
The most obvious idea would be to use Phantom, Nightmare.js or whatever to simply render that page in Chrome on server and serve that to client, but this is very likely to cause big productivity issues.
Thanks!
UPD
According to Rob Eisenberg's response on FDConf today (16 Apr 2016), server-side rendering will be implemented in 2016, there's one core team member working on that and there's a deadline for this feature.
There is an open issue for Universal/Isomorphic Aurelia which you can monitor. In particular EisenbergEffect (who is Rob Eisenberg, the creator of Aurelia) states that they are gradually working towards providing Universal support for Aurelia. This post from him provides most of the detail:
EisenbergEffect commented on Aug 25
We are trying to lock things down within the next month. That doesn't
mean we won't add anything after that, but we need to work towards
stabilization, performance and solid documentation without
distractions of lots of new features for a little bit.
Primarily, "isomorphism" isn't a use case we want to tackle for the
initial v1 release. Again, that doesn't mean we won't do it later.
But, we want to have a solid framework for browser-based apps as well
as phone gap and electron/nwjs desktop apps first. That was our
original goal and we want to make sure we handle those scenarios
better than any other framework or library.
After that, we've got some other features we want to do, which are
valuable in their own right, but will also take us closer to
isomorphism.
Enable all aurelia libraries to run on the server. This enables some
new testing scenarios, so it's valuable if only from that perspective.
Once code can run on the server, we can then implement server view
compilation. This isn't isomorphic rendering, but rather the ability
to run Aurelia's view compiler as part of your build and bundle
process. This enables more work to be done ahead of time, as part of
your build, and then it doesn't need to be done in the browser at
runtime. So, this will improve the startup time for all apps and
reduce initial render times for all components. It also will make it
possible to store compiled views in browser local cache to improve
performance of successive runs of the application.
After both of those
things are in place, then we can look at doing a full server render
for each route. This isn't quite isomorphic in the truest sense, but
it solves the SEO problem without needing 3rd party libraries. So,
it's nice to have a solution there.
Finally, we can then "sync" a
server pre-rendered app with a stateful Aurelia app running in
browser, giving us 100% isomorphic support. So, those are the stages.
The first two would be beneficial to all developers, even those who
are not interested in isomorphic apps. The 3rd stage can be done today
with 3rd party libraries, so this is a nice to have for us, for those
who don't want an extra dependency. All of that leads into 4 which
adds the final pieces.
We have already begun some of the work on 1. That might get into our
first release. We aren't going to push it, but it's already in
progress and we're looking for the problem areas so we can make it
work. Steps 2-4 involve significant work. Really, we are talking about
a collection of features here, each one being rather complex. So,
those will probably come in stages after v1, as point releases.
We really don't want to do what Angular 2 has done. They have
massively complicated their architecture...to the point that very few
people will be able to understand it and developing applications with
it has become much more complicated, with many nuances. We really
don't want that, so we're focusing on the developer experience we want
first, then we'll come back and see about isomorphic support (yes, we
already have ideas how to do this cleanly, but want to give those
ideas some time to mature). In all of this, our goal is to be modular.
So, if you don't care about isomorphism, you don't have to think or
worry about it. If you do, you would install the necessary packages,
agree to the "constraints" of the system and be on your way.
So, to all who are interested in this topic, I would just ask you
kindly to be patient. For those who aren't interested in isomorphism,
don't worry, we aren't going to brake the developer experience on you.
For those of you who want it badly, you will have to wait longer and
it will come in stages and in modular pieces so as not to disrupt
others.
Just for now
The only way I can propose: render pages with phantomjs + use redis to speedup that process.
But you will have lots of trouble restoring the state at client side.
.......
Dirty solution
Load rendered page from server and at the client side render new one in the usual way, than switch UI's.
It won't be a truly isomorphic, but something like https://github.com/rails/turbolinks on first page load.
.....
I hope soon Aurelia team will provide simpler stuff for that case.
In the current Aurelia there is the possibility to enhance existing html.
The document says
So far you've seen Aurelia replacing a portion of the DOM with a root component. However, that's not the only way to render with Aurelia. Aurelia can also progressively enhance existing HTML.
Check out enhancement section # http://aurelia.io/docs.html#/aurelia/framework/1.0.0-beta.1.0.8/doc/article/app-configuration-and-startup
I'm looking forward to get a better documentation of this feature.
It seems to me like rendering the html on the Server and inject aurelia will work with it and google will like it as well.
a hack i just came up with is to put a static copy of the initial rendering into the index.html file:
<html>
<body aurelia-app="main">
<h1>static copy of the website here</h1>
<script src="scripts/vendor-bundle.js" data-main="aurelia-bootstrapper"></script>
</body>
</html>
this is of course completely manual and if the initial rendering contains any content from a database then the static copy may need to be updated
every time the database content changes. (which is of course what isomorphic rendering is supposed to solve)
however for my needs, which is a simple website with some information that is rarely updated, this solution is good enough. it will at least suffice until i am able to implement proper isomorphic rendering.
I want to ask whether there is a way to deploy the angular apps i.e. (modules, controllers, factories) and the bindings so that when users would inspect it or view page source on their browsers they're shown the html and not the bindings like for example {{persons.name}}, {{persons.email}}.
Even when we use ng-bind or ng-bind-template we have our model objects displayed in the code inspection or view page source views of browser.
Understandably the framework it self is based on Java script to start with and the scripts are required on the page, but my question is that is there a way to hide the underlying model architecture in the controller or factories written for some app ?
Can we use some technique for building our scripts and executing them on run time instead while our app initializes and not make code (in our scripts) and bindings (in our html) observable to the users ?
I have done a bit of searching and haven't yet found a suitable solution, most of the articles and references regarding Angular point towards it's core concepts instead.
I have recently started working on Angular so I'm trying to do things the right way as I have a jQuery background.
It sounds like you are wanting to know if you can pre-render angular. While there are some technologies that do this, it is for the sake of search engine optimization, not for end-user use. This is because AngularJS is run client-side. If you have to pre-render it, you completely defeat the purpose of having it (honestly, you should just go with some other technology that does server-side rendering).
If you want to 'hide' your angular code, about all you can do there is minify it with something like uglify. This will make your angular code incredibly difficult to work with, and smaller for the end-user to download. There is an additional 'mangle' capability that uglify offers, but my understanding is that it is difficult or impossible to get it to work with angular due to some of angular's peculiarities regarding dependency injection.
To hide bindings like {{persons.name}} during page loading just add the ng-cloak class to your container (don't forget to add angular css file to your page), Angular will display it when everything is loaded.
You can't, as far as I know, hide your directive in your html code, but honestly I don't think it's really a problem, in front-end development your code is anyway always observable.
Short Answer: No
its not possible to hide the underlying model since Javascript is interpreted at client side it will always be possible to view the underlying model.
However you can also view the interpreted version of your HTML with firebug or any other debugging tool
I'm writing Angular.js application. I want it to be really fast, therefore I serve it completely generated server-side when it is initially loaded. After that every change should be handled client-side by Angular with asynchronous communication with server.
I have ng-view attribute on central <div>. But now Angular regenerates content of this <div> even on first load, before clicking any link. I don't want this behavior because then the server-side generation of page is useless.
How to achieve that?
Although Gloopy's suggestion will work in some cases, it will fail in others (namely ng-repeat). AngularJS does not currently have the ability to render on the server, but this is something that (as far as I know) no other JavaScript framework does either. I also know that server-side rendering is something that the AngularJS developers are looking into, so you may yet see it in the not-too-distant future. :)
When you say you want the application to be "really fast," you should consider where exactly you want this speed. There are a lot of places to consider speed, such as time it takes to bootstrap the app, time it takes to respond, resource intensiveness, etc (you seem to be focusing on bootstrap time). There are often different trade-offs that must be made to balance performance in an application. I'd recommend reading this response to another question on performance with AngularJS for more on the subject: Angular.js Backbone.js or which has better performance
Are you actually running into performance issues, or is this just something you predict to be a problem? If it's the later, I'd recommend building a prototype representative of your type of application to see if it really is an issue. If it's the former and it's taking your app too long to bootstrap on the client side, there may be some optimizations that you can make (for instance, inlining some model data to avoid an additional round trip, or using Gloopy's suggestion). You can also use the profiling tools in Chrome, as well as the AngularJS Batarang to look for slow areas in your application.
btford: You are absolutely right that this sounds like premature optimization - it sounds that way to me either :). Another reason is, that the application should work without JS in very simple way, so this basic layout (and angular does that for me for all other pages), so there will be always rendering on server.
I found a very hacky ugly solution - I bootstrap application after first click on any internal link. After clicking it, I unbind this initial callback, update URL with History.pushState and bootstrap app - it grabs the new URL and regeneration is absolutely OK. Well, I'll keep looking into not-too-distant future :).
I was able to come up with a solution for doing this. It doesn't work perfectly or for everything, but it is ok at least as far as routing and the directive I made that uses ng-repeat.
https://github.com/ithkuil/angular-on-server/wiki/Running-AngularJS-on-the-server-with-Node.js-and-jsdom
I've been doing research on this:
Using Rails 3.1, where do you put your "page specific" javascript code?
But I have yet to see a satisfactory answer, which also makes me question whether I'm doing something wrong.
Here's my mental model: for different views, I'm going to have different
$(document).ready(....)
blocks, that obviously reference elements that are very specific to that page. I don't want to pollute things by loading that code for every single page and somehow trying to figure out how to only execute it when on specific pages; that seems pretty ugly.
My intuition, admittedly not backed up by any preliminary experiments, is that the ideal thing would be to:
Load application wide code from application.js.
Load shared controller code from something like assets/controller_name/shared.js
Load view-specific code from something like assets/controller_name/show.js
Off the top of my head. The helper would, the first time it ran, check if the file exists and, if so, do a javascript_include for it.
Perhaps this has some performance issues compared to the "let's just wrap the whole thing up in a big sticky ball and send it all" approach, but seems like a better approach to compartmentalizing code.
However, as above, I get the feeling I'm missing something. Is $(document).ready on a per-page basis a bad idea? Should that just be in the template and call a page specific bit of JS from application.js? The linked article above comes to that conclusion, but I don't like the image I'm getting in my head of one huge $(document).ready riddled with if this, if that, if the other thing.
What you propose is sound, but not the rails 3.1 way.
They say to divide the JS into many files, but serve as a whole single piece to the user. This allows better performance and scalability, so is a good thing if the final big piece of mud is not so big. Really 3 http requests give worse performance than 1 http request.
So you have already dipartimentized your code, because you have different Coffeescript files, which have different scopes.
To load in your app, just standardize a way to initialize the single piece of code, like calling a "myapp.users.init()" method-.
You could even automatize that peace of code using an helper, so it will be transparent for the controller.
Background
(Why Use The Asset Pipeline At All?)
One of the basic premises behind the Rails asset pipeline is the idea that it is preferable to load all the JS and CSS for a site up front once, and then cache them indefinitely (at least until the site is updated). The Asset Pipeline allows you to do this relatively automatically while still organizing your JS and CSS src files in a logical fashion.
This of course carries an upfront load cost, at the promise of saving time on additional roundtrips loading individual files. If that premise doesn't sit well then the asset pipeline is probably not for you.
The Nut Of The Problem
Ok, so we want to combine all our JS into one file to load it more efficiently. Just because we are going to load all of our JS doesn't mean we want to run all of our JS.
In the reality of a complex webapp you will probably have lots of page specific functionality that you won't want to spend resources executing when the user is not viewing the corresponding page. What we need is a uniform strategy for executing only the portion of our big monolithic JS file that is applicable to the current page.
Convention To The Rescue
I'm not aware of an official Rails strategy to deal with this, but there are some great solutions that establish and then leverage a good convention (which makes things feel "railsy"). The general idea is to define all your page specific JS code into an object literal, and then run only the code relevant to the current page on load.
For the specifics great strategy on how to organize and conditionally execute your JS code, see the answer by #welldan97 on this question:
Using Rails 3.1, where do you put your "page specific" javascript code?
which in turn is based on this article by Jason Garber:
http://viget.com/inspire/extending-paul-irishs-comprehensive-dom-ready-execution