Cloudinary | S3 | File System file upload with Koa & Express & Angular & Progress bar

Introduction

Back in my early career, I have always stored all the files in the backend server and there was no progress indicator whatsoever or maybe I didn't have requirements that needed those but later on, I started utilizing the XMLHttp progress events and later migrated to Angular, React and Vue.

In this post, I will be writing how to upload files to Cloudinary, S3 bucket and file storage using Node js server and angular 8 application.

Since we are discussing 3 different channels to do this, I will not be writing about transformation but rather just focusing only on upload, I am very excited so let's get started.

At the end of this post, it should be very easy to -

  • Upload files to S3, FileSystem & Cloudinary server.
  • Get the transfer percentage of the upload in real-time

Although we can transfer files directly from the Client (Angular) to Cloudinary etc, for the sake of this post, we will be transferred to the node server and from there to those third-party media servers.

Freebie at the end of the post

Just, as usual, I have already prepared a little freebie at the end of the post, pointed to a repository with working sources and an example on how to upload to Cloudinary, S3 & File system using Nodejs & a sample angular project.

Installation & Configuration

First of all, before we continue, there are some of the libraries and dependencies to download in order to make our lives a little bit easier.

  • Install Cloudinary library npm install cloudinary --save
  • install AWS S3 library npm i aws-sdk --save

Configuring Cloudinary Server

In order to use Cloudinary server, you will need an account with the necessary token to connect and upload your files.

Create an account and get API details.

To connect to Cloudinary we will be needing only the cloud_name api_key api_secret

Configuring Amazon AWS and S3

Just like Cloudinary, you will need to create a bucket on Amazon S3 and create Access key security credentials.

To connect to S3 bucket we will need the secretAccessKey accessKeyId region and bucket.

By now we have already all we need to connect to those services

Create the configuration file

Putting all the configuration together, we will have a file like this


const config = {
    cloudinary: {
        cloud_name:'',
        api_key: '',
        api_secret: ''
    },
    aws: {
        config: {
            secretAccessKey: '',
            accessKeyId: '',
            region: ''
        },
        bucket: '',
        url: 'amazonaws.com'

    },
    fileSystem: {
        dir: 'public/images',
        url: 'https://127.0.0.1:5533'
    }
}

module.exports = config;

Connecting to cloudinary

Per Cloudinary NodeJs configuration, to establish a connection -

const cloudinary = require('cloudinary').v2

cloudindary.config(configuration.cloudinary)

Connecting to S3

To connect to Amazon S3

const aws = require('aws-sdk');
aws.config.update(configuration.aws.config);
const s3Instance = new aws.S3();

Uploading via S3

We are using NodeJs on Koa or Express, whatever you choose and sending our files via Angular 8

Blob file transfer on koa are available at ctx.request.body.file and can be converted to buffer and passed directly to S3 putObject method

Converting to buffer

fs.readFile(ctx.request.body.file.path, (error, buffer) =>{
    if(error){
        console.error(error)
        return
    }
    // buffer to send

})

You can also use the node fs.promises API introduced on version > 10

const objectParams = {
    Bucket: configuration.aws.bucket,
    KeyName: fileName,
    Body: buffer
}

s3Instance.putObject(objectParams).promise();

This is all that is required to upload using S3, few things to keep in mind though that ctx.request.body.file is for koa and express we will be using npm install --save multiparty for this post and code found below.

Uploading via Cloudinary

Although Cloudinary has a lot of transformation and good stuff within the SDK but for this post, we will only be focused on uploading files only and leave those for later posts.

cloudinary.uploader.upload(ctx.request.body.file.path, (error, res)=>{
    if(error){
        console.error(error);
    }
     // res - > cloudinary upload response
});

Response sample is available here and thats all that is required for simple upload on Cloudinary.

Uploading to file system

This is one of the easiest to do, you just have to copy the file from a temp directory to a directory of your choice dirOfChoice.

fs.rename(ctx.request.body.file.path,dirOfChoice),(error,res)=>{
    if(error){
        console.error(error);
        return;
    }

    //completed
})

Although there are few codes to run in order to make sure all works okay etc but this is just the basics of uploading directly to the server.

Request file on Koa & Express

On koa files are available on ctx.request.body.file using koa-parser middleware and express using multiparty with following code

