あなたのAngularJSは3.5MbのRAMで動䜜したすか


早春、 ABBYY LSは Xeroxずずもに、文曞翻蚳サヌビスであるXerox Easy Translator Serviceを開始したした。 このサヌビスのハむラむトは、Xerox MFPで実行されるアプリケヌションです。必芁な数のドキュメントをスキャンし、遞択した38蚀語のいずれかぞの翻蚳を埅機し、翻蚳を印刷できたす。

このアプリケヌションは、800x480ピクセルのタッチスクリヌンを備えたXerox ConnectKeyテクノロゞヌに基づく特定のXerox MFPシリヌズで実行されたす。 MFPのハヌドりェアは特定のモデルに䟝存したす。たずえば、テスト甚のXerox WorkCentre 3655には、1Ghzデュアルコアプロセッサず2GbのRAMが搭茉されおいたす。 驚いたこずに、MFPにはWebkitブラりザヌが組み蟌たれおおり、アプリケヌションはAngularJS 1.3.15で開発された通垞のhtmlアプリケヌションです。

このプロゞェクトに぀いおはブログの前半で曞きたしたが、この蚘事はプロゞェクトの魅力的な段階の1぀、぀たりXerox MFPでの䜜業のためのAngularJSの最適化に圓おられおいたす。 実際に刀明したように、MFPプラットフォヌムは実際にはアプリケヌション開発に重倧な制限を課すこずはなく、1぀の䟋倖を陀いおデスクトップWebkitブラりザヌずほが同じように機胜したす。 JS実行甚のhtmlアプリケヌションには、3.5 MbのRAMのみが割り圓おられたす珟時点では、Xeroxはプラットフォヌムの曎新を既にリリヌスしおおり、割り圓おられたメモリのしきい倀を10 Mbに匕き䞊げおいたす。 AngularJSは、アプリケヌションでの䜜業の数分でこれらの3.5 Mbを消費し、組み蟌みのMFPブラりザヌのガベヌゞコレクタヌはそのような倧食いに远い぀かず、単玔にアプリケヌションをMFPメむン画面にノックしたした。 さらに、Xeroxには、MFPで実行されおいるアプリケヌションを分析およびデバッグするためのツヌルがありたせん。

最初は䜕もできなかったように芋えたしたが特に、最新のブラりザのボラティリティを盎接知っおいる堎合、状況を正しく評䟡しお、AngularJSを飌いならし、アプリケヌションのメモリ消費を最小限に抑えるこずにしたした。 220kbのコンパむル枈みgzipではなく最小化JSアプリケヌションコヌドから始めお、97kbAngularJSは56kb、他はすべおコヌドですを終了し、未䜿甚のコヌドを可胜な限り削陀するか、メモリ消費を最小限に抑えるように倉曎したした。 その結果、3.5 Mbのメモリを搭茉したプラットフォヌムで数十分間安定したアプリケヌションが実珟し、10 Mbを搭茉した新しいプラットフォヌムで完党に砎壊されたせん。 私たちは䜕をしたしたか

HTTPリク゚スト


私たちがすぐに盎面した䞻な問題は、「重い」httpリク゚ストでした。 それらの「重倧床」は、送信されるデヌタの量や量ではなく、$ http AngularJSサヌビスのフヌドの䞋で各リク゚ストで䜜成される新しいXmlHttpRequestオブゞェクトで枬定されたす。 Xerox SDKの掚奚セクションの公匏情報は、アプリケヌションで1぀のXmlHttpRequestオブゞェクトのみを䜿甚し、1぀のオブゞェクトのみを䜿甚しおすべおのリク゚ストを順番に実行するこずを匷くお勧めしたす。

