PagSeguro
Canais iMasters

CodeIgniter + CSS + Javascript + Framework

Otimização de Javascript e CSS com CodeIgniter e Minfy, minimizando e unindo arquivos css e js.

Não é necessário discorrer sobre a importância do Javascript e do CSS bastando apenas citar alguns poucos exemplos como a validação de formulários, criação de elementos de interface como acordions e menus e citar alguns dos muitos plug-ins para desenvolvimento que agregam funcionalidades como geração de gráficos e data-grids para que fique clara a importância de manter uma boa estrutura destes arquivos em sua aplicação ou página da web.

Quando mais funcionalidades desejadas, mais arquivos .js e .css teremos, tomemos por exemplo uma página que contenha o arquivo compactado da JQuery, um plugin de calendário da JQuery UI e mais um arquivo .js para funções gerais do website, somados os arquivos .css necessários para o website e para a geração do calendário. Este exemplo nos daria pelo menos 5 arquivos distintos para compactar e carregar.

Há tempos vem sendo usada a técnica de compactar os arquivos javascript e css removendo comentários, linhas em branco, espaços desnecessários e quebras de linha com a finalidade de diminuir o tempo de carregamento on-line.

É interessante também diminuir o número de requisições http feitas ao servidor pelo browser, sendo que, se possível unir todos os arquivos .js em um único arquivo diminuiremos a quantidade de requisições, fazendo o mesmo com o .css estaremos contribuindo para um carregamento mais ágil.

Toda vez que iniciamos um projeto teremos que escolher quais são as bibliotecas e plug-ins que iremos utilizar bem como referenciar em nosso header html estes arquivos.

Cansado desta tarefa repetitiva fui buscar uma solução que fosse a mais simples e menos trabalhosa possível, gostaria de uma solução que “encontrasse” os arquivos .css e .js em uma pasta e fizesse o restante do trabalho para mim.  Acabei encontrando o Minify e melhor que isso, já existe um Driver * (Library) para o CodeIgniter 2.0.x.

Neste artigo estou descrevendo a forma como eu uso, mas é claro que existem muitas outras maneiras de integrar seus arquivos com esta solução.

Passo 1 - Baixando a biblioteca

O primeiro passo é baixar o CI-Minify, você encontrará o link (e também mais informações sobre como usar) aqui.

Então descompacte o arquivo e copie a pasta “Minify” que está dentro da pasta “libraries” do arquivo .zip para a sua pasta application/libraries conforme mostrado na figura 1.0

Copiando arquivos para o seu projeto

A partir deste momento já é possível utilizar a biblioteca Minify, contudo é importante observar que, por se tratar de um Driver, não será possível carregar pelo autoload, você precisará carregar este driver a partir de um controlador.

Passo 2 - Organizando os arquivos

Vamos analisar a estrutura das pastas e arquivos que serão utilizadas neste exemplo. Na figura 2.0 está a estrutura de pastas que contém os arquivos .css e .js  que estou utilizando em meu projeto.

Estrutura de pastas

Note que tenho um pasta chamada assets na raiz da aplicação com as seguintes subpastas .

js – Esta pasta contem os arquivos Javascript originais sem compactação, estes arquivos podem ser editados facilmente, caso existam arquivos compactados aqui dentro, também não tem problema.

css – É a pasta onde estão os arquivos .css originais, eles estão identados e organizados para facilitar a edição.

ie_css – Esta é uma pasta auxiliar onde deixo os arquivos css específicos para corrigir problemas com o IE. Não quero estes arquivos carregando o tempo todo, portanto, não os adiciono ao arquivo final compactado.

min – Que irá guardar os dois arquivos gerados pelo Minify, um css e um js. Nesta pasta eu armazeno também a JQuery já compactada, tive que utilizar esta abordagem porque preciso que ela seja carregada antes dos outros scripts e tive como quero compactar a pasta js toda de uma vez não é possível definir a ordem dos arquivos a compactar.

