Angular Js的性能和加载时间

时间:2016-10-29 07:45:14

标签: javascript angularjs performance angularjs-directive performance-testing

我正在使用Laravel 5.2作为API处理Angular Js Web应用程序,我在性能方面遇到了很大的问题,特别是在主页的加载时间内。

我有一个请求,从数据库中获取5个部分,每个部分有一个或两个项目,每个项目都有很多注释。我遍历各个部分然后是项目,然后通过嵌套的ng-repeat指令进行注释。

我还有一个过滤器列表,其他朋友都有自己的请求,ng-repeat也可以呈现它。

这相当于使用Angular JS的大量数据,我如何才能提升它的性能?

我在主模块的依赖项中也有大约20个模块,是否有更好的方法只在我需要时才加载这个模块?

注意:

  1. Angular Js版本1.5.1
  2. 通过CDN加载Angular Js和jQuery
  3. 所有其他js文件由GULP.js连接在一个文件中,大约66000行代码
  4. 主模块的依赖项数组中有25个模块
  5. 负载时间约为25-35秒
  6. 这是导致问题的我的主页部分的代码:

            <div ng-class="{'col-sm-6':currentUser,'col-sm-9':!currenUser}" fc-loading="getCoupons" class="allCoupons lbm">
                <section class="fc-section text-center fc-direction" ng-init='current="all"'>
                    <button type="button" class='btn  btnp btnm0 srm' ng-class='{"btnr":current=="all"}' ng-click='updateCoupons();current="all"' name="button">كل الكوبونات</button>
                    <button type="button" class='btn btnp  btnm0' ng-class='{"btnr":current=="my"}' ng-click='updateCoupons("user");current="my"' name="button">الكوبونات المخصصة لك </button>
                </section>
    
                    <div  ng-repeat='(key,section) in coupon_sections' class="{{key}} fc-programs">
                        <div class="header">
                            <div class="clearfix">
                                <h3 class="pull-left">{{::section.type}}</h3>
                                <ul ng-init="active = 'newset'" class="pull-right">
                                    <li ng-click="sortCoupons(1,key); active='newset'" ng-class="{active:active == 'newset'}"><span>{{::'sort_by.newest'| translate}}</span></li>
                                    <li ng-click="sortCoupons(2,key); active='oldset'" ng-class="{active:active == 'oldset'}"><span>{{::'sort_by.oldest'| translate}}</span></li>
                                    <li ng-click="sortCoupons(3,key); active='popular'" ng-class="{active:active == 'popular'}"><span>{{::'sort_by.popular'| translate}} </span></li>
                                </ul>
                            </div>
                        </div>
                        <div class="fc-section">
                          <p>
                            {{::section.description}}
                          </p>
    
                        </div>
                        <div class="lucky_hour centerContainer" ng-if='key =="luckyHour"' ng-init='getTimeRemaining("December 31 2016 23:59:59 GMT+0200")'>
                          <div class="centerContent">
                            <ul>
                              <li class="hh" ng-repeat='hour in hours track by $index'>{{hour}}</li>
                              <li class="dots">:</li>
                              <li class="mm" ng-repeat="minute in minutes track by $index">{{minute}}</li>
                              <li class="dots">:</li>
                              <li class="ss" ng-repeat="second in seconds track by $index">{{second}}</li>
                            </ul>
                          </div>
                        </div>
                        <section class="fc-section text-center" ng-if="!section.coupons.length ">
                            <p class="title">{{::'no_coupons'| translate}}</p>
                        </section>
                        <div ng-repeat="coupon in section.coupons">
                            <fc-coupon ng-init='showCarousel();'></fc-coupon>
                        </div>
                        <div class="text-center" ng-if="section.coupons.length ">
                            <button  class="btnloadmore icon-plus-circled btni lbm" ng-click="loadMore(key)">{{::'load_more'| translate}}</button>
                        </div>
    
    
                    </div>
    
    
            </div>

    这是fc-coupon模板

    <div class="fc-coupon lbm" id='{{coupon.coupon_data.slug}}'>
    
        <div class="header bb">
          <div class="rippon">
    {{::coupon.coupon_data.type}}      </div>
            <img  style="background-image: url('{{::absolute_url+'images/brands/100x100/'+ coupon.brand_data.logo }}')" />
    
            <h3>{{::coupon.brand_data.name}}</h3>
            <fc-stars   rating="{{::coupon.coupon_data.rate}}" ></fc-stars>
            <div class="pull-right">
                <!-- <label>{{::'available_for'| translate}}</label> -->
                <div class="fc-badge sPadges" ng-repeat="customer in ::coupon.coupon_data.users_type">
                    <img uib-tooltip="{{:: 'available_for' | translate}} {{::customer.name.name}}" ng-src="{{::absolute_url}}/images/customer-types/50x50/{{customer.image}}">
                </div>
    
    
            </div>
    
        </div>
        <div class="sp" ng-if='key !="challenges"'>
          <h4>{{::coupon.coupon_data.title}}</h4>
          <p hm-read-more
             hm-text="{{:: coupon.coupon_data.description }}"
             hm-limit="100"
             hm-more-text="{{::'read_more'|translate}}"
             hm-less-text="{{::'read_less'|translate}}"
             hm-dots-class="dots"
             hm-link-class="links" class="sbm mtp "></p>
        </div>
        <div class="sp mtp" ng-if='key =="challenges"'>
          <p>
            <i class="fc-red icon-award"></i> <span class="fc-purple srm">التحدي </span>
            {{::coupon.coupon_data.challenges.name}}
          </p>
          <p>
            <i class="fc-red icon-gift"></i> <span class="fc-purple srm">الجائزة </span>
              <span>{{::coupon.coupon_data.type}}</span>
          </p>
    
        </div>
        <div class="couponImage">
            <div class="fc-overlay centerContainer">
                <div class="centerContent">
                    <i ng-if="coupon.coupon_data.in_wallet" class="icon-heart"></i>
                    <i ng-if="!coupon.coupon_data.in_wallet" ng-click="addToMyCoupons(coupon.coupon_data)" class="icon-heart-empty"></i>
    
                    <label>{{::coupon.coupon_data.no_of_users_in_wallet }}</label>
    
                </div>
                <div class="couponFooter">
                    <a href="{{::absolute_url}}/{{lang}}/coupon/{{coupon.slug}}">{{::'details'| translate}}</a>
                    <ul class="socials">
                        <li><span ng-click="shareCoupon(coupon.coupon_data.slug,'facebook')" spantarget="_blank" class="icon-facebook"></span> </li>
                        <li><span ng-click="shareCoupon(coupon.coupon_data.slug,'twitter')" class="icon-twitter"></span> </li>
                        <li><span ng-click="shareCoupon(coupon.coupon_data.slug,'gplus')" class="icon-gplus"></span> </li>
                    </ul>
                </div>
            </div>
            <img ng-src="{{::absolute_url}}/images/coupons/747x390/{{coupon.coupon_data.image}}"/>
        </div>
        <div class="couponDetails sp">
    
            <div class="owl-carousel mbm">
                <div class="item " ng-repeat="friend in ::coupon.coupon_data.coupon_users">
                    <div style="background-image: url('{{::absolute_url}}/images/users/75x75/{{friend.picture}}')" class="roundImages mProfilePics"></div>
                </div>
    
    
            </div>
            <div   ng-init="coupon.coupon_data.isMapCollapsed =true;coupon.coupon_data.isMapOpened=false">
            <div class="clearfix  bb mbp mtp bt sbm" >
                <div class="pull-left srm"   ng-click="openBranches(coupon.coupon_data)">
                    <i class="icon-location"></i>
                    <label>{{::'branches'| translate}} {{::coupon.coupon_data.no_of_branches}}</label>
                </div>
    
                <div class="pull-left">
                    <i ng-class="{'icon-cancel':coupon.coupon_data.feed_w_estafeed_id ==null,'icon-ok':coupon.coupon_data.feed_w_estafeed_id != null}"></i>
                    <label>{{::'benefit'| translate}}</label>
                </div>
                <div class="pull-right">
                  <i class="icon-share"></i>
    
                  <label for="">{{::'share'| translate}} :</label>
                    <i class="icon-facebook" ng-click='shareCoupon(coupon.coupon_data.slug,"facebook")'></i>
                    <i class="icon-twitter" ng-click='shareCoupon(coupon.coupon_data.slug,"twitter")'></i>
                </div>
            </div>
                <div class="fc-map " uib-collapse="coupon.coupon_data.isMapCollapsed" >
    
                </div>
            </div>
            <div class="clearfix">
    
              <div class="buttons add_to_my_coupones pull-right">
                  <button ng-if="coupon.coupon_data.in_wallet  " type="button" class="btn btnr btnp btni" ng-click='couponConditions(coupon.coupon_data.slug)'>{{::'in_my_coupons'| translate}}</button>
                  <a ng-if="!coupon.coupon_data.in_wallet && key=='challenges' " href='{{absolute_url}}/{{lang}}/coupons/{{coupon.coupon_data.slug}}/{{coupon.coupon_data.challenges.title}}'  class="btn btnr btnp btni" >ابدء التحدي</a>
                  <button ng-if="!coupon.coupon_data.in_wallet && key!='challenges'" analytics-on="click" analytics-event="addToMyCoupons" analytics-properties="{coupon_id:{{coupon.coupon_data.coupon_id}}}" ng-click="addToMyCoupons(coupon.coupon_data)" class="btn btnr btnp btni icon-heart">{{::'add_to_my_coupones'| translate}}</button>
              </div>
              <div class="pull-left">
                <i class="icon-calendar"></i>
                <label class="srm">{{::'available_to' | translate}}</label>
                <!-- <fc-countdown date='coupon.coupon_data.available_to.date'></fc-countdown> -->
    
              </div>
            </div>
    
            <div class="fc-couponComments" >
                <!-- <span>{{coupon.comments.length}} {{::'comments'|translate}}</span> -->
                <button  ng-init="isCollapsed = true;" ng-click="isCollapsed = !isCollapsed;"><i class="icon-comment-1"></i> </button>
                <ul uib-collapse="isCollapsed" >
                    <li>
                        <img src="{{ currentUser?absolute_url+'/images/users/50x50/'+currentUser.picture:absolute_url+'/images/user.png'}}"/>
                        <div class="userComment">
                            <textarea ng-model="addComment.newComment" ng-enter="sendComment(coupon)"></textarea>
                        </div>
                    </li>
                    <li ng-repeat="comment in coupon.coupon_data.comments track by $index">
                        <img ng-src="{{::absolute_url}}/images/users/50x50/{{::comment.user.picture}}"/>
                        <p>
                            <label>{{::comment.user.firstname}} {{::comment.user.lastname}}</label>
                            <span> {{::comment.comment}} </span>
                            <label>{{::comment.created_at}}</label>
                        </p>
                    </li>
    
                </ul>
            </div>
        </div>
    
    </div>

    家庭控制器js:

    var url = user ? "user/home/coupons" : "home/coupons";
    
    fcDB.query(url, "GET", data).success(function(res) {
        console.log('home', res);
        $scope.coupon_sections = res;
    });

