микрозаймы онлайн займы на карту займы по паспорту

Usando Grunt com Laravel e Bootstrap 14

Um dia cansei de compilar LESS client side e procurei um jeito mais automatizado. Tentei com Basset, adorei no início, mas depois ele começou a ter vontade própria. Desculpe Basset, mas desse jeito não rola não. Próximo, tentei com Guard, mas não consegui o guard-less funcionar de jeito nenhum. Procurei ajuda no fórum, mas sem resultados concretos.

Finalmente, resolvi tentar mais uma vez com Grunt, mesmo que a primeira tentativa tinha me deixado assustada. Ra! Revelação! A vida acabou de ficar muito mais fácil.

No nosso exemplo vamos usar Twitter Bootstrap e vamos configurar essas tarefas simples, mas bastante usadas. Vamos:

  • Compilar os arquivos LESS e minificar o resultado
  • Concatenar e minificar os arquivos JavaScript
  • Executar os testes
  • Fazer o Grunt executar determinadas tarefas e atualizar o navegador cada vez que salvamos determinados arquivos

O que é o Grunt?

Definição oficial

Grunt: The JavaScript Task Runner

Grunt é uma ferramenta que automatiza as suas tarefas de front-end. Com apenas um comando no seu terminal, o Grunt vai compilar os seus arquivos LESS, SASS, Coffeescript, concatená-los, minificá-los, executar seus testes, atualizar o seu navegador e muito mais. As opçoẽs são inúmeras. E se você não achar o plugin certo para a sua tarefa, sempre pode criar o seu.

Instalação

Grunt roda no Node, então, antes de tudo, verifique se tem o npm instalado.

Agora vamos instalar o command line interface do Grunt:

npm install -g grunt-cli

Com o flag -g você instalou ele globalmente e agora pode acessar o comando grunt de qualquer localização no seu computador.

O próximo passo é inicializar o projeto. Na pasta do seu projeto execute

npm init

e siga as instruções. O comando vai criar o seu arquivo package.json, necessário para todo projeto npm.

{
  "name": "gruntRocks",
  "version": "0.0.1",
  "description": "Usando Grunt com Laravel e Bootstrap",
  "main": "Gruntfile.js",
  "repository": {
    "type": "git",
    "url": "https://github.com/elena-kolevska/grunt-laravel.git"
  },
  "keywords": [
    "Laravel",
    "Grunt",
    "laravel.com.br"
  ],
  "author": "Elena Kolevska",
  "license": "BSD",
  "bugs": {
    "url": "https://github.com/elena-kolevska/grunt-laravel/issues"
  }
}

Falta instalar Grunt e alguns plugins como dependências. Vamos usar:

  • “grunt-contrib-concat”: Para concatenar arquivos;
  • “grunt-contrib-less”: Para compilar arquivos LESS
  • “grunt-contrib-uglify”: Para minificar javascript
  • “grunt-contrib-watch”: Para monitorar alterações nos arquivos

No terminal rode:

npm install grunt --save-dev
npm install grunt-contrib-concat --save-dev
npm install grunt-contrib-less --save-dev
npm install grunt-contrib-uglify --save-dev
npm install grunt-contrib-watch --save-dev
npm install grunt-phpunit --save-dev

Isso vai instalar as dependências e porque definimos o flag --save-dev vai adicionar-las no arquivo package.json

Configuração do Gruntfile.js

Agora está começando a diversão. No arquivo package.json definimos que as configuraçoẽs das tarefas vão ficar no Gruntfile.js. Vamos criar ele no root do projeto.

Essa é a estrutura básica dele:

//Gruntfile.js
  module.exports = function(grunt) {
  
    //Inicializando o objeto de configuração
      grunt.initConfig({
 
        // Todas as configuraçoẽs de tarefas que vamos definir vão aqui
        concat: {
          //...
        },
        less{
          //...
        },
        uglify{
          //...
        },
        phpunit{
          //...
        },
        watch{
          //...
        }
      });
  
    // Carregar os plugins
  
    // Definição de tarefas
  
  };

