【问题标题】:Ionic2 performance issueIonic2 性能问题
【发布时间】:2017-10-29 19:10:22
【问题描述】:

我的 ionic2 应用需要大约 15 秒才能在设备中启动。我尝试了所有建议(minify、uglify、enableProd、--prod --release 等) 我的最终 apk 是 4.3MB

该应用程序除了图标和启动画面外没有任何图像,它有更少的 20 个屏幕,但只有文本、列表和按钮(这是一个支付应用程序,所以没什么奇怪的)

我的 package.json 是:

{
  "name": "xxxxx",
  "author": "xxxx",
  "homepage": "http://ionicframework.com/",
  "private": true,
  "scripts": {
    "ionic:build": "ionic-app-scripts build",
    "ionic:serve": "ionic-app-scripts serve"
  },
  "dependencies": {
    "@angular/common": "2.2.1",
    "@angular/compiler": "2.2.1",
    "@angular/compiler-cli": "2.2.1",
    "@angular/core": "2.2.1",
    "@angular/forms": "2.2.1",
    "@angular/http": "2.2.1",
    "@angular/platform-browser": "2.2.1",
    "@angular/platform-browser-dynamic": "2.2.1",
    "@angular/platform-server": "2.2.1",
    "@ionic/cloud-angular": "^0.8.0",
    "@ionic/storage": "1.1.6",
    "@ngtools/webpack": "1.1.9",
    "angularfire2": "^2.0.0-beta.6",
    "firebase": "^3.6.4",
    "ionic-angular": "2.0.0-rc.4",
    "ionic-native": "2.2.11",
    "ionicons": "3.0.0",
    "rxjs": "5.0.0-beta.12",
    "zone.js": "0.6.26"
  },
  "devDependencies": {
    "@ionic/app-scripts": "^1.1.0",
    "@ngtools/webpack": "^1.1.9",
    "@types/request": "0.0.30",
    "ionic-minify": "^2.0.10",
    "typescript": "2.0.9"
  },
  "cordovaPlugins": [
    "cordova-plugin-whitelist",
    "cordova-plugin-statusbar",
    "cordova-plugin-splashscreen",
    "cordova-plugin-device",
    "ionic-plugin-keyboard",
    "phonegap-plugin-push"
  ],
  "cordovaPlatforms": [],
  "description": "xxxxx: An Ionic project"
}

您是否发现依赖项或插件有任何问题?

最小化的 main.js 文件为 5.8MB。

我的 app.module 是:

import { NgModule, ErrorHandler } from '@angular/core';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';
import { NextPayments } from './payment/nextPayments/nextPayments';
import { Login } from './user/login/login';
import { SignUp } from './user/signup/signup';
import { Terms } from './user/terms/terms';
import { Contactus } from './user/contactus/contactus';
import { ChangeEmail } from './user/changeEmail/changeEmail';
import { ChangePassword } from './user/changePassword/changePassword';
import { ResetPassword } from './user/resetPassword/resetPassword';
import { PaymentInformation } from     './payment/paymentInformation/paymentInformation';
import { UnidadesList } from './payment/unidadesList/unidadesList';
import { UnidadInformation } from     './payment/unidadInformation/unidadInformation';
import { PaymentConfirmation } from './payment/paymentConfirmation/paymentConfirmation';
import { PaymentHistory } from './payment/paymentHistory/paymentHistory';
import { OneClickPayment } from './payment/oneClickPayment/oneClickPayment';
import { HistoryInformation } from './payment/historyInformation/historyInformation';
import { AddPayment } from './payment/addPayment/addPayment';
import { AccountList } from './account/accountList/accountList';
import { AddAccount } from './account/addAccount/addAccount';
import { AccountInformation } from './account/accountInformation/accountInformation';
import { EqualValidator } from './directives/equalValidator';
import { AngularFireModule } from 'angularfire2';
import { CloudSettings, CloudModule } from '@ionic/cloud-angular';

