Blibli.com – How I refactor AngularJS 1.x to be minify-able

Berikut saya akan berbagi pengalaman saya beberapa pekan yang lalu di Blibli.com dalam meminify-ing AngularJS code.

Sebelumnya saya akan bercerita existing condition yang terjadi,
bahwa kami di Blibli.com menggunakan AngularJS sebagai framework rasanya sudah bukan rahasia lagi,
namun sebenarnya kami mengalami kesulitan dalam handle dan manage AngularJS code kami sendiri.
Ada banyak hal kami masih belum bisa handle dan benahi terutama dengan AngularJS yang begitu mengendalikan semua interaksi client side.
Sebenarnya kami sendiri tidak ingin menggunakan AngularJS untuk semua halaman kami,
dan hanya ingin digunakan pada halaman-halaman yang memang membutuhkan complex interaction saja,
namun yang terjadi sepertinya kami terjebak dengan kenikmatan data-binding dari AngularJS dan akhirnya merembet ke berbagai page kami.

Pada titik ini dimana ketika saya mulai bergabung dengan Blibli.com hal seperti ini memang sudah kadung terjadi,
dan yang bisa saya tawarkan hanyalah membenahi pelan-pelan code mengikuti yang seharusnya.
Hal akan saya bagikan di post kali ini adalah mengenai proses membuat AngularJS code kami minify-able.

Untuk issue soal AngularJS yang susah untuk di minify sebenarnya sudah dijelaskan di berbagai situs.
https://scotch.io/tutorials/declaring-angularjs-modules-for-minification
https://www.sitepoint.com/5-minutes-to-min-safe-angular-code-with-grunt/
Penyebabnya adalah karena gagal meng-implementasikan Depedency Injection yang ditawarkan oleh AngularJS,
yang tentu saja hal ini tidak terjadi bila code tidak di minify.

Setelah saya coba melihat exising code dan sepertinya memang masalah terbesarnya adalah di Depedency Injection,
namun pada penerapannya ternyata saya juga harus refactor beberapa code agar bisa berjalan dengan baik dalam kondisi yang ter-minify.

1. Menambahkan manual inject di controller

Bila sebelumnya kami mendefinisikan controller kami seperti ini :

myModule.controller('my.id', ['$scope', 'myService', myFunc]);

Maka harus ditambahkan manual injection ke function tesebut, seperti berikut :

myFunc.$inject = ['$scope', 'myService'];
myModule.controller('my.id', ['$scope', 'myService', myFunc]);

2. Mengeluarkan Depedency Injection dari custom directives

Hal lain yang membuat saya harus refactor code sebelum minify adalah karena beberapa directives menggunakan depedency injection dengan tidak seharusnya,
Solusi yang bisa dilakukan adalah mengeluarkan depedency ini ke independent controller sehingga nanti controller lah yang akan kita inject depedency.

Bila code sebelumnya seperti ini :

myModule.directive('mydirective', ['$scope', '$modal', 'myService', myDirectiveFunc]);
function myDirectiveFunc() {
    return {
        restrict: "A",
        controller: function($scope, $modal, myService){
	
	}
    };
}

Maka harus dipisahkan controllernya, seperti berikut :

myCtrlFunc.$inject = ['$scope', '$modal', 'myService'];
myModule.controller('myCtrl', ['$scope', '$modal', 'myService', myCtrlFunc]);
function myCtrlFunc($scope, $modal, myService){

}
myModule.directive('mydirective', myDirectiveFunc);
function myDirectiveFunc() {
    return {
        restrict: "A",
        controller: "myCtrl",
	require: "mydirective"
    };
}

Bila menggunakan link, bisa ditambahkan method untuk diakses dari scope-nya, seperti berikut :

myCtrlFunc.$inject = ['$scope', '$modal', 'myService'];
myModule.controller('myCtrl', ['$scope', '$modal', 'myService', myCtrlFunc]);
function myCtrlFunc($scope, $modal, myService){
	$scope.getDepedencies = function () {
        	var depedencies = {};
        	depedencies["modal"] = $modal;
        	depedencies["myService"] = myService;
        	return depedencies;
    	};    
}
myModule.directive('mydirective', myDirectiveFunc);
function myDirectiveFunc() {
    return {
        restrict: "A",
        controller: "myCtrl",
	require: "mydirective",
	link: function (scope, element, attrs) {
		var depedencies = scope.getDepedencies();
		var modal = depedencies["modal"];
		var myService = depedencies["myService"];
	}
    };
}

3. Mengeluarkan inline controller inside controller

Ini kerap terjadi ketika membuat controller kecil yang dibuat di dalam controller lainnya.
Bila sebelumnya ada hal seperti ini :

myCtrlFunc.$inject = ['$scope', '$modal', 'myService'];
myModule.controller('myCtrl', ['$scope', '$modal', 'myService', myCtrlFunc]);
function myCtrlFunc($scope, $modal, myService){
  $scope.openSomeModal = function(){
         $scope.modalInstance = $modal.open({
           templateUrl :  'templateSnippet/someView.html',
           controller : inlineController
        });
  };
  function inlineController($scope, $modal, $modalInstance) {
        $scope.closeModal = function () {
            $modalInstance.close();
        };
  }
}

Maka salah satu solusinya adalah memisahkan controller ini, seperti berikut :


inlineController.$inject = ['$scope', '$modal', '$modalInstance'];
myModule.controller('inlineCtrl', ['$scope', '$modal', '$modalInstance', inlineController]);

myCtrlFunc.$inject = ['$scope', '$modal', 'myService'];
myModule.controller('myCtrl', ['$scope', '$modal', 'myService', myCtrlFunc]);

function myCtrlFunc($scope, $modal, myService){
  $scope.openSomeModal = function(){
         $scope.modalInstance = $modal.open({
           templateUrl :  'templateSnippet/someView.html',
           controller : 'inlineCtrl'
        });
  };  
}

function inlineController($scope, $modal, $modalInstance) {
        $scope.closeModal = function () {
            $modalInstance.close();
        };
  }

Bila ada yang salah atau bila ada yang punya solusi lebih elegan, silahkan isi di kolom komentar dibawah ya…

Demikian sharing dari saya, semoga bermanfaat

mazipan-signature

3 thoughts on “Blibli.com – How I refactor AngularJS 1.x to be minify-able

    1. sama om,
      ane juga pake ng-annotate.
      next post kayanya mau ane tulis juga kok.
      tapi ada hal yang tidak ke jangkau ama ini.
      Masalahnya ada di kita sendiri, kebiasaan ngoding asal jalan tanpa ngikutin best practice-nya.

      Like

Be a good reader, leave your comment please.