Vamos precisar de Bootstrap e jQuery, então adicione eles no seu composer.json

  "require": {
    "twitter/bootstrap": "3.0.*@dev",
    "components/jquery": "1.9.*@dev"
  },

e roda composer update.

Obs: Para essas dependências pode usar o Bower, também, mas já que temos o Composer e os pacotes existem no Packagist, vamos utilizar ele.

Os stylesheets

Vamos criar a seguinte estrutura:

/app
  /assets
    /stylesheets
      -application.js
    /javascript
      - backend.less
      - base.less
      - fonts.less
      - frontend.less
      - variables.less

O arquivo /app/assets/stylesheets/frontend.less

@import 'base.less';

//estilos específicos para o frontend
// ...

O arquivo /app/assets/stylesheets/backend.less

@import 'base.less';

//estilos específicos para o backend
// ...

Os estilos comuns do frontend e backend ficam em base.less que também inclui as componentes necessárias do bootstrap.

O arquivo /app/assets/stylesheets/base.less

 
@import "variables.less";
@import "../../../vendor/twitter/bootstrap/less/mixins.less";

@import "../../../vendor/twitter/bootstrap/less/normalize.less";
@import "../../../vendor/twitter/bootstrap/less/print.less";


@import "../../../vendor/twitter/bootstrap/less/scaffolding.less";
@import "../../../vendor/twitter/bootstrap/less/type.less";
@import "../../../vendor/twitter/bootstrap/less/code.less";
/*
...
...
*/

E vamos configurar a tarefa para eles:

    less: {
        development: {
            options: {
              compress: true,  //minifica o resultado
            },
            files: {
              //compilando frontend.less em frontend.css
              "./public/assets/stylesheets/frontend.css":"./app/assets/stylesheets/frontend.less",
              //compilando backend.less em backend.css
              "./public/assets/stylesheets/backend.css":"./app/assets/stylesheets/backend.less"
            }
        }
    },

Para executar somente essa tarefa pode rodar grunt less no command line

O javascript

Essa é bastante clara, estamos concatenando jquery.min.js, bootstrap.min.js e frontend.js em um arquivo só: frontend.js que vai ficar na pasta public.

    concat: {
      options: {
        separator: ';',
      },
      javascript: {
        src: ['./vendor/components/jquery/jquery.min.js','./vendor/twitter/bootstrap/dist/js/bootstrap.min.js','./app/assets/javascript/frontend.js'],
        dest: './public/assets/javascript/frontend.js',
      },
    },

Se precisar pode adicionar mais arquivos. Por exemplo

    concat: {
      options: {
        separator: ';',
      },
      javascript: {
        src: ['./vendor/components/jquery/jquery.min.js','./vendor/twitter/bootstrap/dist/js/bootstrap.min.js','./app/assets/javascript/frontend.js'],
        dest: './public/assets/javascript/frontend.js',
      },
      validation: {
        src: ['./app/assets/javascript/jQueryValidator.js','./app/assets/javascript/validate.js'],
        dest: './public/assets/javascript/validate.js',
      },
    },

Para executar somente uma dessas tarefa pode rodar grunt concat:javascript ou grunt concat:validation no command line

E para minificar o resultado:

    uglify: {
      options: {
        mangle: false  // não muda os nomes das funções e variáveis
      },
      dist: {
        files: {
          './public/assets/javascript/frontend.js': './public/assets/javascript/frontend.js'
        }
      }
    },

Para executar somente essa tarefa pode rodar grunt uglify no command line

Os testes

Grunt também pode executar os seus testes em Laravel, mas para isso, vamos precisar de PhpUnit primeiro. Adicione ele no seu composer.json

    "phpunit/phpunit": "3.7.*"

e roda composer update.

