Статьи

5 минут до минимального безопасного углового кода с Grunt

Оптимизация скорости страниц, несомненно, является основным направлением для любого разработчика, создающего веб-приложения. Исполнители задач, такие как Grunt, могут играть ключевую роль в процессе разработки, поскольку они автоматизируют действия по конкатенации и минимизации кода, которые станут основными темами этого руководства. В частности, мы собираемся использовать набор плагинов Grunt, которые обеспечат безопасность нашего приложения AngularJS для минимизации. Прежде чем я начну обсуждать AngularJS и минификацию, я хочу подчеркнуть, что разработчики всех уровней квалификации могут извлечь выгоду из этого урока, однако базовые знания Grunt желательны. В этой статье мы будем генерировать новые папки с помощью Grunt, чтобы те, кто плохо знаком с использованием бегунов задач, получили представление о том, как все работает.

Проблема с минимизацией угловых приложений

Приложения AngularJS не являются минимально безопасными по умолчанию. Они должны быть написаны с использованием синтаксиса массива. Не беспокойтесь, если вы не уверены, что такое синтаксис массива, вы, вероятно, уже написали код, который его использует. Давайте рассмотрим два примера контроллеров AngularJS, которым передаются параметры $scope и $http .

В первом примере ниже фабрика и контроллер модуля обернуты в массивы, которые начинаются с аннотаций DI, и, как вы можете видеть, он не следует принципу СУХОЙ (не повторять себя) .

 var form = angular.module('ControllerOne', []) form.factory('Users', ['$http', function($http) { return { get: function() { return $http.get('/api/users'); }, create: function(userData) { return $http.post('/api/users', userData); }, delete: function(id) { return $http.delete('/api/users/' + id); } }; }]); form.controller('InputController', ['$scope', '$http', 'Users', function($scope, $http, Users) { formData = {}; $scope.createUser = function () { if ($scope.formData != undefined) { Users.create($scope.formData) .success(function (data) { $scope.users = data; $scope.formData = {}; $scope.myForm.$setPristine(true); }); } }; }]); 

В следующем примере crud.config модуля crud.config по-прежнему небезопасен, но код короче предыдущего. Он просто называет службы и затем передает необходимые зависимости в функцию в качестве параметров, без необходимости сначала записывать их в виде строк. Этот код будет работать нормально, если он не минифицирован. Таким образом, легко понять, почему люди часто выбирают этот синтаксис при написании кода AngularJS.

 var form = angular.module('ControllerTwo', []) form.factory('Users', function($http) { return { get: function() { return $http.get('/api/users'); }, create: function(userData) { return $http.post('/api/users', userData); }, delete: function(id) { return $http.delete('/api/users/' + id); } }; }); form.controller('InputController', function($scope, $http, Users) { formData = {}; $scope.createUser = function() { if ($scope.formData != undefined) { Users.create($scope.formData) .success(function(data) { $scope.users = data; $scope.formData = {}; $scope.myForm.$setPristine(true); }); } }; }); 

Теперь, когда вы узнали физические различия между двумя кодами, я быстро объясню вам, почему этот синтаксис небезопасен для минимизации.

Как работает массив

Как я уже говорил выше, обозначение массива начинается с аннотаций DI, которые играют ключевую роль в обеспечении минимальной безопасности этого кода. Когда UglifyJS запустится, он переименует наши параметры из $scope и $http в a и b соответственно. Наличие аннотаций DI, передаваемых в виде строк в массиве, блокирует их переименование. Следовательно, эти переименованные параметры могут по-прежнему иметь доступ к необходимым зависимостям.

Если этих аннотаций нет, код сломается. Как видите, писать код таким способом вручную крайне неэффективно. Чтобы помочь вам избежать этого, я сейчас собираюсь показать, как использовать Grunt для аннотирования, объединения и минимизации ваших приложений AngularJS таким образом, чтобы они были полностью оптимизированы с точки зрения минификации и готовы к использованию в производстве.

Используя Grunt

Весь репозиторий проекта, включая файлы, на которые мы нацеливаемся, можно найти на GitHub . Для тех, кому удобно использовать Grunt, смело следуйте инструкциям и создайте свою собственную сборку или добавьте этот код в существующий проект. Если вы работаете из пустой директории, вы должны убедиться, что в вашей директории есть файл «package.json». Этот файл может быть создан с помощью команды npm init .

Если у вас есть файл «package.json» в вашем проекте, вы можете загрузить плагины, выполнив следующую команду:

 npm install grunt-contrib-concat grunt-contrib-uglify grunt-ng-annotate --save-dev 

Это установит Grunt в ваш проект, а также три плагина, которые мы будем использовать:

  • Грунт-вно-CONCAT
  • Грунт-вно-уродовать
  • Грунт-нг-аннотировать

Несмотря на то, что ng-annotate можно использовать без Grunt, вы скоро увидите, как без проблем Grunt выполняет процесс аннотирования, объединения и минимизации кода. Он предлагает простое, но эффективное решение для минимизации кода AngularJS. Если вы следили за этим проектом с нуля, у вас должен быть Gruntfile.js в корневом каталоге вашего проекта, который будет содержать весь ваш код Grunt. Если вы еще этого не сделали, создайте его сейчас.

Три шага к минимально-безопасному коду