const getFiles = (req) =>{
    return new Promise((resolve, reject) =>{
        new multiparty.Form().parse(req, async (error,fields, files)=> {
            if(files && files.file && files.file.length){
                resolve(files.file[0])
            }

            reject(error);

        })
    })

}

Front-end for the upload

We will be using a simple Angular 8 application to do the upload but i won't be writing the code here, but you could find the complete Front-end source here.

You can also accomplish the same with other libraries like Vue, React and Vanilla JS XMLHttp.

putting it all together, all the back-end source and working sample used for this post are available here.

Let's keep the post going. Let me know what you think in the comment box below and feel free to share and use the source for your projects.

HTML to PDF using Koa.js & Express.js with Sample Invoice

Getting Started

We all go through this especially when starting to build mid to large scale business application in the form of dynamic invoices or reports.

This can really be a challenging part especially when it comes to making decision on the right tools to use, fortunately enough, this post is about giving you all the details you would need to actually transform or build HTML template to PDF either with dynamic data from the data source of your choice or just static files with Koa.js or Express.js. I will be covering both frameworks on this post.

Freebie at the end of the post

If you stick around till the end of this post, I have compiled a full customizable invoice script for both Koajs and express, you can start using that right away on your project with just a few changes.

Package installations

Depending on whether you are using Koajs or Express, I got you covered here, after all, there are just a few changes between those.

You will need to install all there is in general installation and the next install for the framework you are using.

General installations

npm install html-pdf --save
npm install esm --save-dev

Koa Installations

npm install koa --save
npm install koa-router --save
npm install express --save

Express Installations

npm install express --save

At this point, you have finished installing all you need for a very simple PDF.

Testing installation

You now have all the packages to create a PDF with HTML strings

Koa Sample

const koa = require('koa');
const htmlPdf=require('html-pdf');
const Router=require('koa-router');
const router=new Router();

let app=new koa();
Const htmlString=`
<!doctype html>
<html>
   <head>
      <meta charset="utf-8">
   </head>
   <body>
      <h1>Hello PDF </h1>
   </body>
</html>
`;

router.get('/',async (ctx,next)=>{
htmlPdf.create(htmlString,{}).toFile(pathToStorePdf,(error,response)=>{
 if(error){
   console.log(error);
   return
  }
  console.log(response)
})
});

app.listen(4000,'127.0,0.1');

Express Sample

const express=require('express');
const app=express();
const htmlPdf=require('html-pdf');

const htmlString=`
<!doctype html>
<html>
   <head>
      <meta charset="utf-8">
   </head>
   <body>
      <h1>Hello PDF </h1>
   </body>
</html>
`;
app.get('/',(req,res)=>{
htmlPdf.create(htmlString,{}).toFile(pathToStorePdf,(error,response)=>{
 if(error){
   console.log(error);
   return
  }
  console.log(response)
})
});

app.listen(4000,'127.0.0.1')

If you are able to see a PDF file in the pathToStorePdf path specified, then your installation is now successful, and we will dive into parsing variables to the HTML files and other complicated parts you might come across in every PDF projects.

Dos and Don’ts

We will be using entirely HTML to create the new PDF layout but there are few things you might have to keep in mind when doing this -

  • If you would like to attach a media file, then make sure your file is hosted publicly and use a public link.
  • Make sure to select the paper type that matches your document and format your document to that, always develop with the right paper type.
  • Add a render delay in the option if you are running JavaScript in the HTML view, especially ones that take a bit amount of time to return response or process.
  • Use inbuilt header and footer if you plan to add a header to your document.

The first time I worked on PDF was using ASP.Net a few years ago, but the solution we had then was very limited, even a lot CSS2 syntax wasn’t working correctly, but it seems the html-pdf library has much better support although some CSS3 are not working as expected, but overall, you could create exactly anything you would imagine on PDF with that.

Parsing Variables to our PDF

You can concatenate any string to the HTML string and will output properly to our PDF, but I prefer mostly the multi-line quote with variable, makes it a lot easier to prevent syntax error, Here is the documentation on additional configuration files for this

One line string concatenation

const name='martin';
const htmlString = '<!doctype html>'+
'<html><head>'+
      '<meta charset="utf-8">'+
   '</head>'+
   '<body>'+
      '<h1>Hello '+name+' </h1>'+
   '</body>'+
