Статьи

Использование Grunt с AngularJS для оптимизации интерфейса

Я увлечен оптимизацией интерфейса и был в течение многих лет. Моим оригинальным вдохновением был Стив Соудерс и его выступление на веб-сайтах Even Faster на OSCON 2008 . С тех пор я оптимизировал этот блог , сделал его еще быстрее с новым дизайном , удвоил скорость работы нескольких приложений для клиентов и показал, как сделать AppFuse быстрее . В рамках презентации Devoxx 2013 я показал, как оптимизировать скорость страницы в веб-приложении Java .

Я разработал пару приложений AngularJS в прошлом году. Чтобы объединить и минимизировать их таблицы стилей и сценарии, я использовал механизмы, которые уже существовали в проектах. В одном проекте это был Ant и его конкретная задача . С другой стороны, это было частью приложения Grails, поэтому я использовал ресурсы и плагины yui-minify-resources .

Проект Angular, над которым я сейчас работаю, будет опубликован на веб-сервере, а также включен в собственное приложение iOS. Поэтому на этот раз я обратился к Гранту за оптимизацией. Я обнаружил, что это довольно просто, как только я понял, как заставить его работать с Angular . Основываясь на моих выводах, я отправил запрос на добавление Grunt в angular-seed .

Ниже приведены шаги, которые я использовал, чтобы добавить Grunt в свой проект Angular.

  1. Установите интерфейс командной строки Grunt с помощью команды «sudo npm install -g grunt-cli».
  2. Отредактируйте файл package.json, указав номер версии (например, «версия»: «1.0.0»).
  3. Добавьте плагины Grunt в package.json для создания версий concat / minify / asset:
    "grunt": "~0.4.1",
    "grunt-contrib-concat": "~0.3.0",
    "grunt-contrib-uglify": "~0.2.7",
    "grunt-contrib-cssmin": "~0.7.0",
    "grunt-usemin": "~2.0.2",
    "grunt-contrib-copy": "~0.5.0",
    "grunt-rev": "~0.1.0",
    "grunt-contrib-clean": "~0.5.0"
  4. Создайте, Gruntfile.jsкоторый запускает все плагины.
    module.exports = function (grunt) {
     
        grunt.initConfig({
            pkg: grunt.file.readJSON('package.json'),
     
            clean: ["dist", '.tmp'],
     
            copy: {
                main: {
                    expand: true,
                    cwd: 'app/',
                    src: ['**', '!js/**', '!lib/**', '!**/*.css'],
                    dest: 'dist/'
                },
                shims: {
                    expand: true,
                    cwd: 'app/lib/webshim/shims',
                    src: ['**'],
                    dest: 'dist/js/shims'
                }
            },
     
            rev: {
                files: {
                    src: ['dist/**/*.{js,css}', '!dist/js/shims/**']
                }
            },
     
            useminPrepare: {
                html: 'app/index.html'
            },
     
            usemin: {
                html: ['dist/index.html']
            },
     
            uglify: {
                options: {
                    report: 'min',
                    mangle: false
                }
            }
        });
     
        grunt.loadNpmTasks('grunt-contrib-clean');
        grunt.loadNpmTasks('grunt-contrib-copy');
        grunt.loadNpmTasks('grunt-contrib-concat');
        grunt.loadNpmTasks('grunt-contrib-cssmin');
        grunt.loadNpmTasks('grunt-contrib-uglify');
        grunt.loadNpmTasks('grunt-rev');
        grunt.loadNpmTasks('grunt-usemin');
     
        // Tell Grunt what to do when we type "grunt" into the terminal
        grunt.registerTask('default', [
            'copy', 'useminPrepare', 'concat', 'uglify', 'cssmin', 'rev', 'usemin'
        ]);
    };
  5. Добавьте комментарии в app / index.html, чтобы usemin знал, какие файлы обрабатывать. Комментарии являются важной частью, ваши файлы, вероятно, будут отличаться.
    <!-- build:css css/app-name.min.css -->
    <link rel="stylesheet" href="lib/bootstrap/bootstrap.min.css"/>
    <link rel="stylesheet" href="lib/font-awesome/font-awesome.min.css"/>
    <link rel="stylesheet" href="lib/toaster/toaster.css"/>
    <link rel="stylesheet" href="css/app.css"/>
    <link rel="stylesheet" href="css/custom.css"/>
    <link rel="stylesheet" href="css/responsive.css"/>
    <!-- endbuild -->
    ...
    <!-- build:js js/app-name.min.js -->
    <script src="lib/jquery/jquery-1.10.2.min.js"></script>
    <script src="lib/bootstrap/bootstrap.min.js"></script>
    <script src="lib/angular/angular.min.js"></script>
    <script src="lib/angular/angular-animate.min.js"></script>
    <script src="lib/angular/angular-cookies.min.js"></script>
    <script src="lib/angular/angular-resource.min.js"></script>
    <script src="lib/angular/angular-route.min.js"></script>
    <script src="lib/fastclick.min.js"></script>
    <script src="lib/toaster/toaster.js"></script>
    <script src="lib/webshim/modernizr.min.js"></script>
    <script src="lib/webshim/polyfiller.min.js"></script>
    <script src="js/app.js"></script>
    <script src="js/services.js"></script>
    <script src="js/controllers.js"></script>
    <script src="js/filters.js"></script>
    <script src="js/directives.js"></script>
    <!-- endbuild -->
    

Несколько вещей, на которые следует обратить внимание: 1) задача копирования копирует каталог » shims » из библиотеки Webshims, потому что он загружает файлы динамически, и 2) установка «mangle: false» в задаче uglify необходима для внедрения внедрения Angular в зависимости. Я попытался использовать grunt-ngmin с uglify и не повезло.

После внесения этих изменений я могу запустить «grunt» и получить оптимизированную версию моего приложения в папке «dist» моего проекта. Что касается разработки, я продолжаю запускать приложение из папки «app», поэтому в настоящее время у меня нет необходимости наблюдать и обрабатывать ресурсы на лету. Это может измениться, если я начну использовать LESS или CoffeeScript.

Результаты говорят сами за себя: от 27 запросов до 5 при начальной загрузке и только 3 запроса менее чем за 2К после этого.

YSlow Скорость страницы
Без оптимизации 75

27 HTTP-запросов / 464K

55/100
Оптимизация Apache (заголовки gzip и expires) 89

начальная загрузка: 26 запросов / 166 КБ,
заполненный кэш: 4 запроса / 40 К

88/100
Apache + concat / minified / versioned файлы 98

начальная загрузка: 5 запросов / 136
Кбайт: кэш: 3 запроса / 1,4 КБ

93/100