imgs – A pasta de imagens da minha aplicação (não relevante para nosso exemplo).

O que vai ocorrer é que a Minify irá buscar todos os arquivos na pasta css e na pasta js e compactar criando apenas duas saídas na pasta min.

Passo 3 - Gerando os arquivos compactados

Para efetuar esta ação estamos colocando o seguido código no construtor da minha classe “home” que é a classe que defini  em default_controller no arquivo de configuração routes.php. De modo que cada vez que a aplicação for carregada serão gerados dois novos arquivos com o CSS e JS. Se você preferir (ou achar mais semântico) poderá criar um método para isto.

<?php if(!defined('BASEPATH')) exit('No direct script access allowed');
class Home extends CI_Controller {
       function __construct(){
             parent::__construct();
             $this->load->driver('minify');
             $csss = $this->minify->combine_directory('assets/css/');
             $this->minify->save_file($csss,'assets/min/minified.css');
             $jss =$this->minify->combine_directory('assets/js/');
             $this->minify->save_file($jss,'assets/min/minified.js'); 
}
}

Chamei meus arquivos respectivamente de minfied.css e minified.js

Passo 4 - Utilizando os arquivos compactados

Para utilizar os arquivos você simplesmente irá incluí-los em suas views conforme faria com qualquer outro arquivo .css e .js. Para simplificar esta tarefa eu construí uma view parcial e salvei em uma pasta chamada libraries dentro da pasta views com o nome de arquivo html-header.html. Veja a seguir o método no controlador que chama a minha tela de login.

function index(){
$this->load->view('libraries/html-header');
$this->load->view('login');
$this->load->view('libraries/html-footer');
}

Desta forma posso compartilhar o mesmo cabeçalho html em todo o website me preocupando apenas em construir o corpo das paginas propriamente dito.

A seguir está o código da view parcial html-header que carrega os arquivos compactados.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="pt-BR">
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
        <link rel="stylesheet" href="<?php echo base_url();?>assets/min/minified.css" type="text/css" media="screen"/>
        <!--[if IE]>
            <link rel="stylesheet" href="<?php echo base_url();?>assets/ie_css/ie.css" type="text/css" media="screen"/>
        <![endif]-->
        <!--[if IE 7]>
        <link rel="stylesheet" href="<?php echo base_url();?>assets/ie_css/ie7.css" type="text/css" media="screen"/>
        <![endif]-->
        <!--[if IE 6]>
        <link rel="stylesheet" href="<?php echo base_url();?>assets/ie_css/ie6.css" type="text/css" media="screen"/>
        <![endif]-->
        <script type="text/javascript" language="JavaScript">
            var base_url = "<?php echo base_url();?>";
        </script>
        <script type="text/javascript" src="<?php echo base_url();?>assets/min/jquery.js"></script>
        <script type="text/javascript" src="<?php echo base_url();?>assets/min/minified.js"></script>    
        <title>SISTEMA DE GESTÃO DE PEDIDOS</title>
    </head>
    <body>

Note que a JQuery está sendo carregada separadamente e todos os outros arquivos .js vem do resultado da compactação pelo Driver Minify que gerou o arquivo minified.js. Desta forma, quando quisermos uma nova funcionalidade javascript ou houver a necessidade de incluir um novo arquivo .css basta incluir na pasta e na próxima vez que o sistema for carregado ele será automaticamente incluído no arquivo compactado.

Os arquivos relativos as correções do IE continuam sendo carregados do modo tradicional e poderão ser minimizados separadamente se desejado.

Em meu header html incluo uma variável global JavaScript camada base_url onde guardo a o caminho base da aplicação ou website para utilizar em requisições Ajax etc.

Espero que tenha sido útil. Abraço e até a próxima!


Comente também

7 Comentários

Danilo Melo
Danilo Melo

nossa meu, um dia eu chego lá...

André
André