'</html>';

Multi-line string concatenation

const name='martin';
const htmlString=`
<!doctype html>
<html>
   <head>
      <meta charset="utf-8">
   </head>
   <body>
      <h1>Hello ${martin}</h1>
   </body>
</html>
`;

Running JavaScript Libraries

CSS, Fonts and JavaScript can be loaded to the page either inline or via external public URL.

const htmlString=`
<!doctype html>
<html>
   <head>
      <meta charset="utf-8">
<link type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.css"/>
<link type="text/css" href="https://fonts.googleapis.com/css?family=Ubuntu:300,400,400i,500,700|Material+Icons" rel="stylesheet">

<style type="text/css">
   .h1{
     Color:red;
   }

</style>

   </head>
   <body>
      <h1 class='echo-class'> </h1>
<script
       src="https://code.jquery.com/jquery-3.4.1.min.js"
       type="text/javascript"
       crossorigin="anonymous"></script>

<script type='text/javascript'>
$(document).ready(function(){
   $('body .echo-class').html('hello pdf');
})

</script>
   </body>
</html>
`;

const options={
 "format": "Letter",  
  "orientation": "portrait",
  "header": {
    "height": "45mm",
    "contents": '<div style="text-align: center;">Invoice</div>'
  },
}

htmlPdf.create(htmlString,options).toFile(pathToStorePdf,(error,response)=>{
 if(error){
   console.log(error);
   return
  }
  console.log(response)
})

it is important to note that, processing assets files or running operations that take a lot of time on the JavaScript part to process needs a special option value, renderDelay in order to wait for this to complete before the PDF is bundled, this will go a long way in solving blank page.

Sometimes you might want to render chart via D3 or any other SVG lib out there, you also need to disable animation, having them turned on will most likely produce empty white pages too.

Putting it all together

Working with HTML to PDF is extremely easy when you understand what exactly to do, I would suggest you read up the documentation here and test as much as possible when building your HTML template, at least you would be able to catch something that isn’t working properly immediately.

I have compiled a business Invoice with both Koajs, Express with Dynamic and Static HTML on a repository, you can feel free to download, play with it and use that on your project.

If this post helped you, please consider sharing with your friends and let me know what you think in the comment below. Let's keep the conversation going

Cordova Custom Plugin Easy than expected with ionic wrapper

Cordova custom plugin easy than expected with Ionic wrapper

I shouldn’t have created this post, because there are similar posts out there but I feel they are not detailed enough or even hard to comprehend.

The purpose of the post is to explain in details how easy it can be to build a Cordova plugin.

Why should you create a custom plugin?

There are lots of reasons to go down this direction, one of the main reasons is to benefit from the native functionality and increase performance, and this is the reasons I do this sometimes.

This post is about giving a very detailed explanation on how to build a Cordova plugin directly with android studio and making your ionic wrapper around the plugin.

The source code used throughout this post is available at the end of the article.

Installing Android studio

Download android studio if you do not already have one, once the download is completed, open it up and follow all the prompt to create a new android app, depending on the plugin, you may like to create have a UI but at this point, for the purpose of simplicity, we will only be using android native toast and for that, we only need to use the no activity option.

But creating a new android project doesn't necessarily give us access to all the good stuff on Cordova API out there so for this case too, we will be adding an implementation org.apache.cordova to application gradle.

implementation group: 'org.apache.cordova', name: 'framework', version: '7.0.0

Depending on the version of Cordova you are building on, mine is 7.0.0.

Writing the plugin code Android

We are now ready to start typing the plugin code, create the entry class file for your plugin and extend it to CordovaPlugin and add the methods below inside the class file.

public class HelloWorld extends CordovaPlugin {
    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        return false;
    }
}

Extending to CordovaPlugin and execute method is the entry point from the JavaScript context and this is very important when building plugin.

At this point, due to the Cordova framework we added on gradle, we can safely org.apache.cordova without any errors thus


import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;

import org.json.JSONArray;
import org.json.JSONException;

public class HelloWorldPlugin extends CordovaPlugin {
    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        return false;
    }
}

After updating the final part of the plugin is as follows -

import android.widget.Toast;

import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;

import org.json.JSONArray;
import org.json.JSONException;