export const firebaseConfig = {
    apiKey: "xxxxxx",
    authDomain: "xxxxxxxx",
    databaseURL: "xxxxxxxxxx",
    storageBucket: "xxxxxxxx",
    messagingSenderId: "xxx"
}

const cloudSettings: CloudSettings = {
  'core': {
    'app_id': 'xxxxx'
  },
  'push': {
    'sender_id': 'xxxxx',
    'pluginConfig': {
      'ios': {
        'badge': true,
        'sound': true
      },
      'android': {
        'iconColor': '#921F67'
      }
    }
  }
};

@NgModule({
  declarations: [
    MyApp,
    NextPayments,
    PaymentInformation,
    Login,
    PaymentConfirmation,
    AddPayment,
    EqualValidator,
    AccountList,
    AddAccount,
    HistoryInformation,
    Terms,
    Contactus,
    PaymentHistory,
    AccountInformation,
    UnidadInformation,
    UnidadesList,
    SignUp,
    ResetPassword,
    OneClickPayment,
    ChangeEmail,
    ChangePassword
  ],
  imports: [
    IonicModule.forRoot(MyApp, {
      monthNames: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre' ],
      monthShortNames: ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic' ],
      dayNames: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',     'Viernes', 'Sabado' ],
      dayShortNames: ['Dom', 'Lun', 'Mar', 'Mie', 'Jue', 'Vie', 'Sab' ],
    }),
    AngularFireModule.initializeApp(firebaseConfig),
    CloudModule.forRoot(cloudSettings)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    NextPayments,
    PaymentInformation,
    Login,
    UnidadInformation,
    UnidadesList,
    PaymentConfirmation,
    AddPayment,
    Terms,
    Contactus,
    AccountList,
    AddAccount,
    AccountInformation,
    HistoryInformation,
    PaymentHistory,
    OneClickPayment,
    SignUp,
    ResetPassword,
    ChangeEmail,
    ChangePassword
  ],
  providers: [{provide: ErrorHandler, useClass: IonicErrorHandler}]
})
export class AppModule {}

还有我的 app.components:

import { Component, ViewChild } from '@angular/core';
import { Nav, Platform, AlertController, IonicApp, ToastController,     MenuController } from 'ionic-angular';
import { StatusBar, Splashscreen } from 'ionic-native';

import { NextPayments } from './payment/nextPayments/nextPayments';
import { UnidadesList } from './payment/unidadesList/unidadesList';
import { PaymentHistory } from './payment/paymentHistory/paymentHistory';
import { PaymentInformation } from './payment/paymentInformation/paymentInformation';
import { Login } from './user/login/login';
import { ChangeEmail } from './user/changeEmail/changeEmail';
import { OneClickPayment } from './payment/oneClickPayment/oneClickPayment';
import { ChangePassword } from './user/changePassword/changePassword';
import { Contactus } from './user/contactus/contactus';
import { Terms } from './user/terms/terms';
import { Response } from './models/response';
import { Payment } from './models/payment';
import { Session } from './session/session';
import { Push, PushToken } from '@ionic/cloud-angular';
import { AccountList } from './account/accountList/accountList';
import { UserService } from '../app/user/userService';
import { ServerService } from './server/server.service';
import { LoadingController } from 'ionic-angular';
import { AccountService } from './account/accountService';
import { PaymentService } from './payment/paymentService';

declare var navigator: any;

@Component({
  templateUrl: 'app.html',
  providers: [Session, UserService, ServerService, PaymentService, AccountService]
})
export class MyApp {
  @ViewChild(Nav) nav: Nav;
  payment : Payment = new Payment();
  rootPage: any = Login;
  backButtonPressed: boolean = false;
  pages: Array<{title: string, component: any}>;

