Faster AngularJS Rendering (AngularJS and ReactJS)

Have you used AngularJs and ran into some performance problems? Using ReactJs rendering becomes much faster. A small examples explains how to use ReactJs for rendering in AngularJs and a comparison is made between native rendering and rendering using ReactJs.

I like AngularJS. I use it when I do some little fun projects and I use it professionally in large Web apps. I tried other frameworks as well, like BackboneJS and EmberJS, which both are great tools as well. All three of them belong to the class of MVC frameworks (or MVVC whatever you want o call them). But whenever I used any of such a tool I always ran and still run into the same problem: Rendering performance of lists of items. Two way binding or one-way binding makes no real difference. For me BackboneJS had better performance for rendering than AngularJS. Lets put that on the back of two-way binding.

Now there is this great tool coming along called ReactJS. And this little innocent looking lib will definitely make one of the biggest changes in JavaScript MVC frameworks for the last couple of months (if not years). In short words, this library will make rendering finally fast. ReactJs calls itself the V in MVC (the View). At first I was wondering, why the hell would I want to drop the MC part? The MC part is where the fun is in all these frameworks like EmberJs, BackboneJS and AngularJS, right? After a closer look, you can actually see that ReactJs has quite some features of the C (controller) part as well, but yet ReactJs is not a full featured MVC framework and does not intend to be. The way ReactJs works is to keep a virtual DOM and render only what actually changes when the UI is updated?? Does that make sense, sounds new but so true. Send command to update UI, React compares these changes to existing DOM (using the Virtual DOM for ultra-fast diff) and React only updates what is needed. The cool stuff is actually that the the diff of changes can be performed very fast on the Virtual DOM. Facebook and Instagram have developed ReactJs and are using it in production.

I listened to a podcast with Pete Hunt, dev of ReactJ, where this guy talks about the intention of ReactJs. To resume in this place, but be sure to listen to this podcast, the intentions behind open sourcing ReactJs are make some noise in the V part of existing frameworks. And I think that existing frameworks are going to adopt the same or similar strategy for their UI part, or new libraries will come up that can be used.

As ReactJs is the V it can be easily as V in existing frameworks already today. BackboneJS , more, with AngularJS, ngReact  orhere. Use it with Coffeescript? So you can use ReactJs to render those parts of your App where some performance comes in handy, for example ng-repeat with a few hundred items. In a previouspost, I blogged how to make long lists ‘usable’ in AngularJs, but all these techniques to make “rendering” faster all rely on rendering only a part of the list. Using ReactJs with AngularJs, your rendering time will drop by about 80%. I played with ngReact and I experienced a performance increase that made me think something was wrong. Rendering time dropped from about 4200ms in native AngularJs to 120ms using ReactJs.  Go check ngReact out to try it yourself, or have a look at the plunkrs in this post.

I still experienced some issues when there are too many bindings in the DOM with AngularJS, but this is another problem that is specific to two-way binding. If you are too scared of this problem, you should probably go with another framework than AngularJs. ReactJs just helps us getting things as fast as possible on he screen of the user and here ReactJs is making a great job.

I will show a small example on how to use ReactJs to render the view for an Angular app. I installed bower and then

user@computer:$ mkdir fast-angular

cd fast-angular

bower install –save react

bower install –save angular

And then we are good to go. We only need ReactJs and AngularJs. We create a simple html file with both scripts loaded:

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width">

  </head>
  <body>
    <h1>Fast AngularJs</h1> <h3>AngularJs with ReactJs</h3>


    <script src="bower_components/angular/angular.js"></script>
    <script src="bower_components/react/react.js"></script>

</body>
</html>