public class HelloWorldPlugin extends CordovaPlugin {
    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        if(action.equals("nativeToast")){
            nativeToast();;
        }
        return false;
    }

    public void nativeToast(){
        Toast.makeText(webView.getContext(), "Hello World Cordova Plugin", Toast.LENGTH_SHORT).show();
    }
}

The toast plugin is now completed, we now need to transform this to real Cordova plugin, this is also the process you can take when transforming another android library to plugin as well.

We will need to have few tools ready and installed before we continue. First of all, i assume you already have NodeJs installed.

Mac & Windows can download on NodeJs website, for linux, you can use nvm to install Node, having said that.
Let dive deep.

Prerequisite installation

  • Plugman Installation npm install -g plugman
  • Cordova Installation npm install -g cordova
  • Ionic Installation npm install -g ionic@latest

Creating your plugin

Navigate the the directory you would like the plugin created, open the terminal on that location and type the following command -

plugman create --plugin_id io.electrosoft.helloworld --plugin_version 0.0.1 --name HelloWorldPlugin

You might want to change plugin_id and name for your plugin.

This will generate all the necessary files for your plugin and you need to add the platform, i will be adding android however you can add iOS on your end as well if you have iOS native code already, be sure to navigate to the directory of the newly created plugin in-order to run the command below.

Adding Android

plugman platform add --platform_name android

Adding iOS

plugman platform add --platform_name ios

Adding package.json and plugin details

At this point, you have already added the platform you wish to build for, you will also need to add package.json file to the plugin directory and you can do this by running, this will prompt you to enter the details -

plugman createpackagejson ./

You now have a very basic plugin inside the plugin -> src, but you need to copy our code from the plugin from android studio and paste it into the android plugin class, you also might need to adjust the class files respectively to individual packages and class names.

If you encounter any error during this process, please make sure your class name and packages matches the plugin package correctly or change it.

Updating the JavaScript bridge

Inside the plugin directory -> www, you can find the JavaScript bridge for the plugin and we need to change the content of this file as well to make sure that our nativeToast part of the plugin is called

var exec = require('cordova/exec');

exports.nativeToast = function (arg0, success, error) {
    exec(success, error, 'HelloWorld', 'nativeToast', [arg0]);
};

Now we have everything ready to test our new plugin.

Installing your plugin

Now you have already completed your plugin, you can also checkout the complete code for our toast version at the end of this post -

Install your plugin using plugman

plugman install --platform android --project projectPlatformPath --plugin pluginPath

The plugin should be available on window.cordova.plugins.HelloWorld` assuming in our case, we would be calling the nativeToast `window.cordova.plugins.HelloWorld.nativeToast(args...)

Uninstalling your plugin

You can also uninstall the plugin from the project by using plugman and running the following command

plugman uninstall --platform android --project projectPlatformPath --plugin pluginPath

This is all there is to creating even a complex plugin. Although you do not need android studio to create those plugin but it makes the whole process very easy to especially when working with a lot of native codes and API.

You can skip all the other section of the plugin and checkout the source if you are not working on Ionic as the rest of the post will be explaining how to implement the ionic native wrapper for this plugin.

Building your plugin wrapper for Ionic

Developers documentation for creating the ionic wrapper is available here and this is exactly what we will be doing here.

First of all, we need to clone the repository or download it and install gulp CLI

git clone https://github.com/ionic-team/ionic-native
sudo npm install --global gulp-cli
npm install

After running all the above command.

Create the template file for the new plugin, in our case, i still proceed to use the name HelloWorld for the new plugin

gulp plugin:create -n HelloWorld

The plugin should now be available at src -> @ionic-native -> plugins -> hello-world and this is where we will type all the code necessary, i would suggest you review the developers documentation for more solid understanding.

Here is the final change for our nativeToast plugin


import { Injectable } from '@angular/core';
import { Plugin, Cordova, IonicNativePlugin } from '@ionic-native/core';
@Plugin({
  pluginName: 'HelloWorld',
  plugin: 'io.electrosoft.helloworld', // npm package name, example: cordova-plugin-camera
  pluginRef: 'cordova.plugins.HelloWorld', // the variable reference to call the plugin, example: navigator.geolocation
  repo: '', // the github repository URL for the plugin
  platforms: ['Android'] // Array of platforms supported, example: ['Android', 'iOS']
})
@Injectable()
export class HelloWorld extends IonicNativePlugin {