  constructor(public loadingCtrl : LoadingController, public paymentService     : PaymentService, public accountService : AccountService, public menuCtrl: MenuController, public toastCtrl: ToastController, private ionicApp : IonicApp, public platform: Platform, public serverService: ServerService, public session: Session, public push: Push, public userService: UserService, public alertCtrl: AlertController) {
    this.initializeApp();
    if(this.session.isAuth())
      this.rootPage = NextPayments;
    // used for an example of ngFor and navigation
    this.pages = [
      { title: 'Próximos Pagos', component: NextPayments },
      { title: 'Mis Unidades', component: UnidadesList },
      { title: 'Mis C.B.U.', component: AccountList },
      { title: 'Historial de Pagos', component: PaymentHistory },
      { title: 'Cambiar Email', component: ChangeEmail },
  { title: 'Cambiar Contraseña', component: ChangePassword },
  { title: 'Términos y Condiciones', component: Terms },
  { title: 'Contáctenos', component: Contactus },
  // { title: 'Configuración', component: Settings }
];

this.push.rx.notification()
    .subscribe((msg) => {
      let loader = this.loadingCtrl.create({
        content: "Obteniendo información..."
      });
      loader.present();
      if(msg.payload != undefined && msg.payload != null){
        let payload : any = msg.payload;
        if(payload.id != ""){

              this.paymentService.getPayments(payload.id).then((result : Response) => {
                if(result.success){
                  if(result.eror!= null && result.eror == "id invalido"){
                    this.session.clearSession();
                    this.nav.setRoot(Login);
                  }
                  else{
                    if(result.data!= null && result.data.expensas.length > 0){
                        this.payment = result.data.expensas[0];
                        this.payment.date = this.payment.diahabil;
                        if(this.payment.diahabil > this.payment.date1 && this.payment.date2.toString() != "0000-00-00")
                          this.payment.suggested = this.payment.importe2;
                        else
                          this.payment.suggested = this.payment.importe1;
                        this.accountService.getAccounts().then((result : Response) => {
                          if(result.success){
                            if(result.data.accounts != null && result.data.accounts.length > 0){
                              loader.dismiss();
                              this.payment.account = result.data.accounts[0];
                              this.nav.setRoot(OneClickPayment, {
                                item : this.payment
                              });
                            }
                            else{
                              loader.dismiss();
                              this.payment.account = result.data.accounts[0];
                              this.nav.setRoot(PaymentInformation, {
                                item : this.payment
                              });
                            }
                          }
                        });
                    }
                  }
                }
              });
        }
      }
      loader.dismiss();
      this.nav.setRoot(NextPayments);
        });
  }

  readPushNotification(){
      this.push.register().then((t: PushToken) => {
        return this.push.saveToken(t);
      }).then((t: PushToken) => {
        this.session.setPnToken(t.token);
      });
  }

  registerBackButtonAction() {
    this.platform.registerBackButtonAction(() => {
      let activePortal = this.ionicApp._modalPortal.getActive();
      if (activePortal) {
        activePortal.dismiss().catch(() => {});
    activePortal.onDidDismiss(() => {});
    return;
  }
  if(this.menuCtrl.isOpen()){
    this.menuCtrl.close();
  }
  else{
    let view = this.nav.getActive();
    if(view.component.name == "NextPayments" || view.component.name == "Login")
      this.showExit();
    else
          return view._nav.canGoBack() ? view._nav.pop() :         this.goBacktoDefaultPage();
        }
    }, 1);
  }

    goBacktoDefaultPage(){
      if(this.session.isAuth())
        this.nav.setRoot(NextPayments);
    }
   showExit() {
     if (this.backButtonPressed) {
       this.platform.exitApp();
     } else {
       this.toastCtrl.create({
         message: 'Presione nuevamente para cerrar la aplicación.',
         duration: 2000,
         position: 'top'
       }).present();
       this.backButtonPressed = true;
       setTimeout(() => this.backButtonPressed = false, 2000);
     }
   }

  initializeApp() {
      this.platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      StatusBar.styleDefault();
      Splashscreen.hide();
      this.registerBackButtonAction();
      this.readPushNotification();
    });
    if(navigator['connection']['type'] == "none"){
        let alert = this.alertCtrl.create({
          subTitle: "No posee conexion a internet. La aplicación se cerrara. Por favor reintente cuando posea conectividad.",
      buttons: [
        {
        text: 'Aceptar',
        handler: () => {
          this.platform.exitApp();
        }
      }
      ]
    });
        alert.present();
    }
  }

  openPage(page : any) {
    // Reset the content nav to have just this page
    // we wouldn't want the back button to show in this scenario
    this.nav.setRoot(page.component);
  }

  logout(){
    this.session.clearSession();
    this.userService.setToken(null);
    //UNREGISTER PUSH NOTIFICATION TOKEN
    this.push.unregister();

    this.nav.setRoot(Login);
  }
}