Шаг 1 — Настройте Grunt для чтения файла «package.json»

Чтобы получить доступ к плагинам, которые мы установили ранее, вам сначала нужно настроить свойство pkg в Gruntfile для чтения содержимого файла «package.json». Объект config начинается непосредственно в верхней части функции-оболочки Grunt и простирается от строк 3 до 5 в приведенном ниже примере, но вскоре будет содержать большую часть кода.

 module.exports = function(grunt) { //grunt wrapper function grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), //grunt task configuration will go here }); } 

Шаг 2 — Загрузите и зарегистрируйте задачи Grunt

После настройки Grunt для чтения нашего файла «package.json» необходимо загрузить плагины, чтобы Grunt мог получить к ним доступ. Это делается путем передачи имени плагина в grunt.loadNpmTask() в виде строки. Важно убедиться, что эти плагины загружены внутри функции-оболочки, но вне объекта config. Если эти условия не будут выполнены, Грант не будет работать правильно.

Следующее, что нам нужно сделать, это создать задачу по умолчанию, которая будет выполняться при вызове Grunt без определенной цели. Следует отметить порядок, в котором эти задачи добавляются, поскольку они будут выполняться в соответствии с их конфигурацией. Здесь ngAnnotate настроен для запуска в первую очередь, перед concat и UglifyJS, что, я считаю, является лучшим способом для создания вашего кода. Кроме того, важно помнить, что grunt.registerTask() должен быть размещен после загрузки плагинов.

Исходя из того, что мы только что обсудили, Gruntfile.js должен выглядеть следующим образом:

 module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), //grunt task configuration will go here }); //load grunt tasks grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-ng-annotate'); //register grunt default task grunt.registerTask('default', ['ngAnnotate', 'concat', 'uglify']); } 

Шаг 3 — Настройка плагинов

ngAnnotate

Теперь, когда наш Gruntfile готов к работе, давайте вернемся к объекту config и укажем файлы, которые мы хотим использовать для ngAnnotate модуля ngAnnotate . Чтобы сделать это, мы должны сначала создать раздел для ngAnnotate и создать цель, которая в этом случае называется spApp . Внутри этой цели вы укажете файлы, к которым вы хотите добавить аннотации DI, а также папку, в которой они должны быть сгенерированы. В этом примере Grunt возьмет три файла, указанных в public/js , и сгенерирует их в новую папку с именем public/min-safe .

Как только вы это настроите, вы можете запустить grunt ngAnnotate и посмотреть, как генерируется код. Кроме того, вы можете посетить страницу GitHub для grunt-ng-annotate и проверить различные опции, которые он позволяет вам указать.

 ngAnnotate: { options: { singleQuotes: true }, app: { files: { './public/min-safe/js/appFactory.js': ['./public/js/appFactory.js'], './public/min-safe/js/FormController.js': ['./public/js/FormController.js'], './public/min-safe/app.js': ['./public/js/app.js'] } } } 

конкатенация

Теперь, когда вы создали папку, заполненную новым аннотированным кодом AngularJS, давайте двигаться дальше, скомпилировав или объединив этот код в один файл. Таким же образом, как мы создали раздел для ngAnnotate , теперь мы сделаем то же самое для concat и UglifyJS . Как и ngAnnotate , обе эти задачи имеют цель, которая в данном случае — js . Существует несколько опций конфигурации, которые можно передать в эти задачи, но мы просто укажем src и dest чтобы указать на правильные файлы. Как вы уже догадались, эти плагины возьмут содержимое файлов, переданных в объект src , и обработают их в папку, указанную после dest .

Давайте попробуем понять, что здесь происходит. Вы можете проверить это, просто запустив grunt concat в своем терминале, и это должно привести к созданию ./public/min/app.js .

 concat: { js: { //target src: ['./public/min-safe/app.js', './public/min-safe/js/*.js'], dest: './public/min/app.js' } } 

минификация

Последнее, что нам нужно сделать, — это удалить ненужное пространство из нашего кода, уменьшив его. Это где плагин UglifyJS вступает в игру. Работая с UglifyJS, мы хотим, чтобы Grunt завершил окончательный процесс минимизации нашего приложения. Поэтому мы хотим нацелить файл, который содержит весь наш недавно объединенный код, который в этом случае является public/min/app.js Чтобы проверить это, запустите grunt uglify и посмотрите на свою недавно уменьшенную версию.

Вот относительная конфигурация для этой задачи:

 uglify: { js: { //target src: ['./public/min/app.js'], dest: './public/min/app.js' } } 

Во время этого урока мы использовали все эти задачи отдельно. Теперь давайте используем задание по умолчанию, которое мы создали ранее. Это позволит Grunt запускать все задачи, указанные сразу друг за другом, в порядке их регистрации. Теперь ваш код будет аннотирован, объединен и минимизирован простым запуском grunt внутри вашего проекта.

Выводы

Я надеюсь, что благодаря этому короткому руководству вы хорошо разберетесь в обозначении массива и о том, почему это важно для обеспечения минимальной безопасности приложений AngularJS. Если вы новичок в Grunt, я настоятельно рекомендую вам поиграть с этими и другими плагинами, так как они могут вас спасти. Как всегда, не стесняйтесь комментировать ниже, или напишите мне по адресу в моей биографии, если у вас есть какие-либо вопросы.