Otimo artigo, só uma perguntinha, eu posso criar um metodo aleatório para gerar os arquivos minificados e chamar esse método apenas qnd eu fizer alguma alteração no .js/css ? Assim o cliente nao teria que ficar toda hora abrindo o site para gerar os arquivos ... Ou estou enganado com relação a isso ? ?

Ademir Cristiano Gabardo
Ademir Cristiano Gabardo

Sim André, pode sim, só não esquecer de sempre que você alterar algo nos CSS originais deverá chamar esse método para que ele atualize os arquivos minimizados para você.
Obrigado por comentar.

Abraços a todos.

Reinaldo Deprera
Reinaldo Deprera

Não usei o driver, mas pelo que li ele tem grandes limitações:
- Não declarar um javascript ou css em linha. Só suporta carregamento de arquivos.
- As propriedades das etiquetas script e css não podem ser usadas, ou seja, atributos.como defer, charset, media e entre outros não podem ser utilizados.
- Não realiza cache. Faz o processo de compactação cada vez que uma página é visitada.
- No view, o direver não oferece uma forma de abstrai os requisitos de cada página. Ou seja, se você precisa carregar um css para o IE 7 ou inferior numa página X e não houver essa necessidade na página Y você terá uma etiqueta css vazia para o IE 7 ou inferior nessa página. A menos que você carregue outro header, o que é um paradigma que lhe rendera trabalho extra.
- Não há preocupação com a segurança do servidor. Um hacker pode criar um bot simples para solcitar de maneira assíncrona diversas requisições da uri assets/min/minified.css elevando o consumo de memória do servidor. Se não for suficiente para derrubar o apache, pode ser pelo menos uma das ferramentas para conseguir isso em conjunto com um syn-ack flood na porta 80 com spoofing. Tornaria o ataque muito eficiente para a imensa maioria dos sites.

Eu fiz uma livraria para o CI 1.7.3 que tem tudo isso e mais um pouco. Se algúem tiver interesse eu mando por e-mail. Quando eu trabalhar com o CI 2.0 com certeza vou criar (se ninguém criar antes) uma livraria ou driver igual para ele ou quem sabe, modificar este driver e implementar esses atributos.

Marco Monteiro
Marco Monteiro

Não conhecia de todo este Driver! Muito bom, e vou passar a usar certamente nos meus próximos projectos.

Já me tinha perguntado se existiria algo assim, assim como no rails podemos criar Bundles com as CSS e o javascript isto assim ajuda bastante =)

Ademir Cristiano Gabardo
Ademir Cristiano Gabardo

Reinaldo, tem alguns pontos que acho que você não compreendeu, sobre a questão de segurança, chamar várias vezes o arquivo minified.css não irá acarretar em nada além do trafego que estes kb consumirem, pois uma vez gerado o arquivo ele é igual a qualquer outro CSS.

E sobre ter que gerar o .CSS e o .JS atualizado todas vez que carregar a classe, não precisa, você pode criar um método em uma classe para fazer isso, e chamar este método somente quando modificar algum script .JS ou algum arquivo .CSS.

Sobre o CodeIgniter 1.7.3 eu gostava bastante dele, e fui bem relutante em migrar para o 2.0, mas agora que estou trabalhando com ele a uns 6 projetos já. Não voltaria para o 1.7.3. Ele está muito melhor estruturado.

De qualquer modo, obrigado pelos comentários e fique a vontade para postar sua Library, se ela for realmente melhor que a Minify a comunidade com certeza vai acolher.

Obrigado, Abraços.

Halan Batista
Halan Batista

Quando eu coloco o código no meu Controller aparece a seguinte mensagem:

Fatal error: Call to undefined method CI_Loader::driver() in /Applications/XAMPP/xamppfiles/htdocs/www/adoroviagem/system/application/app-av/controllers/revista.php on line 20

Qual a sua opinião?

Comentários considerados ofensivos serão moderados.
KingHost

Parceiros

IBM
PagSeguro
Internet Innovation
Dialhost
HostNet
Tecla
KingHost
DotStore
Dinamize