1 个答案:

答案 0 :(得分:1)

你似乎有太多的绑定。回到Angular 1.2的时代,我记得在页面上最多有2000个绑定是一个经验法则。现在已经上升了,但我怀疑它是成倍增长的。

你有5个部分,每个部分都有大量的ng-click绑定,几个嵌套的ng-repeats,它们会加倍,然后每张优惠券的评论数量不确定。

您可以通过几种不同的方式处理所有这些问题。其中一些:

  • 加入点击监听器,
  • 延迟加载嵌套的注释,小时等,如果可能的话,
  • 也渲染为html那些社交分享,
  • 预翻译内容,
  • 一次性绑定比现在更多,
  • 减少依赖关系。

E.g。你可以有一个顶级ng-click而不是每个部分十几个(在那些fc-coupon重复中可能更多)。因此,创建一个顶级ng-click,并使该功能找到其预期目标并采取相应措施。我会说你可以节省一点时间,但那里并不重要。

延迟加载嵌套重复 - 即。不要立即渲染它们。在最初呈现这些部分时,您会继续渲染hoursminutesseconds。不知道为什么,但看起来你真的做了很多。在呈现主要内容之前,那些甚至不显示。只有一种方法是用ng-if开关隐藏整个块,当你知道你已经加载并渲染了最初的5个部分时,翻转一个(或所有)开关并等待那些也被渲染。你甚至可以隐藏那些(“加载评论......”)直到你知道它们是用单个css翻转渲染的。此外,也许你可以一次一个地做。首先完全解析顶部,然后是第二部分,然后是第三部分等。