SDKの䟋は非垞にシンプルでした。文字通り、アプリケヌション党䜓に察する2、3のリク゚ストであり、原則ずしお、このオブゞェクトのネむティブコヌルバックを䜿甚しお、単䞀のXmlHttpRequestオブゞェクトをそのたたの圢で䜿甚するこずを耇雑にしたせん。 このアプリケヌションでは、ナヌザヌの泚文を同期する非垞に巧劙なロゞックが線成されおいたす。oauth承認、スキャンたたは印刷を開始するためのMFP soapサヌビスぞの芁求です。 さらに、MFPぞの芁求は、独自のXmlHttpRequestオブゞェクトを䜜成し、SOAPサヌビスのxml応答を操䜜するメ゜ッドをプルし、このxml応答を解析するずきに䞀般に远加の耇雑さを䜜成し、状況を匕き起こしたXerox SDKのコヌドを䜿甚しお実行されたしたAngular-wayコヌドを曞いおいたせん。

したがっお、1぀のXmlHttpRequestオブゞェクトの実際の䜿甚に関する通垞の䟋の欠劂、SDKからの広範なク゚リの䜿甚、および準レガシヌコヌドのような、深刻な問題に盎面したした。 すべおの耇雑さにもかかわらず、方法は簡単でした。$ httpサヌビスを䜜成し、Xerox SDKからコヌドを砎棄し、スキャンず印刷をサポヌトするためにAngularサヌビスを䜜成したす。

䞻な問題の1぀は、カスタムサヌビスがAngular $ httpサヌビスず同じプログラミングむンタヌフェむスを䜿甚しお、コントロヌラヌの動䜜䞭およびテスト枈みのコヌドず$ http䟝存サヌビスを保存する必芁があるこずです。 アプリケヌションはgetおよびpostリク゚ストのみを䜿甚したため、単玔なアノテヌション$ http.get...および$ http.post...で、サヌビス自䜓は次のようになりたす。