What we are going to create is a small ReactJs component that renders the string that we enter. So we use reactJs to render our model. We create a component called MYAPP, that renders a props that is passed to it. Then we create a traditional angularJs directive and controller (add the tags to our html, to start the app). The directive instead of rendering calls the ReactJs component and tells it to render. We use a $watch on framework to re-render on update. From the ReactJs docs calling createComponent when Component is already mounted updates the existing instance. (using React Chrome Dev integration tools, I keep on having the same instance ID, so I assume docs are true ) (See it live here http://plnkr.co/edit/FXK3lU?p=info)

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width">

  </head>
  <body ng-app="fasterAngular">
    <h1>Fast AngularJs</h1> <h3>AngularJs with ReactJs</h3>
    <div ng-controller="mycontroller">
        <input ng-model="framework"/>
        <hr>
        <fast-ng framework="framework"></fast-ng>
        <hr>
        Rendering with traditional AngularJs {{framework}}
    </div>

    <script src="bower_components/angular/angular.js"></script>
    <script src="bower_components/react/react.js"></script>
    <script >
        var MYAPP = React.createClass({
            displayName:'MYAPP',
            render:function(){
                return React.DOM.div(null, "Rendering faster in AngularJs with ", this.props.framework);

            }
        });
    </script>

    <script>
        angular.module('fasterAngular', []).
        controller('mycontroller', ['$scope', function($scope){
            $scope.framework = 'ReactJs';
 
        }]).directive('fastNg', function(){
            return{
                restrict:'E',
                scope:{
                    framework:'='
                },
                link:function(scope, el, attrs){
                    scope.$watch('framework', function(newValue, oldValue){
                        React.renderComponent(
                            MYAPP({framework:newValue}),
                            el[0]
                        );
                    })
                }
            }
        })
    </script>
</body>
</html>

Of course this simple example does not make us gain some performance, but It illustrates how we can use ReactJs to render our model. An other example that shows the performance is the next one, where we render a long list of numbers. The example is taken from the example of ngReact. We generate an Array with 1500 data entries and render it in a table. This is usually what brings some performance problems with native ng-repeat in AngularJs. See this Plunkr for rendering using ReactJs (http://plnkr.co/edit/ykYILa) and this one for native ngRepeat rendering (http://plnkr.co/edit/YnF7Vn). See code here, rendering with ReactJs

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width">

  </head>
  <body ng-app="fasterAngular">
    <h1>Fast AngularJs</h1> <h3>AngularJs with ReactJs</h3>
    <div ng-controller="mycontroller">

        <fast-repeat data="data"></fast-repeat>

    </div>

    <script src="bower_components/angular/angular.js"></script>
    <script src="bower_components/react/react.js"></script>

    <script >
        var MYLIST = React.createClass({displayName: 'MYLIST',
            render: function() {

              var data = this.props.data;

              var rows = data.map(function(datum) {
                var clickHandler = function(ev){
                    console.log("Still in reactJs");
                    console.log(ev);
                }

                return (
                  React.DOM.tr( {onClick:clickHandler},
                    React.DOM.td(null, datum['0']),
                    React.DOM.td(null, datum['1']),
                    React.DOM.td(null, datum['2']),
                    React.DOM.td(null, datum['3']),
                    React.DOM.td(null, datum['4'])
                  )
                );
              });

              return (
                React.DOM.table(null,
                  rows
                )
              );
            }
        });
    </script>
    <script>
        angular.module('fasterAngular', []).
        controller('mycontroller', ['$scope', function($scope){
            $scope.framework = 'ReactJs';
            $scope.data = [];
            // Fill the data map with random data
            for(var i = 0; i < 1500; ++i) {
                $scope.data[i] = {};
                for(var j = 0; j < 5; ++j) {
                    $scope.data[i][j] = Math.random();
                }
            }
        }]).directive('fastRepeat', function(){
            return{
                restrict: 'E',
                scope:{
                    data: '='
                },
                link:function(scope, el, attrs){
                    scope.$watch('data', function(newValue, oldValue){
                        React.renderComponent(
                            MYLIST({data:newValue}),
                            el[0]
                        );
                    })
                }
            }
        })
    </script>
</body>
</html>

A similar example where you can update the Data with a button Plunkr for Native Angular (http://plnkr.co/edit/YnF7Vn) and using ReactJs (http://plnkr.co/edit/6zfFXU)

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width">

  </head>
  <body ng-app="fasterAngular">
    <h1>Fast AngularJs</h1> <h3>AngularJs with ReactJs</h3>
    <div ng-controller="mycontroller">
        <button ng-click="refresh()">Refresh Data</button>
        <fast-repeat data="data"></fast-repeat>
        <!-- <table>
          <tr ng-repeat="line in data" ng-click="clickHandler(ev)">
            <td>{{line[0]}}</td>
            <td>{{line[1]}}</td>
            <td>{{line[2]}}</td>
            <td>{{line[3]}}</td>
            <td>{{line[4]}}</td>
          </tr>
        </table> -->
    </div>

    <script src="bower_components/angular/angular.js"></script>
    <script src="bower_components/react/react.js"></script>

    <script >
        var MYLIST = React.createClass({displayName: 'MYLIST',
            render: function() {

              var data = this.props.data;

              var rows = data.map(function(datum) {
                var clickHandler = function(ev){
                    console.log("Still in reactJs");
                    console.log(ev);
                }

                return (
                  React.DOM.tr( {onClick:clickHandler},
                    React.DOM.td(null, datum['0']),
                    React.DOM.td(null, datum['1']),
                    React.DOM.td(null, datum['2']),
                    React.DOM.td(null, datum['3']),
                    React.DOM.td(null, datum['4'])
                  )
                );
              });

              return (
                React.DOM.table(null,
                  rows
                )
              );
            }
        });
    </script>
    <script>
        angular.module('fasterAngular', []).
        controller('mycontroller', ['$scope', function($scope){
            $scope.framework = 'ReactJs';
            $scope.data = [];
            // Fill the data map with random data

            $scope.clickHandler = function(){
                console.log("in AngularJS");
            }
            $scope.refresh = function(){
                for(var i = 0; i < 1500; ++i) {
                    $scope.data[i] = {};
                    for(var j = 0; j < 5; ++j) {
                        $scope.data[i][j] = Math.random();
                    }
                }
            }
            $scope.refresh()
        }]).directive('fastRepeat', function(){
            return{
                restrict: 'E',
                scope:{
                    data: '='
                },
                link:function(scope, el, attrs){
                    scope.$watchCollection('data', function(newValue, oldValue){
                        React.renderComponent(
                            MYLIST({data:newValue}),
                            el[0]
                        );
                    })
                }
            }
        })
    </script>
</body>
</html>

To render 1500 rows, with AngularJS the time to render was about 1.35 seconds. When we let ReactJs do the rendering time was about 310ms. I attached the timeline for both from Chrome Dev Tools

 

Rendering with ReactJs, 320ms

Rendering with ReactJs, 320ms

Native AngularJs rendering 1200ms

Native AngularJs rendering 1200ms

This is just a short introduction to use ReactJs with AngularJs. For some parts of my next apps I will definitely use ReactJs to render parts of it where I think that performance will be an issue. ReactJs, as said by Pete Hunt,  is quite a game changer and the intentions behind is to show the general idea of its internal workings. I assume all major frameworks will soon have a similar concept that will be used with them or something to integrate easily. I like ReactJs and the idea behind to use a virtual DOM for the diff makes perfect sense.

In a coming up post I will write about communication between ReactJs and AngularJs, follow me on twitter to stay tuned. I am just playing around…if you think I made some terrible mistakes, ignore best practices, break stuff…etc please comment or write me and I will happily learn and update this post.

 

UPDATE 21.04.2014 21:00 CET: This post was creating some discussions and I got a bigger response than expected. Some people gave good feedback and other ideas to explore. Others questioned the usefulness of combining ReactJs with AngularJs. I try to explore the constructive feedback given and leave the more subjective response to everyone to figure it out. Find the discussion here: Hackernews,  and Reddit.

* The argument that the loaf of another JS file does not value the performance increase, did not maybe see that this performance helps increasing responsiveness of the app and therefore increase usability. And not only on initial call be on every update. For me I have been spending ours to make WebApps react faster on user input. Webapps already have a great difficulty to deal with (300ms delay). For me I will to a reasonable amount always choose what helps usability.

* The first hint was to use track by $index in the ng-repeat directive (“…With this association in place, AngularJS will not $destroy and re-create DOM nodes unnecessarily. This can have a huge performance and user experience benefit….” read here about it, and official docs) As far as I understood track by $index, this will only render faster when DOM is updated, but not on INITIAL rendering. So I tested again using the same example as above, let the test run several times and found the following results

  1. AngularJs + ReactJs: (http://plnkr.co/edit/6zfFXU?p=preview) Initial loading: ~ 243ms, Updating: ~ 125ms
  2. AngularJS using Track By (http://plnkr.co/edit/5FCsQO?p=preview) Initial loading: ~ 990ms, Updating: ~130ms
  3. AngularJs ngRepeat (http://plnkr.co/edit/YnF7Vn?p=preview) Initial loading: ~ 1100ms, Updating: 1150ms

So Track By $index does really have a huge impact when model is updated. (jn plunkrs hit refresh button in HTML), but initial rendering is still slow. I tried to run the tests several time and times may vary a little but the trend never changed. See timelines here:

AngularJs with ReactJs Updating

AngularJs with ReactJs Updating

AngularJs with ReactJs Initial Load

AngularJs with ReactJs Initial Load

Straight AngularJs. Updating

Straight AngularJs. Updating

Straight AngularJs Initial Load

Straight AngularJs Initial Load

AngularJs using Track By. Updating.

AngularJs using Track By. Updating.

AngularJs using Track By Initial Loading

AngularJs using Track By Initial Loading


* Virtual DOM in AngularJS: Ahmed pointed out in the comments (down here) the point of view of AngularJS Team on Virtual DOM.  http://www.youtube.com/watch?v=srt3OBP2kGc#t=118 As I think too, making the diff on a virtual DOM is what sooner or later will be done by default either in Browsers or frameworks. As Pete Hunt stated in the podcast linked above, that was the intentions of ReactJs’ Team

* BindOnce? I don’t think that https://github.com/Pasvaz/bindonce has anything to do here with the performance of rendering. The performance that is gained is a different one, when there are too many bindings any updates becomes slow, scrolling is lagging..etc. Here it is just writing and updating the DOM. Please comment me if you think I am wrong, or provide examples.

* Rendering using Mustache or Handlebars (In comments): I tried the plunkr and yes, rendering the DOM (initial and updating) is fast. Initial load ~ 220ms and updating is even faster ~ 120ms. That is also impressive numbers. This is even faster than with ReactJs. But I think that something goes lost here. In the examples there is always a click handler on the rows that renders to the console. Is this possible with Mustache or Handlebars? I am still working on an example to get the communication between AngularJs and ReactJs going, and I guess this is not possible with a template lib like Mustache or Handlebars. But be assured Mustache is rendering fast and I will keep it in mind for future work.

* Mithril, seems to be a new framework on the market. I know I already came across the framework once, but it seems to be rendering fast. Also using a virtual DOM. Difficult to tell which direction this framework will take? But the works seems interesting and I will check into the code to see what is so different from ReactJs virtual Dom.

Looking forward to more feedback. AngularJs 2.0 is on the way and I don’t know whtas coming, but I really appreciate the way the folks at Google have chosen to develop the framework by including the community.

Reference:

http://www.williambrownstreet.net/blog/2014/04/faster-angularjs-rendering-angularjs-and-reactjs/

https://www.quora.com/profile/Pete-Hunt/Posts/Facebooks-React-vs-AngularJS-A-Closer-Look

Bài thơ tặng vợ tháng 10/2013

Tôi gặp em vào đêm se lạnh những ngày Giáng Sinh năm 2012, đó cũng là lần đầu gặp gỡ. Em là MC, còn tôi là 1 chàng dev quèn say bia, say mồi và say luôn cả em.

Tiệc Giáng Sinh tàn, cũng là lúc tôi ngồi lại để say đàn, say thêm tiếng hát, đương nhiên có cả em. Tôi đàn, em hát.

Tiệc tàn, tôi có đề nghị đưa em về, nhưng lần gặp đầu tiên ấy em còn xa lạ, em được người anh cùng công ty đưa về.

Mấy ngày sau, Chị PM nói tôi theo đuổi em đi, vì anh kia lăng nhăng quá. Nghe là thế thôi, chứ tôi nghĩ chỉ là cuộc gặp gỡ thoáng qua, một kỹ niệm đẹp hằng xâu trong tâm trí.

Thời gian trôi qua, tôi và em không gặp cũng không liên lạc gì. Đến một hôm farewell chị PM ấy. Tôi hỏi vui với chị: “Có rủ em MC hôm nọ không, hôm bữa tôi và em ấy gặp gỡ, giờ lưu luyến quá”, thế rồi chị PM forward message ấy cho em. Em added Skype tôi và bắt đầu những dòng trò chuyện đầu tiên.

Thế đấy, lần gặp lại này đã gần tròn 1 năm rồi, đúng ngày sinh nhật em. Đây là bài thơ tôi viết cho em sau 1 thời gian dài xa cách:

Nhớ lại hôm nào nơi chốn đông,

Gặp em cô gái nhỏ má hồng,

Vô tư em ngắm vầng trăng ấy,

Lặng lẽ tôi nhìn mãi ngóng trông.

 

Hôm nay, gặp lại má vẫn hồng.

Vẫn nụ cười ấy, vẫn hoài mong.

Tiếng đàn ai dạo lời tha thiết,

Tiếng hát em hòa có nhớ không.

 

 

 

7 bước làm tăng tốc độ Google nhận biết website của bạn

Hầu hết những chuyên gia SEO đều khuyên bạn nên mua 1 site domain đã cũ để được Google đánh giá cao hơn và dễ Index hơn, nhưng nếu như bạn bắt đầu tạo 1 website mới thì sao? Thường thì bạn sẽ tốn vài tuần để site của bạn được bộ máy tìm kiếm google biết đến.Tuy nhiên những việc làm theo những bước sau đây sẻ giúp bạn tiết kiệm khá nhiều thời gian cho việc index site (chỉ sau khoảng 24h).

1/ Tạo 5 trang nội dung trong site:

Đừng để site bạn “under construction” (site đang trong quá trình xây dựng) hãy tạo 1 vài trang với nội dung thật sự.

2/ Tạo link nội bộ giữa các trang của bạn:

Hãy sử dụng template thống nhất để quản lý các trang nội dung thông qua các menu. Bạn có thể tìm thấy những template free giúp bạn làm việc này tại freecodevn.com hoặc joomlaviet.org…. Nếu bạn tự tạo thì nhớ hãy đơn giản hóa nó chứ đừng có làm nó quá phức tạp và cầu kỳ. Bạn nhớ liên kết 2, 3 trang (liên kết có chiều sâu)

3/ Đưa trang web của bạn lên các Social Bookmark Sites:

Bạn chỉ mất vài phút để tạo tài khoản và đăng trang web của bạn lên các bookmark site này. Việc làm này giúp các bộ máy tìm kiếm liên kết tìm kiếm trang web của bạn có cách dễ dàng hơn. Các bookmark sites thông dụng là: Del.icio.us, BlinkList, StumbleUpon.com, và Furl. Bạn lưu ý rằng khi ghi vào phần Tag, nhớ ghi những Tag thông dụng và phổ biến.

4/ Đăng trang web của bạn trên những blog phổ biến (nhớ kèm theo link):

Bạn tìm khoảng 5 trang blog phổ biến, và có những bài viết vừa mới viết,thường xuyên . Bạn cố gắng vào đó comment, xây dựng câu truyện và kèm theo link đến trang web của bạn.

5/ Tạo, đưa lên và ping XML Sitemap:

Bạn có thể tạo 1 trang xml free (tìm hiểu làm sitemap cho website) sau đó bạn đưa trang này lên website của bạn sau đó thì ping nó với google bằng link sau: http://google.com/webmasters/sitemaps/ping?sitemap=XXXX (đổi XXX thành link Sitemap trang web của bạn) Sau đó bạn tạo tài khoản Google Webmaster Central, và đưa lên Google XML Sitemap. Một số mã nguồn mở thường có plugin hoặc component để tự tạo google sitemap tự cập nhật cho website như xmap của joomla và google sitemap generator của wordpress…

6/ Cài đặt Google Analytics:

Cài đặt Google Analytics lên site của bạn và bạn nhớ là xác nhận lại thông tin của GA cho phù hợp với site của bạn.

7/ Tạo 1 số quảng cáo của Google:

Tạo tài khoản Google Adwords và add 1 số quảng cáo vào site của bạn. Bạn cứ add thậm chí chỉ là domain hay tên công ty thôi, không cần quan tâm nhiều đến keyword. Bởi vì khi add thì chắc chắn google sẽ phải ghé thăm site của bạn. Chỉ cần tốn 1 ít tiền thì site của bạn đã có rất nhiều lợi ích.

Với việc bạn làm theo các bước này bạn sẽ thấy rằng site của bạn sẽ rất nhanh chóng được phổ biến rộng rải. Mình không chắc chắn trong 24h bạn sẽ thành công, nhưng điều đó là có thể. Cách làm này chắc chắn sẽ rút ngắn thời gian index site từ vài tuần xuống chỉ còn vài ngày

Theo VietSEO.net

Tạo trang tin tức 30′ với wordpress

Để tạo trang tin tức động đẹp, nhiều widget hỗ trợ, dể dàng sử dụng với chi phí thấp và thời gian nhanh, bạn không nên bỏ qua

colorMag

Nhiệm vụ còn lại của bạn là upload resource, makup layout, chia category, viết bài, phân loại bài viết. 🙂

Tạo website cá nhân chỉ tốn tiền domain

Tạo 1 blog hoặc website cá nhân với chi phí rẻ, chỉ tốn duy nhất tiền domain (free nếu dùng subdomain). Tại sao bạn không thử!

  • Việc đầu tiên bạn làm là chọn cho mình 1 domain ưng ý. Bạn có thể mua tại godaddy với giá 184k/1 năm với domain .com. Hoặc bạn có thể dùng subdomain ở các trang web cung cấp free.
  • Vào hostinger đăng ký 1 hosting free ứng với domain bạn đã mua.
  • Download wordpress framework tại wordpress và upload lên hostinger.
  • Cài đặt wordpress với mySQL miễn phí trên hostinger.
  • Chọn theme, config giao diện.

Thế là xong, bạn có ngay 1 website với domain .com của riêng bạn. Bạn có thể viết bài, đăng bài, toàn quyền bằng quyền Administrator.