请记住,很多表现都是感知效果

我看到你有许多绑定到函数的社交共享。为什么不直接将它们渲染为简单的HTML?根据这些优惠券,您可以再次删除大量绑定。

我看到你使用ng-translate - 它引入了更多的绑定。如果您事先知道用户的语言(即设置),也许您可​​以预先翻译每种语言的模板?例如。如果用户最初选择english,则会加载名为home-en.htmlfc-coupon-en.html的页面,而不是一个通用页面。不知道这是否可行,但考虑到你有很多嵌套内容,它可能会有用。你甚至不需要手工完成它,我打赌你可以编写一个一次性的脚本来编写这样的源模板,并且额外的构建步骤将在构建时生成所有这些的每个语言模板

还尝试一次性绑定嵌套内容。例如。 ng-repeat="hour in ::hours"可能会有所帮助。根据您必须绑定小时,分钟和秒的次数,可能会有数千个绑定要引入页面。

如果可以,减少依赖关系。例如。我看到你使用“read-more”模块。也许你可以没有它。只需使用css elipsis。并有一个第二次单击侦听器,可以找到目标部分并按需扩展/折叠。我打赌这就是原始模块无论如何都会做的,但你的是一次性的顶级点击监听器,而不是必须整理的每项角度绑定。

现在,这些都是猜测,因为你没有显示有多少实际项目以及它究竟做了什么。因此,请选择其中一个建议,然后尝试或打开一个新问题,并提供更多详细信息。

就个人而言,我认为懒惰加载一切都会给你最“感知”的表现。