有什么建议吗?你需要更多信息?这是我在 Ionic2 中的第一个应用程序,加载 15 秒是不可接受的。请帮助找到解决方案,我在这个应用程序上投入了大量时间。


编辑:package.json 更新:

"@angular/animations": "^4.0.0",
"@angular/common": "4.0.0",
"@angular/compiler": "4.0.0",
"@angular/compiler-cli": "4.0.0",
"@angular/core": "4.0.0",
"@angular/forms": "4.0.0",
"@angular/http": "4.0.0",
"@angular/platform-browser": "4.0.0",
"@angular/platform-browser-dynamic": "4.0.0",
"@angular/platform-server": "4.0.0",
"@ionic-native/core": "3.4.2",
"@ionic-native/push": "^3.4.4",
"@ionic-native/splash-screen": "3.4.2",
"@ionic-native/status-bar": "3.4.2",
"@ionic/cloud-angular": "^0.12.0",
"@ionic/storage": "2.0.1",
"@ngtools/webpack": "1.3.0",
"angularfire2": "^2.0.0-beta.8",
"firebase": "3.7.8",
"ionic-angular": "3.0.1",
"ionicons": "3.0.0",
"rxjs": "5.1.1",
"sw-toolbox": "3.4.0",
"zone.js": "^0.8.4"

【问题讨论】:

  • 我也面临同样的问题。等待 ionic 团队发布更新的优化版本。他们正在努力。
  • 您有更多信息的链接吗?无论如何,有几页有建议(这对我不起作用)但可能是 ionic 2.2.1 的问题?你试过低版本吗?

标签: android performance ionic-framework ionic2


【解决方案1】:

尝试使用 crosswalk 或 crosswalk lite 看看性能如何。APK 大小将增加 15-30 MB,具体取决于您使用的人行横道,但您可以期望在不同设备上获得一致的性能。

【讨论】:

  • 但是我在不同设备上的性能没有问题,加载应用程序时性能总是很慢。然后一切正常。这对应用加载时间有帮助吗?
  • 我尝试过人行横道,但人行横道和铬启动时间之间没有太大区别。不过人行横道的动画效果更好。我正在使用的应用程序与您的应用程序和启动的配置文件相同时间约为 6-9 秒(APK-4.7MB)。我使用的是 Ionic 2.3 和 Ionic 本机 3.x,尽管在我更新到最新版本之前启动是相同的。
【解决方案2】:

尝试更新您的应用程序...2.0.0-rc.4 使用真正过时的 Ionic 和 Angular 版本。

您可以在这里找到更多信息:changelog Ionic2

我正在开发一个包含大量插件和图像的大型应用程序,使用ionic run android --prod,应用程序在真实设备(Galaxy S4 - 相对较旧)中启动需要大约 3-4 秒。

这是一项乏味的工作,但迟早你必须这样做......还添加了很多新功能!

这是我的 package.json,给你一个想法:

  "dependencies": {
    "@angular/animations": "4.0.1",
    "@angular/common": "4.0.1",
    "@angular/compiler": "4.0.1",
    "@angular/compiler-cli": "4.0.1",
    "@angular/core": "4.0.1",
    "@angular/forms": "4.0.1",
    "@angular/http": "4.0.1",
    "@angular/platform-browser": "4.0.1",
    "@angular/platform-browser-dynamic": "4.0.1",
    "@ionic-native/barcode-scanner": "3.4.4",
    "@ionic-native/camera": "3.4.4",
    "@ionic-native/core": "3.4.4",
    "@ionic-native/facebook": "3.4.4",
    "@ionic-native/google-plus": "3.4.4",
    "@ionic-native/network": "3.4.4",
    "@ionic-native/social-sharing": "3.4.4",
    "@ionic-native/splash-screen": "3.4.4",
    "@ionic-native/sqlite": "3.4.4",
    "@ionic-native/status-bar": "3.4.4",
    "ionic-angular": "3.0.0",
    "ionicons": "3.0.0",
    "jsbarcode": "3.5.9",
    "moment": "2.18.1",
    "rxjs": "5.3.0",
    "sw-toolbox": "3.6.0",
    "zone.js": "0.8.5"
  },
  "devDependencies": {
    "@ionic/app-scripts": "1.3.0",
    "typescript": "2.2.2"
  }