  @Cordova()
  nativeToast(arg1: string, arg2: number): Promise<any> {
    return; // We add return; here to avoid any IDE / Compiler errors
  }

}

After you might have finished your coding your plugin, run the code below in the root of ionic-native directory to generate the build folder

npm run build

Installing your plugin wrapper for ionic

The wrapper has already been completed and the native plugin too.

To install the native plugin

ionic cordova plugin add pathToNativePlugin

To add the wrapper simply go to the ionic-native directory -> dist ->@ionic-native ->plugins ->pluginName to your project node_modules -> @ionic-native

Test and Integrate

It is now time to check the fruit of our labour

Add the wrapper to root module provider with the necessary imports

import { HelloWorld } from '@ionic-native/hello-world/ngx';

@NgModule({
  imports: [
   ...
  ],
  providers:[HelloWorld]
})

In your component, you can call the plugin via the nativeToast method

import { HelloWorld } from '@ionic-native/hello-world/ngx';

declare var window:any;
.... 
constructor(private helloWorld:HelloWorld){}

public nativeToast(){
    this.helloWorld.nativeToast("").then(r=>{
        console.log('success');
    }).catch((e)=>{
        console.error(e);
    })
}

//without ionic wrapper -> plugin is available via window.cordova.plugins.PluginName
public withoutWrapper(){
    if(window.cordova && window.cordova.plugins && window.cordova.plugins.HelloWorld){
      window.cordova.plugins.HelloWorld.nativeToast();
    }
 }
...

Native toast come on to the screen anytime you execute this function.

Finally, you should be able to implement any native functionality you would like on ionic. You might also want to checkout the cordova plugin documentation and good luck.

Here are all the code used for this project. Feel free to copy and play around those files.

I'd love to hear what your thought are about this approach. If you like this article please consider sharing to your friends, you might be helping someone struggling with same

The Secret of faster Performance App on Ionic Cordova

The secret of faster performance App on Ionic Cordova

Based on my experience so far, there are few misconceptions which are true in certain cases but not necessarily true, however totally dependent on the situation and the person building the application.

Sometimes the idea of developing more performant apps only prevail for experienced ionic developers.

The purpose of this post is about trying to explain how to optimize your ionic application for maximum performance, and security by highlighting several processes that are extremely useful when optimizing a very resource-intensive application.

Introduction

Ionic is an HTML5 mobile application framework targeted at building mobile apps, and these are essentially small websites running in-browser shell in an app that has access to the native platform layer.

Why hybrid?

I ask myself that question a lot, and the reason is basically to be able to ship faster for all platform but that may not always the case if things take the wrong turn, especially developing mid to large scale application on Ionic, and as such a lot of things needs to be done in order to achieve smooth development and ship a decent application to the end-user.

Generally, Hybrid application has many benefits and a lot of downsides and most of the benefits are -

  • Cross-platform support (Write once and deploy anywhere)
  • Development Speed
  • Access to a lot of third party code and libraries.

But downside -

  • Security
  • Performance

Although the downside seems just a little but will cost you dearly if you do not take a lot of things into consideration when working on a hybrid app.

Analysis and Design for a Resource-Intensive Applications

Just like any other application, Analysis and designs are crucial before development, preparing UML, use cases and user stories, highlighting key part of the app that requires a lot of resources and moving them to native.

Although the process above sounds cumbersome but will remove a lot of issues and headaches in the long run.

Optimizing and Scaling Ionic Application

Just like analysis, scalability and test are also crucial to the performance of the application because oftentimes you only have one shot to impress the right audience, most of the users will never bother trying to checkout an application that was buggy on their first trial.

Here are some of the ways to get this done -

Moving resource-intensive portion to Native

One of the processes to scale a very large scale application is having the resources and understanding the part of the application to move to native and ones that need to stay completely on WebView.

Ideally, long-running time, resource-intensive and the need native hardware should be moved to native and others on WebView.

This can be creating a whole new Cordova plugin or using existing one or sometimes you might have to create a completely new activity on native and keep it below transparent WebView, there are lots of choices, but doing this the right way can help achieve massive performance boost on those parts comparable to native.

if you would like to build a complete custom plugin you can check out this article on a complete guide on how to do that.

Updating Application once