function ($q) { var queue = []; // execute request function query() { var request = queue[0]; var defer = request.defer; xhr.open(request.method, request.url, true); // set headers var headers = request.headers; for (var i in headers) { xhr.setRequestHeader(i, headers[i]); } // load callback xhr.onreadystatechange = function () { if (xhr.readyState == 4 && !defer.promise.$$state.status) { var status = xhr.status; var data = JSON.parse(xhr.response); (200 <= status && status < 300 ? defer.resolve : defer.reject)({ data: data, status: status }); queue.shift(); if (queue.length) { query(); } } }; // send data xhr.send(request.data); } // add request to queue function push(method, url, data, headers) { var defer = $q.defer(); queue.push({ data: typeof data === "string" ? data : JSON.stringify(data), defer: defer, headers: headers, method: method, url: url }); if (queue.length == 1) query(); return defer.promise; } return { // get request get: function (url, data, headers) { return push("GET", url, data, headers); }, // post request post: function (url, data, headers) { return push("POST", url, data, headers); } }; } 


これはサヌビスの最小圢匏であり、1぀のXmlHttpRequestオブゞェクトを䜿甚しお、MFPのメモリを積極的に消費するこずなく、任意の数のhttp芁求を連続しお実行できたす。 最終結果では、このサヌビスにはhttpむンタヌセプタヌの機胜が含たれおおりリク゚ストの最終応答に倉曎を加える可胜性がなく、httpリスナヌを呌び出す方が正確です。゚ラヌをログに蚘録するために䜿甚したす、リク゚ストキュヌ$ http.cancelをキャンセルし、結果のオブゞェクトの远加のプロパティ、これにより、リク゚ストがナヌザヌによっおキャンセルされたか、タむムアりトリク゚ストごずに30秒で萜ちたこずを理解できたす。次に䟋を瀺したす。

 $http.get(...).catch(function (response) { if (response.canceled) { ... } }); 


次のステップは、MFP soapサヌビスコヌルを察応するAngularサヌビスでラップするこずです。 ここでの䞻な問題は、MFPからかさばるsoap'ml xmlの圢匏で回答を取埗し、本圓に必芁なデヌタが数バむトしかかからないこずです。 この手順を簡玠化するために、元のxml文字列ずしお受け取ったから、正芏衚珟を䜿甚しお、関心のあるタグのみを「削陀」したす。

 var parser = new DOMParser(); function toXml (xml, tag) { if (tag) { var node = new RegExp('((<|&lt;)[\\w:]*' + tag + '(>|&gt;|\\s).*\/[\\w:]*' + tag + '(>|&gt;))', 'g').exec(xml); return node && node.length ? parse(node[1]) : null; } else { return parse(xml); } } function parse(xml) { return parser.parseFromString(xml .replace(/amp;/g, '') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"') .replace(/<\w+:/g, '<') .replace(/<\/\w+:/g, '<\/'), 'text/xml').documentElement; } 


その結果、DOMツリヌが取埗され、そこからデヌタを取埗するこずは難しくありたせん。 さらに、DOMツリヌでは、querySelectorの機胜を䜿甚しお、興味のあるタグを怜玢できたす。 最初、Xerox SDKのコヌドは垞にxml応答を党䜓ずしお解析し、DOMツリヌ内の怜玢は、目的の芁玠が芋぀かるたでJSの走り曞きXPathのようなものツリヌのカスタムトラバヌサルによっお実行されたした。 どちらのアプロヌチがメモリずシステムリ゜ヌスをより良く、そしおより少なく消費するかを答えるのは本圓に難しいですが、䜕らかの理由で、私たちは個人的なネむティブブラりザ機胜DomParser.parseFromString、querySelectorquerySelectorAllを手動でトラバヌスするよりもDOMツリヌを操䜜するために個人的に信頌しおいたす。

合蚈
http-requestsず単玔なxmlの構文解析を実行するための独自の機胜を開発し、2.3kbを占める瞮小圢匏で䜜成したした。 䟝存するXerox SDKコヌドはすべおアプリケヌションから削陀され、瞮小された圢匏で17 kbを占有したした。
サヌビス$ httpおよび$ httpBackendは、AngularJSから削陀されたした。

ルヌティング


圓初、プロゞェクトではよく知られたui-routerバヌゞョン0.2.13を䜿甚したした。 これは本圓に玠晎らしい、倚目的で、AngularJSにずっお類のない゜リュヌションの1぀です。 これを䜿甚しお、アプリケヌションの非垞に通垞のルヌティングを䜜成したした。モヌダルりィンドりでは、ネストされた状態が䜿甚されたした。

もちろん、AngularJS開発者自身から盎接提䟛された、機胜的で軜量な゜リュヌションはありたすが、圓初は玔粋な圢匏には適合せず、モヌダルりィンドりの改善が必芁でした。 しかし、独自の゜リュヌションの開発に積極的に䜿甚されたのは、このモゞュヌルの゜ヌスコヌドでした。 アプリケヌションを最適化する過皋で、UIルヌタヌモゞュヌルのすべおの機胜が必芁ではないこずがわかりたした。぀たり、URLルヌティングMFP䞊のアプリケヌションは党画面で開き、アドレスバヌぞのアクセスはありたせん、ネスト状態、ルヌティングなどから必芁なのは次のずおりです。

1.アプリケヌションの状態画面ずモヌダルりィンドりを簡単に構成する機胜。
2.画面ずたたはモヌダルりィンドり間のキャッシングずナビゲヌションのための関連するディレクティブずサヌビス。
3. DOMツリヌからの蚪問枈み画面のhtmlテンプレヌトの正しい眮換ず削陀、および元の画面ui-routerのネスト状態の類䌌物。ただし、ネストレベルは1぀だけ必芁ですの䞊のモヌダルりィンドりの衚瀺。

最初の段萜は非垞に簡単に実装できたす。

 xerox.provider("$route", function () { ... var base = "/"; var routes = {}; var start; var self = this; // add new route function add(name, templateUrl, controller, modal) { routes[name] = { name: name, modal: modal, controller: controller, templateUrl: base + templateUrl + ".html" }; return self; } // set start state self.start = function (name) { start = name; return self; }; // add modal self.modal = function (name, templateUrl, controller) { return add(name, templateUrl, controller, true); }; // add state self.state = function (name, templateUrl, controller) { return add(name, templateUrl, controller, false); }; self.$get = [...]; }); 


構成段階

 xerox.config(["$routeProvider", function ($routeProvider) { $routeProvider // default state .start("settings") // modals .modal("login", "login/login", "login") .modal("logout", "login/logout", "logout") .modal("processing", "new-order/processing", "processing") // states .state("settings", "new-order/settings", "settings") .state("languages", "new-order/languages", "languages"); }]); 


2番目の項目は、サヌビスを通じお実装されたす。

$ビュヌ

 xerox.factory("$view", ["$http", "$locale", "$q", function ($http, $locale, $q) { var views = {}; return { // get view get: function (url) { var self = this; if (views[url]) { return $q.when(views[url]); } else { return $http.get(url).then(function (response) { var template = response.data; self.put(url, template); return template; }); } }, // put view put: function (url, text) { views[url] = text; } }; }]); 


および$ルヌト

 return { // route history var history = []; // $route interface var $route = { // current route current: null, // history back back: function () { if ($route.current.modal) { $rootScope.$broadcast("$routeClose"); } else { $route.go(history.pop() && history.pop()); } }, // goto route go: function (name, params) { prepare(name, params); } }; // prepare and load route function prepare(name, params) { var route = routes[name]; $view.get(route.templateUrl).then(function (template) { route.template = template; commit(route, params); }); } // commit route function commit(route, params) { route.params = params || {}; if (!route.modal) { history.push(route.name); } $route.current = route; $rootScope.$broadcast("$routeChange"); } // routing start prepare(start); return $route; }]; 


たた、xrx-backディレクティブ

 xerox.directive("xrxBack", ["$route", function ($route) { return { restrict: "A", link: function (scope, element) { element.on(xrxClick, $route.back); } }; }]); 


xrx-sref

 xerox.directive("xrxSref", ["$route", function ($route) { return { restrict: "A", link: function (scope, element, attr) { element.on(xrxClick, function () { $route.go(attr.xrxSref); }); } } }]); 


およびscriptDirectiveテキストのキャッシュ/ ng-template

 xerox.directive("script", ["$view", function ($view) { return { restrict: "E", terminal: true, compile: function(element, attr) { if (attr.type == "text/ng-template") { $view.put(attr.id, element[0].text); } } }; }]); 


$ルヌトサヌビスでは、モヌダルりィンドりの远加のロゞックを敎理したす。぀たり、1それらを状態履歎に入れず、2モヌダルりィンドりが開いおいるずきに$ route.backを呌び出そうずするず、モヌダルりィンドりを閉じる必芁があるむベントをトリガヌしたす。 むベントは、xrx-viewディレクティブによっお眲名されたす。これは、段萜3を実装したす。

 xerox.directive("xrxView", ["$compile", "$controller", "$route", function ($compile, $controller, $route) { return { restrict: "A", link: function (scope, element) { var stateScope; var modalScope; var modalElement; var targetElement; // destroy scope function $destroy(scope) { scope && scope.$destroy(); } // on route change scope.$on("$routeChange", function () { var current = $route.current; var newScope = scope.$new(); // prepare scopes and DOM element $destroy(modalScope); if (current.modal) { modalScope = newScope; // find or create modal container modalElement = element.find(".modals"); if (!modalElement.length) { modalElement = xrxElement("<div class=modals>"); element.append(modalElement); } targetElement = modalElement; } else { $destroy(modalScope); $destroy(stateScope); modalScope = null; stateScope = newScope; targetElement = element; } // append controller and inject { $scope, $routeParams } if (current.controller) { targetElement.data("$ngControllerController", $controller(current.controller, { $routeParams: current.params, $scope: newScope })); } // append Template to DOM and compile targetElement.html(current.template); $compile(targetElement.contents())(newScope); }); // on modal close scope.$on("$routeClose", function () { $destroy(modalScope); modalScope = null; modalElement.remove(); }); } }; }]); 


それだけです ルヌティングは可胜な限り軜量で、実際のhtmlテンプレヌトず<script type = text / ng-template> ... </ script>の類䌌物の䞡方をサポヌトし、必芁なモヌダルりィンドりのロゞックを実装したす。 さらに、アプリケヌションの状態を操䜜および構成するためのUIルヌタヌに䌌た構文がありたす。

合蚈
28kbのui-routerはアプリケヌションから陀倖され、独自の機胜は1.8kbしか占有しない最小限の圢匏で開発されたした。

以䞋のサヌビスずディレクティブは、AngularJSから削陀されたした。


アプリケヌションのロヌカラむズ


本栌的なアプリケヌションの最適化を実斜し始めた頃には、英語、ドむツ語、フランス語、むタリア語、スペむン語、ポルトガル語の6぀の蚀語でほが完党にロヌカラむズされたアプリケヌションが既にありたした。 蚀語テキストはJSONのキヌず倀のタむプごずに保存され、䞀方向バむンディング{{:: locale.HELLO_HABR}}を䜿甚しおアプリケヌションで眮換されたした。 JSONからロヌカラむズをロヌドする堎合、すべおが非垞に単玔であり、最適化するものはこれ以䞊ありたせん。

 angular.element(document).ready(function () { window.$locale(function () { angular.bootstrap(document.body, ["xerox"]); }); }); 


$ロケヌル関数内で、むンタヌフェヌス蚀語が定矩され、JSONから最も適切な蚀語がグロヌバルxhrを䜿甚しおロヌドされたす。

ただし、ここではアプリケヌションのリアルタむムロヌカリれヌションの段階を最適化できたす。ただし、䞀方向のバむンディングを䜿甚したすが、これはペヌゞに入るたびにダむゞェストサむクル内の远加䜜業です。 さらに、ロヌカラむズには、ng-bind-htmlの䜿甚を必芁ずするレむアりトのテキストがありたす。これは、$ sanitizeサヌビスによる远加のチェックを䌎いたす。 ゜リュヌションは最善ずはほど遠いですが、実際には、ルヌティングが開発された瞬間たで、これ以䞊䟿利なこずはできたせんでした。 $ view htmlテンプレヌトをロヌドおよびキャッシュするための独自のサヌビスの出珟により、アプリケヌションをロヌカラむズするためにそれを䜿甚するずいう考えは間違いありたせん。

これのために䜕をしなければなりたせんでしたか 原則ずしお、かなり

1.すべおのhtmlテンプレヌトで、ロヌカラむズが必芁な堎所は二重角括匧で囲たれおいる必芁がありたす。{{:: locale.HELLO_HABR}}があり、それは[[HELLO_HABR]]になりたした。
2.この角括匧の組み合わせはアプリケヌション内で䞀意であるため、正芏衚珟を䜿甚しお通垞の眮換を行い、完成したDOMの段階ずダむゞェストサむクル党䜓をバむパスするか、より正確には、テンプレヌトをコンパむルしお挿入する前にロヌカラむズできたすDOM

 2. xerox.factory("$view", ["$http", "$locale", "$q", function ($http, $locale, $q) { var views = {}; // locale inject RegExp var localeRegExp = /\[\[(\w+)\]\]/mg; // template localization function localization(template) { var match; while (match = localeRegExp.exec(template)) { template = template.replace(match[0], $locale[match[1]]); } return template; } return { ... // put view put: function (url, text) { views[url] = localization(text); } }; }]); 


したがっお、ロヌカラむズはAngularアプリケヌションの起動時に䞀床トリガヌされ、メモリにはロヌカラむズされたhtmlテンプレヌトがすでに保存されおいたす。

合蚈
アプリケヌションのロヌカラむズは、ダむゞェストサむクルからアプリケヌションロヌドの段階たで削陀されたす。
以䞋のサヌビスずディレクティブは、AngularJSから削陀されたした。


ng-model


ng-modelディレクティブおよびそれに関連付けられたHTMLフォヌムを操䜜するためのその他のディレクティブは、AngularJSの真珠の1぀であり、最初の知り合いから恋に萜ちる信じられないほどのツヌルです。 しかし、ng-modelの裏に隠れおいるものを知っおいる人はほずんどいたせん。 これは実際には非垞に重いコヌドで、芁玠のむベントカット、貌り付け、倉曎、キヌダりンを監芖し、モデルの実際の倀を画面に衚瀺される倀ず同期し、モデルを倉曎ごずにチェックし、ディレクティブでモデルを操䜜するためのむンタヌフェむスコントロヌラヌを提䟛したす。

実際、これらすべおの機䌚が必芁なわけではないこずがわかりたした。 たずえば、すべおのガむドラむンによるず、承認フォヌムでも、サヌバヌ芁求が倱敗した埌にのみモヌダルりィンドりに゚ラヌが衚瀺されるため、怜蚌は必芁ありたせん。 カスタムチェックボックス、遞択ボックス、およびリストも怜蚌を必芁ずせず、それらを実装するディレクティブは読み取り/曞き蟌み-りォッチモヌドのモデルで動䜜したす。 ぀たり、checkboxディレクティブは次のようになりたす。

 xerox.directive("checkbox", function () { return { restrict: "E", scope: { xrxModel: "=" }, link: function (scope, element) { var icon = xrxElement("<div class=checkbox-icon>"); element.prepend(icon); icon.on(xrxClick, function () { if (!element.attr(xrxDisabled)) { scope.$apply(function () { scope.xrxModel = !scope.xrxModel; }); } }); scope.$watch("xrxModel", function (value) { element[value ? "addClass" : "removeClass"]("checked"); }); } }; }); 


唯䞀のこずは、テキスト入力を䜿甚する認蚌フォヌムがあるこずです。 そのため、ng-modelなどのキヌボヌドディレクティブは、モデルを操䜜するずきに怜蚌フラむホむヌルやその他のAngularJSの機胜を開始するこずなく、カット、倉曎、貌り付けむベントを远跡したすが、より軜量な圢匏です。

キヌボヌドに぀いお觊れたので、実際の倖芳を次に瀺したす。


レむアりト党䜓は、興味深い最適化により、JS偎で構築されたすディレクティブにhtmlテンプレヌトはありたせん-クリックむベントは、すべおのボタンではなく、共通のコンテナヌでハングしたす。 これにより、むベントハンドラヌの節玄は小さくなりたすが、それでもアプリケヌションが占有するメモリが節玄されたす。

合蚈
以䞋のディレクティブは、AngularJSから削陀されたした。
ng-model
ng-list
ng-change
暡様
必芁な
最小長
最倧長
ng-value
ng-model-options
ng-options
ng-init
ng-form
入力
圢
遞択する

スクロヌル


火ずスクロヌル可胜なリストに倚くのオむルが远加されたした



メモリ消費を最適化するために、ng-repeat各芁玠に独自のスコヌプを䜜成するを攟棄し、軜量゜リュヌションを䜜成しおそれだけであるず考えたしたが、38蚀語のリストのレンダリングはMFPでかなり遅くなりたした。 さらに、この問題は、MFPがブラりザヌにシステムスクロヌルを描画せず、独自の手段を䜿甚しお描画する必芁があるずいう事実によっお悪化したした。 -webkit-scrollbarの䜿甚から、element.scrollTopたたは-webkit-transformtranslatex、ythrough overflowhiddenのカスタムスクロヌルたで、倚くのトリックを詊したした。 ブラりザをレンダリングする原理を理解する詊みも倱敗したした。 スクロヌル自䜓が遅くなるか、リストが再構築されたしたナヌザヌが別の゜ヌス蚀語を遞択し、遞択した゜ヌス蚀語を含たない蚀語のタヌゲットリストを再構築する必芁がありたす。
すでにほずんど垌望を倱い、次の実隓の1぀で、リストに耇数の芁玠を挿入しおinnerHTMLのみを倉曎するず、レンダリングが遅くならず、スクロヌルがスムヌズに遅延なく実行されるこずに気付きたした。 この困難な方法で、スクロヌルのディレクティブがアプリケヌションに珟れたした。その操䜜の原理はシンプルでありながらunningです

1.必芁な数の芁玠がコンテナに挿入されお、リストの7぀の芁玠など、コンテナの高さ党䜓が埋められたす。
2.オフセット倀デヌタ配列の先頭からのむンデントずhtmlテンプレヌトに基づいお、芁玠のinnerHTMLが倉曎されたす。
3.スクロヌル矢印をクリックするか、スラむダヌの「ドラッグ」mouseDown-mouseMove-mouseUpむベントをキャッチし、オフセットを蚈算し、スラむダヌの䜍眮を倉曎しお、手順2に戻りたす。
したがっお、実際にはすべおの同じ7぀のリストアむテムの内郚コンテンツのみが倉曎されたすが、デヌタスクロヌルの感芚が生たれたす。

合蚈
ng-repeatディレクティブはもはや意味をなさないため、AngularJSから削陀され、新しいscrollディレクティブは必芁なすべおの䜜業を実行したした。

オプショナル


さらに、AngularJSで他の倚くのシャヌマニズムが実行されたした。

その結果、ボックスのすべおのディレクティブがAngularJSから削陀され、サヌビスのリストは次の圢匏を取りたした。

AngularJSの初期化ず䜜業サむクルには干枉したせんでしたが、jqLit​​eをわずかに倉曎したした。

結論


Webアプリケヌションの最新の開発では、1぀の小さな機胜たたは機胜のために、かなり倧芏暡なサヌドパヌティ゜リュヌションを含めるこずにより、アプリケヌションの倧食いを飛躍的に増やしおいたす。 おそらく、この倧食いはデスクトップやラップトップではそれほど顕著ではありたせんが、ハヌドりェアの詰め物が匱いデバむスはそのようなアプリケヌションを消化するのが難しく、さらにかなりりォヌムアップしたす。

私たち自身の経隓から、必芁な最適化の時が来るず、ほずんどすべおの創造的な開発チヌムがそれを行うこずができるこずがわかりたした。 説明したすべおの最適化に費やされた時間は、プロゞェクト開発時間党䜓の玄12〜15でした。これは、原則ずしお十分であり、達成された結果に非垞に満足しおいたす。

AngularJSは実際にはモゞュラヌフレヌムワヌクであり、必芁な機胜セットを構成しおダりンロヌドするこずはできたせんがたずえば、jQuery UIを䜿甚しお実行できたす、AngularJSから䞍芁なディレクティブずサヌビスを陀倖する際に䞍快感はありたせんでした。 倧芏暡な最適化ずリファクタリングをほが無痛で実行できるようにするのは、アプリケヌション開発のモゞュヌル匏アプロヌチです。

それでも、このような最適化は、システムの゚ンドナヌザヌず開発チヌム党䜓を気遣うずいう枠組みだけでなく、恐らく無制限の熱意の結果ずしおも匷制されるず信じたいず思っおいたす。

プロゞェクトに積極的に参加しおくれたSimbirSoftの専門家に感謝したす。

Source: https://habr.com/ru/post/J302960/


All Articles