E a tarefa:

        phpunit: {
            classes: {
            },
            options: {
            }
        },

Essa tarefa funciona mesmo sem configuração nenhuma, porque o phpunit automaticamente pega as configuraçoẽs do arquivo /phpunit.xml

Mas para ser consistente, aqui uma configuração básica:

        phpunit: {
            classes: {
                dir: 'app/tests/'   //a localização dos testes
            },
            options: {
                bin: 'vendor/bin/phpunit',
                colors: true
            }
        },

Para executar somente essa tarefa pode rodar grunt phpunit no command line

O monitoramento de alterações nos arquivos

O super-poder do Grunt é executar tarefas sem você precisar fazer muita coisa. Ele monitora os seus arquivos e só precisa das suas instruçoẽs para saber o que fazer e quando fazer-lo.

Nós já definimos 4 tarefas, “concat”, “less”, “uglify” e “phpunit”. Você pode executar cada uma deles separadamente, se precisar. Mas para realmente automatizar o nosso projeto vamos juntar as peças e definir a tarefa “watch” que vai monitorar determinados arquivos e executar as determinadas tarefas:

    watch: {
      js: {
        files: ['./app/assets/javascript/*.*'],   //arquivos monitorados
        tasks: ['concat:javascript','uglify'],     //tarefas executadas
        options: {
          livereload: true                        //atualiza o navegador
        }
      },
      less: {
        files: ['./app/assets/stylesheets/*.*'],  //arquivos monitorados
        tasks: ['less'],                          //tarefas executadas
        options: {
          livereload: true                        //atualiza o navegador
        }
      },
      tests: {
        files: ['app/controllers/*.php','app/models/*.php'],  //a tarefa vai ser executada só quando salvar arquivo nessa localização
        tasks: ['phpunit']
      }          
    }

Já deve estar adivinhando: cada vez que um arquivo na pasta “/app/assets/javascript” for salvo, o Grunt vai executar as tarefas “concat:javascript” e “uglify”. A mesma coisa com as tarefas “less” e “tests” e os arquivos apropriados. Alem disso, porque definimos livereload: true nas tarefas “js” e “less”, ele vai atualizar o navegador. Bom, na verdade, não é bem assim, para isso vai precisar de mais configuração, mas existe um extension para Chrome que faz isso para a gente. O nome é LiveReload.

Finalizando

No final, falta só carregar os plugins necessários e registrar a tarefa “default”. Vamos la:

    // Carregar os plugins
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-less');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-phpunit');

  
    // Definicão da tarefa default
    grunt.registerTask('default', ['watch']);

A tarefa “default” é a tarefa que vai ser executada quando rodar apenas grunt no terminal. No nosso caso, isso vai executar a tarefa “watch” que vai monitorando os arquivos e executando as tarefas definidas.

Finalmente, o arquivo completo:

module.exports = function(grunt) {
  
  //Inicializando o objeto de configuração
    grunt.initConfig({

      // Todas as configuraçoẽs de tarefas que vamos definir nesse bloco
      less: {
          development: {
              options: {
                compress: true,  //minifica o resultado
              },
              files: {
                //compilando frontend.less em frontend.css
                "./public/assets/stylesheets/frontend.css":"./app/assets/stylesheets/frontend.less",
                //compilando backend.less em backend.css
                "./public/assets/stylesheets/backend.css":"./app/assets/stylesheets/backend.less"
              }
          }
      },
      concat: {
        options: {
          separator: ';',
        },
        javascript: {
          src: ['./vendor/components/jquery/jquery.min.js','./vendor/twitter/bootstrap/dist/js/bootstrap.min.js','./app/assets/javascript/frontend.js'],
          dest: './public/assets/javascript/frontend.js',
        },
      },
      uglify: {
        options: {
          mangle: false  // não muda os nomes das funções e variáveis
        },
        dist: {
          files: {
            './public/assets/javascript/frontend.js': './public/assets/javascript/frontend.js'
          }
        }
      },
        phpunit: {
            classes: {
                dir: 'app/tests/'   //a localização dos testes
            },
            options: {
                bin: 'vendor/bin/phpunit',
                colors: true
            }
        },
      watch: {
        js: {
          files: ['./app/assets/javascript/*.*'],   //arquivos monitorados
          tasks: ['concat:javascript','uglify'],     //tarefas executadas
          options: {
            livereload: true                        //atualiza o navegador
          }
        },
        less: {
          files: ['./app/assets/stylesheets/*.*'],  //arquivos monitorados
          tasks: ['less'],                          //tarefas executadas
          options: {
            livereload: true                        //atualiza o navegador
          }
        },
        tests: {
          files: ['app/controllers/*.php','app/models/*.php'],  //a tarefa vai ser executada só quando salvar arquivo nessa localização
          tasks: ['phpunit']
        }          
      }
    });

  // Carregar os plugins
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-phpunit');
  
    
  // Definicão da tarefa default
  grunt.registerTask('default', ['watch']);

};

O código completo (sem a instalação do laravel) está disponível no github. Se quiser contribuir/melhorar o código, é só fazer um “pull request”.

Bom, obrigada por ficar comigo até o final. Espero que gostem desse meu primeiro post e que aproveitem as dicas :)

  • Diego Felix

    Com apenas um comando no seu terminal, o Grunt vai compilar os seus
    arquivos LESS, SASS, Coffeescript, concatená-los, minificá-los, executar
    seus testes, atualizar o seu navegador, te praparar um sanduíche de presunto, postar a foto do sanduíche no instagram e muito mais.

    Parabéns Elena, ótimo artigo! Vou tentar seguir em casa =)

  • valmir

    Gostei da dica, também tive problemas com basset.
    Parabéns pelo artigo.

    • Diego Felix

      O próprio Jason recomenda o Grunt agora.

  • fhferreira

    Maravilha Elena, vlw

  • http://brayanrastelli.com/ Brayan Rastelli

    Muito bom Elena, apenas uma dúvida, chegou a usar o Grunt para enviar arquivos estáticos para CDN ? Tipo o Amazon S3?

    • Kennedy Tedesco

      Eu uso, mais especificamente este plugin: https://npmjs.org/package/grunt-aws-s3

      É bem simples configurá-lo.

    • Rafael Ávila

      Tentei utilizar um plugin com algum nome sync no meio, o problema que perdi muito tempo tentando configurar para funcionar redondo e não ia, não faço a menor ideia, pois é bem simples. Então uso outras coisas do grunt, mas na hora de enviar continuo usando o bom e velho conjunto rsync e ssh do linux, aí fiz um pequeno shell script para automatizar a coisa. Com isso funciona semelhante o que o plugin prometia, o rsync salva o que precisa e pode ser usado para backup tb.

      ex.: rsync -av –rsh=”ssh -i key.pem” /var/www/dev.site/ [email protected]:/var/www/prod.site

      Com esse comando já interno do Linux, acredito que o Mac deve ter algo semelhante ou é igual criamos nosso mini Bacula, rs.

  • João Mello

    Bem, só isso? (rsrsrs)
    Eu já tinha “lido” algo sobre o grunt, mas não foi interessante e também não procurei aprofundar-me no assunto, porém seu artigo fez-me ficar maravilhado e otimizar meu trabalho.
    Muito obrigado por sua contribuição em meu aprendizado.
    Deus te abençoe.

  • Obrigada gente :)

  • pedrosttau

    Fantástico Elena!

  • Johnatan Maciell

    show !! vc é 100000*19998320988 .. é isso tudo ae rsrs
    show msm, ajudou muito !!!

  • http://www.navarrotecnologia.com.br Navarro Tecnologia

    Show, bem explicativo! abraços

  • Tivon

    Gulp !