This technique comes in handy when working directly with API, some of the API data especially the huge ones are mostly static and unchanged during the lifecycle of the app, it is best to identify endpoint like this and call it only once since there is no reason to update it during the app run-time.

Those data needs to be fetched only once when the application starts and stored in-app memory for immediate access.

Unsubscribing all subscription

Observable is great tools to use when done the right way, but can also create memory leak and decreases the overall efficiency of the application.

It is recommended to unsubscribe any subscription as soon as it is completed and luckily you can use the Observable add method to teardown the observable.

const sub:Subscription = subscriptionMethod().add(()=>{
    sub.unsubscribe()
})

Making sure that whenever the observable is completed, it will be unsubscribed.

List & Performance

Just like packing a lot of items in a basket gets very heavy overtime and this is the same as any application especially in a list item where lots of data needs to be presented, it is better to load data in chunks as the user goes through the view. Here are some of the ways to solve this issue as regards to Ionic -

  • Ionic ion-virtual-scroll

  • Creating a Cordova plugin with list adapter view and loading contents through JavaScript while keeping the WebView transparent.

Image loading performance

Using ion-img, although getting started you might wonder why used this instead of HTML img tag, I used to wonder about this as well too but they are both different.

ion-img lazy loads image, so the page can actually finish loading on time before the images start to come up depending on the network speed, but just a tip you might want to add a fallback image to make the page looks a bit nicer before the image are loaded.

Minimizing imports

Import only what is necessary and clear up imports when they are not in use anymore, the unnecessary import can also contribute to a lot of size growth and performance issues.

Uglifying using the --prod flag

ionic cordova build android ` or ` npm run build does not uglify the JavaScript code, and can also contribute to app size, decreases performance and compromising your application performance and security.

Using the — prod flag will uglify your javascript files, and turn your application to production, although this won’t protect any information stored within the JavaScript but will decrease the application size and improve performance massively

ionic cordova build android --prod

Application Security

Make sure all users secured information is stored on the server only and pulled from API at runtime, it is not recommended at all to any store any sensitive information inside the app, including API secrets and there is no way to securely store those files without compromising user security and privacy.

Cleaning unused images | Fonts within your application

Sometimes we wonder what the issue is when the application size is too large but we fail to realize that we imported a lot of unused images and font files into the application.

Just like importing source files, for images, fonts, and icons, you also need to import only what is necessary. Importing those assets files on to the application and not removing the unused ones can grow the application size exponentially.

It is far better to only import what you really need and only add what’s needed to the application and delete ones that are not in use anymore.

Lazy load your component

If you have been following ionic for quite some time now, after ionic 1, ionic 2 beta was a huge turn off because of the performance but that mainly because all content in the app tries to load at the first time, sometimes you even end up with load time error which is very annoying.

But ever since version 3, Lazy loading module has been the norm and this improves performance a lot.

Lazy loading your module will only load components available within the current module and not the whole application and this is a very massive performance boost especially to the start time of the application.

Split your app build based on platforms

Huge application size is also a big turn off for many users especially me.

Have you ever seen an application and wonder what they are building to get to that size?
I have seen a lot of it and it is one of the factors that determine whether I install or not.

This one might be new to you, but you can actually split your build to different densities or ABI, this will not only reduce the app size mostly half of the current size but increase the performance as well, luckily you can always upload multiple ABI build to AppStore as well.
To learn more check out the google documentation here

Obfuscate & Optimize your App with ProGuard

ProGuard is the most popular optimizer for Java bytecode. It makes your Java and Android applications up to 90% smaller and up to 20% faster. ProGuard also provides minimal protection against reverse engineering by obfuscating the names of classes, fields, and methods.

ProGuard is one of those tools I call upon whenever my application is about to hit the app store and this is no different from ionic especially if you have a lot of custom plugin built.

ionic cordova plugin add cordova-plugin-proguard

There are several issues you will encounter integrating ProGuard, ranging from excluding required class, etc. You can always check the missing Plugin | lib repository on what to keep.

Finally, you are ready, but if you integrated ProGuard, It is better to actually test thoroughly after this step to make sure all the native functionalities and classes are not excluded and are working as expected

I would love to hear yours as well in the comment below. If you like this article or if it helped you get the performance you would like please consider sharing to your friends, you might be helping someone that is considering or struggling with Ionic for their next project.

Latest Posts