最好的解决方案可能是开始一个新项目并添加您的插件/源代码。 Ionic 2 v3.0.1 (2017-04-06) 应用在生产模式下启动速度非常快。

希望对你有所帮助。 :)

【讨论】:

  • 谢谢!我使用最新版本创建了一个新应用程序并迁移了所有逻辑,但我得到了相同的结果。请检查我的 app.components.ts 看看是否有什么奇怪的地方......请注意 initializeApp() 方法。可以在应用程序启动后立即注册推送通知吗?还有,把所有东西都放在app.module.ts中的declarations和entryComponents上也行吗?
  • 我注意到应用程序一启动就会调用api.ionic.io/insights.. 可以吗?我测试了一个空项目,它在 3/4 秒内加载,但我的不是那么复杂或大,所以它应该更不一样。有什么线索吗?
  • 也许可以尝试逐个删除一些功能并阻止它被初始化并检查启动时间是否减少..所以也许您可以找出哪些特定功能会增加启动时间然后我们可以尝试查找一个解法! initializeApp() 好像没问题,api.ionic.io/insights 是什么?
【解决方案3】:

使用延迟加载页面,而不是在 app.module.ts 中声明所有页面。 在 app.component.ts 中,将根页面声明为字符串,而不是任何 rootPage: String = HomePage。 此外,在声明导航页面时,只需声明为this.navigation.push("secondPage").,我们不需要为导航目的导入页面..

【讨论】:

    【解决方案4】:

    检查 Firebase 是否导致加载缓慢。 一些用户(包括我自己)目前遇到了类似的问题。 以下是一些提示的讨论: https://forum.ionicframework.com/t/ionic-3-super-slow-with-firebase-on-device-emulator/87233/50

    【讨论】:

      【解决方案5】:

      考虑使用您选择的 js 缩小器来缩小您的代码,我更喜欢 uglify 并通过 gulp 任务运行器使用它

      首先通过npm全局安装gulp-cli,然后在dev文件夹中安装gulp,然后安装所有需要的gulp插件(gulp-userefgulp-uglifygulp-if),然后在index.html文件中环绕cmets 的所有 js 引用,useref 将使用这些引用将所有 js 文件合并到一个文件中,并用一个引用替换它们的引用

      <!--build:js build/all.js -->
      
      <script src="build/vendor.js"></script>
      <script src="build/main.js"></script>
      
      <!-- endbuild -->
      

      然后在开发文件夹中创建gulpfile.js

      var gulp = require("gulp");
      var uglify = require("gulp-uglify");
      var useref = require("gulp-useref");
      var gulpIf = require("gulp-if");
      
      
      gulp.task('build', function () {
      
          gulp.src('www/index.html')
              .pipe(useref())
              .pipe(gulpIf('*.js', uglify()))
              .pipe(gulp.dest('www'));
      
      });
      

      然后在dev文件夹中打开cmd并运行gulp build js 文件将被合并和缩小,并且 index.html 中的引用将相应更新

      你也可以使用del插件删除不需要的文件

      编辑

      --prod 标志传递给构建命令会利用提前编译,在构建包之前对js文件进行丑化

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-11-15
        • 1970-01-01
        • 2017-04-13
        • 2022-01-04
        • 1970-01-01
        • 2010-09-05
        • 2012-09-25
        相关资源
        最近更新 更多