问题
My ionic2 app is taking like 15 seconds to start in a device. I tried all the recommendation (minify, uglify, enableProd, --prod --release, etc) My final apk is 4.3MB
The app doesn't have any image except from the icon and from the splashcreen, It has more less 20 screens, but just text and list and buttons (it's a payment app so nothing weird)
My package.json is:
{
"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"
}
Do you see any issue with the dependencies or with the plugins?
The minimized main.js file is 5.8MB.
My app.module is:
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 {}
And my 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);
}
}
Any suggestion? do you need more information? It's my first app in Ionic2 and taking 15 seconds to load is not acceptable. Please help to find a solution, I invest a lot of time in this app.
EDIT: package.json updated:
"@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"
回答1:
Try crosswalk or crosswalk lite and see how the performance is.The APK size will increase by 15-30 MB depending on the crosswalk you're using,but you can expect a uniform performance throughout different devices.
回答2:
Try to update your app... 2.0.0-rc.4
use a really out of date version of Ionic and Angular.
You can find more info here: changelog Ionic2
I'm working on a big app with a lot of plugins and images, and with ionic run android --prod
, app is taking like 3-4 seconds to start in a real device (Galaxy S4 - relatively old).
Is a tedious job, but sooner or later you will have to do it... A lot of new features have been added too!
That's my package.json, to give you an idea:
"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"
}
Best solution maybe will be starting a new project and add your plugin/src code. With Ionic 2 v3.0.1 (2017-04-06) app starts is really fast in production mode.
I hope to have been a help to you. :)
回答3:
use lazy loading of pages instead of declaring all pages in the app.module.ts.
In app.component.ts declare the root page as string instead of any rootPage: String = HomePage
.
Also while declaring the pages for navigation just declare as this.navigation.push("secondPage").
we don't need to import the page for navigation purposes..
回答4:
Check to see if Firebase is causing the slow loading. Some users (myself included) are currently experiencing a similar issue. Here is a discussion with some tips: https://forum.ionicframework.com/t/ionic-3-super-slow-with-firebase-on-device-emulator/87233/50
回答5:
consider minifying your code using js minifier of your choice, I prefer uglify
and use it via gulp
task runner
first install gulp-cli
via npm
globally, and then install gulp in the dev folder and then all needed gulp plugins(gulp-useref
, gulp-uglify
, gulp-if
), then in the index.html file surround all js references by comments that will be used by useref
to combine all js files in one file and replace their references by one reference
<!--build:js build/all.js -->
<script src="build/vendor.js"></script>
<script src="build/main.js"></script>
<!-- endbuild -->
then create a gulpfile.js
in the development folder
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'));
});
then open cmd in the dev folder and run gulp build
the js files will be combined and minified and the reference in the index.html will be updated accordingly
you can also use use del
plugin to delete unnecessary files
Edit
passing the --prod
flag to the build command makes use of Ahead-of-Time compilation that uglifies the js files prior to building the package
来源:https://stackoverflow.com/questions/43383035/ionic2-performance-issue