Melhores práticas para um site mais rápido

Publicado por Ribamar FS em 25/03/2009

[ Hits: 8.736 ]

Blog: http://ribafs.org

 


Melhores práticas para um site mais rápido



Um pequeno resumo da documentação da extensão YSlow para o Firefox, encontrado em inglês em: Best Practices for Speeding Up Your Web Site

A extensão, que mede o desempenho de sites no Firefox, pode ser encontrada em:
Obs.: O original é bem mais detalhado e com muito mais informações, aqui trago apenas o que achei mais interessante ou importante.

80% do tempo gasto pelo visitante para baixar uma página é gasto no front-end (cliente) e somente 20 no back-end (servidor).

Desses 80%, a maioria é gasto baixando componentes: imagens, CSS, script JS, Flash etc.

Reduzindo o número de componentes do site reduzirá as requisições HTTP para renderizar a página no cliente. Esta é a chave de páginas rápidas.

Simplificar o design das páginas reduzirá o número de componentes.

Abaixo algumas técnicas para reduzir o número de requisições e ao mesmo tempo manter um design rico.

Usar CSS sprites reduz o número de requisições de imagens, ao invés de requisitar várias requisita-se somente uma e o CSS mapeia usando o background-image e background-position. Exemplo em: RibaFS - Sprites em CSS

Combinar, quando possível todo o CSS em um único arquivo externo.

Mova o CSS para o topo da página, entre as tags <head> e </head> que a página será carregada mais rapidamente.

Já os scripts em JavaScript devem ser movidos para o final da página, para que a carga seja otimizada. É verdade que em algumas situações não dá para mover para o final da página, mas sempre que possível devemos fazê-lo.

O IE suporta expressões em CSS e para melhor desempenho evite estas expressões.

Sempre que possível tenha o CSS e o JavaScript em arquivos externos para melhor desempenho.

Otimize para reduzir o código do CSS e do JavaScript.

Remova caracteres desnecessários, linhas e trechos duplicados e otimize ao máximo seu código. Isso vale também para toda a construção do site, evitar tudo que seja desnecessário e otimizar o necessário.

Evite redirecionamentos.

Não tenha mais que 3 redirecionamentos na página. Exemplo: temos 3 banners cujas imagens vem de outras URLs. No caso o site só abrirá quando pegar as imagens dos outros sites. Estando tudo normal ele terá que fazer a requisição aos outros sites e imagine quando um deles está lento.

Use GET para as requisições de AJAX. São mais rápidas que usando POST.

Otimize ao máximo a página inicial, reduzindo a carga para que o visitante chegue.

Nas demais páginas poderá adicionar componentes que colocaria na inicial.

Minimizar o número de iframes.

Evite erro 404 (páginas não encontradas).

Use o serviço do servidor para redirecionar o usuário para uma página personalizada quando acontecer um erro 404.

Reduza o tamanho dos cookies.

Minimize acessos DOM.

Desenvolva manipuladores de eventos inteligentes.

Acontece de um evento somente ser disparado quando um outro o for e isso pode complicar. Mais detalhes no documento original.

Ao fazer link dos arquivos externos prefira <link...> ao invés de @import.

Evite filtros no CSS.

Otimize as imagens. Sempre antes de enviar as imagens para o servidor, reduza seu tamanho, como também reduza a quantidade de cores sempre que razoável.

Alguns serviços online que ajudam na otimização de imagens:
Otimize os sprites CSS.

As imagens ficando na horizontal ao invés da vertical carregam mais rapidamente.

Não altere as dimensões de imagens somente no HTML. Isso altera somente a visualização, mas seu tamanho permanece o mesmo. Altere seu tamanho offline e envie para o servidor ao invés.

Reduza o tamanho dos favicon.ico.

Mantenha o tamanho dos componentes sempre inferior a 25KB.

Lembre que esse valor é para o arquivo descompactado.

Mais informações no documento original em inglês: Best Practices for Speeding Up Your Web Site

Página deste artigo: Melhores práticas para um site mais rápido

Outras dicas deste autor

Proteja seus filhos de conteúdo adulto e impróprio

Teste de USB - prevenindo queima de pendrive

Novo site sobre PostgreSQL

Instalar Apache, PHP, MySQL e PostgreSQL no Ubuntu Linux 8.10

Super Scaffold - Crie aplicativos em PHP com MySQL ou PostgreSQL de forma automática

Leitura recomendada

Configurar efeito modal ao fundo de um elemento com jQuery

Para sempre VOL

Ajax loading

Página inicial personalizada

Como personalizar o thumbnail de seu site no Facebook

  

Comentários
[1] Comentário enviado por fabio em 25/03/2009 - 16:47h

Pra quem quiser se aprofundar no assunto, um livro que recomento é o: High Performance Web Sites, da editora O'reilly. O autor do livro foi o responsável pela reforma visando performance de todo o portal da Yahoo e se não me engano é o próprio criador do YSlow.

Dentro de meus limites de limpeza, apliquei muitas de suas técnicas aqui no VOL.

Recomendo a leitura!

Um abraço.

[2] Comentário enviado por henbran em 24/06/2010 - 14:26h

PESSOAL, BOA TARDE!!! Por favor, ajudem-me a resolver um problema de lentidão AJAX no servidor WEB.
..........................................................................................................................................................
Uso a muito tempo Ubuntu (agora versão 10 64bits), apache2, php5, mysql5 e, desenvolvi um sistema com tecnologia Ajax x PHP e Mysql. Uso orientação a Objetos em PHP. A estrutura PHP está assim:

arquivo (classe) principal: chamarClass.php
---------------------------------------------------------------------------------------------------------------------------------------------------------------
<?php
session_start();
require_once 'cmdSql.php';
require_once 'pesquisaSql.php';

class chamarClass extends cmdSQL {
public $funcao;
public function __construct() {
$this->funcao = $_POST[funcao];
$this->funcao();
}

public function funcao() {
switch ($this->funcao) {
case 'pesqTurma':
//echo "teste1: ".$this->funcao; exit;
$pesquisaSql = new pesquisaSql();
//echo "teste3: ".$this->funcao; exit;
$this->sql = $pesquisaSql->pesqTurma();
//echo "teste2: ".$this->sql;exit;
$this->pesquisar();
break;

case 'pesqDiasSemana':
$pesquisaSql = new pesquisaSql();
$this->sql = $pesquisaSql->pesqDiasSemana();
$this->pesquisar();
break;

case 'pesqDisponibilidadeTurno':
$pesquisaSql = new pesquisaSql();
$this->sql = $pesquisaSql->pesqDisponibilidadeTurno();
$this->pesquisar();
break;

case 'pesqOutroTemaInteresse':
$pesquisaSql = new pesquisaSql();
$this->sql = $pesquisaSql->pesqOutroTemaInteresse();
$this->pesquisar();
break;

case 'pesqCargaHrDesejada':
$pesquisaSql = new pesquisaSql();
$this->sql = $pesquisaSql->pesqCargaHrDesejada();
$this->pesquisar();
break;

case 'pesqCursoRealizado':
$pesquisaSql = new pesquisaSql();
$this->sql = $pesquisaSql->pesqCursoRealizado();
$this->pesquisar();
break;

default:
echo "funcao indefinida";
session_destroy(); // DESTRUIR SESSÃO POIS PODE SER TENTARIVA DE CÓDIGO MALICIOSO
exit;
break;
}
if (is_array($this->retorno)
)$this->extraiArrayXml();
///echo $this->xml; exit;
if ($this->xml != ''
)echo $this->exibeXml();
}

}


$chamarClass = new chamarClass();
?>
------------------------------------------------------------------------------------------------------------------------------------------------
que extende a classe cmdSql: cmdSql.php
-----------------------------------------------------------------------------------------------------------------------------------------------
<?php

/* DEFINIÇÃO DESTA CLASSE: Receber as strings básicas Sql e executar (select / insert / update / delete)
* setar o resultado das instruções sql executadas no atributo 'retorno' e ...
* de uma classe extendida dessa se pode gerar a string xml e ...
* exibir o xml
*/

require_once("Banco.php");
class cmdSQL extends Banco {

public $retorno; //GUARDA O RETORNO DA INSTRUÇÃO SQL EXECUTADA
public $rs; // SETA O RECORDSET
public $sql;
public $xml;

//||||||||||||| COMANDOS DE SQL PARA OPERAÇÕES BÁSICAS |||||||||||||||||||||
//++++++++++++++++++++++++++ PESQUISAR ++++++++++++++++++++++++++
public function pesquisar() { // inicio do function PESQUISAR
//if ($sql)$this->sql = $sql;
try {
$this->conectar();
try // depende do resultado das instruções SQL a seguir
{
$this->rs = $this->con->prepare($this->sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$this->rs->execute(); //executa a instrução sql
$this->retorno[n_reg] = $this->rs->rowCount();
$this->retorno[n_cols] = $this->rs->columnCount();
//echo "teste0: ". $this->retorno[n_reg]; exit; //LINHA SÓ P/ TESTE;

if (($this->retorno[n_reg])>0) {
$this->retorno[res]=$this->rs->fetchAll(PDO::FETCH_ASSOC); //Retorna todas as linhas (registros) como um array
}
else {
//Mensagem alertando que não econtrou registros
$this->retorno[msg] .= "Registro(s) não encontrado(s).";
}

}
catch (Exception $e) {
$this->retorno[msg] .= "\nErro: Código: " . $e->getCode() . "Mensagem " . $e->getMessage();
}
} catch (Exception $exc) {
$this->retorno[msg] .= $this->msg." <hr> ".$exc->getTraceAsString();
}
return $this->retorno;
} // fim do function PESQUISAR
//++++++++++++++++++++++++++ INCLUIR ++++++++++++++++++++++++++
public function incluir() {
//$this->Banco = new Banco();
$this->conectar();
if (isset ($this->con)) {
try {
$this->rs = $this->con->prepare($this->sql);
$this->rs->execute();
$this->retorno[msg] = 'Registro salvo com sucesso!';
}
catch (Exception $e) {
$this->retorno[msg] = "Erro de inclusão: Código: " . $e->getCode() . "Mensagem " . $e->getMessage();
}
}
return $this->retorno;
}
//++++++++++++++++++++++++++ ALTERAR ++++++++++++++++++++++++++
public function alterar() {
//$this->Banco = new Banco();
$this->conectar();
if (isset($this->con)) {
try {
$this->rs = $this->con->prepare($this->sql);
$this->rs->execute();
$this->retorno[msg] = 'Registro alterado com sucesso!';
}
catch (Exception $e) {
$this->retorno[msg] = "Erro: Código: " . $e->getCode() . "Mensagem " . $e->getMessage();
}
}
//return $this->retorno;
}
//++++++++++++++++++++++++++ EXCLUIR ++++++++++++++++++++++++++
public function excluir() {
//$this->Banco = new Banco();
$this->conectar();
if(isset($this->con)) {
try {
$this->rs = $this->con->prepare($this->sql);
$this->rs->execute();
$this->retorno[msg] = 'Registro alterado com sucesso!';
}
catch (Exception $e) {
$this->retorno[msg] = "Erro: Código: " . $e->getCode() . "Mensagem " . $e->getMessage();
}
}
return $this->retorno;
}

public function extraiArrayXml() {
try {
if ($this->retorno[res]) {
foreach ($this->retorno[res] as $lin) {
foreach ($lin as $k=>$col) {
$linha .= "<".$k.">".utf8_encode($col)."</".$k.">";
}
}
$this->xml .= "<registros>".$linha."</registros>";
}
if ($this->retorno[n_reg]) $this->xml .= "<n_reg>".$this->retorno[n_reg]."</n_reg>";
if ($this->retorno[n_cols]) $this->xml .= " <msg> ".$this->retorno[n_cols]." </msg>";
if ($this->retorno[msg]) $this->xml .= " <msg> ".$this->retorno[msg]." </msg>";

} catch (Exception $exc) {
echo "Erro de extração da Array para XML.<hr>".$exc->getTraceAsString();
}


}
// %%%%%%%%%%%%%%%% EXIBE XML %%%%%%%%%%%%%%
public function exibeXml() {
try {
$this->xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><raiz>".$this->xml."</raiz>";
header("Content-type: application/xml");
return $this->xml;
} catch (Exception $exc) {
echo '<msg>Erro de montagem XML!!!<msg>'.$exc->getTraceAsString();
}
}
}

?>
------------------------------------------------------------------------------------------------------------------------------------------------------
que extende a classe Banco.php
-------------------------------------------------------------------------------------------------------------------------------------------------------
<?php

require_once("dC.php");

class Banco extends dC {

public $con;
public $msg;

public function __construct() {
}

public function conectar() {

$this->tipoBd();
if ($this->con) {
try {
$this->con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
$this->msg = "Erro de conexão com o banco de dados: Código: " . $e->getCode() . "Mensagem " . $e->getMessage() . "hora: " . date('H:i:s');
}
} else {
echo "Erro na definição PDO do banco de dados!";
exit;
}
}

public function tipoBd() {
try {
switch ($this->tipo) {
case 'mysql':
try {
$this->con = new PDO("mysql:host=" . $this->host . ";dbname=" . $this->bd, $this->user, $this->pass);
} catch (Exception $exc) {
$this->msg = "Erro de coneção com o banco de dados MySql. " . $exc->getTraceAsString();
}
break;
case 'pgsql':
$this->con = new PDO("pgsql:dbname={" . $this->bd . "};user={" . $this->user . "}; password={" . $this->pass . "};host=" . $this->host);
break;
case 'oci8':
$tns = "(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=" . $this->host . ")(PORT=1521)))(CONNECT_DATA=(SID=" . $this->bd . ")))";
$this->con = new PDO("oci:dbname=" . $tns, $this->user, $this->pass, array(PDO::ATTR_PERSISTENT => true));
break;
case 'mssql':
$this->con = new PDO("mssql:host={" . $this->host . "},1433;dbname={" . $this->bd . "}", $this->user, $this->pass);
break;
}
} catch (Exception $exc) {
echo $exc->getTraceAsString();
exit;
}
}

}
?>
------------------------------------------------------------------------------------------------------------------------------------------------------
que extende a classe dC.php
-------------------------------------------------------------------------------------------------------------------------------------------------------
<?php
class dC {
public $tipo = "mysql";
public $host = "localhost";
public $bd = "nomeDoBancoDeDados";
public $user = "usuario";
public $pass = "senha";
}
?>
------------------------------------------------------------------------------------------------------------------------------------------------------
A classe que monta as sstring sql é pesquisaSql.php
-------------------------------------------------------------------------------------------------------------------------------------------------------
<?php

session_start();

class pesquisaSql {

public $fim;
public $funcao;
public $limite;
public $ordem;
public $sessao;
public $todos;
public $id_turma;
public $desc_turma;

public function pesqTurma() {
$this->ordem = "GROUP BY t.id_turma ORDER BY t.desc_turma LIMIT 20";

if ($this->id_turma != '') {
$condicao .= " t.id_turma= " . $this->id_turma;
}

if ($this->desc_turma != '') {
if ($condicao)
$condicao .= " AND ";
$condicao .= " t.desc_turma= " . $this->desc_turma;
}

if ($condicao)
$condicao = " WHERE " . $condicao;

return "SELECT t.id_turma, t.desc_turma FROM turma t " . $condicao . " " . $this->ordem;
}

public function pesqDiasSemana() {
$this->ordem = "GROUP BY s.id_dia_semana ORDER BY s.desc_dia_semana LIMIT 20";

if ($this->id_dia_semana != '') {
$condicao .= " s.id_dia_semana= " . $this->id_dia_semana;
}

if ($this->desc_dia_semana != '') {
if ($condicao)
$condicao .= " AND ";
$condicao .= " t.desc_dia_semana= " . $this->desc_dia_semana;
}

if ($condicao)
$condicao = " WHERE " . $condicao;

return "SELECT s.id_dia_semana, s.desc_dia_semana FROM dia_semana s " . $condicao . " " . $this->ordem;
}

public function pesqDisponibilidadeTurno() {
$this->ordem = "GROUP BY d.id_disponibilidade ORDER BY d.desc_disponibilidade LIMIT 20";

if ($this->id_disponibilidade != '') {
$condicao .= " d.id_disponibilidade= " . $this->id_disponibilidade;
}

if ($this->desc_disponibilidade != '') {
if ($condicao)
$condicao .= " AND ";
$condicao .= " d.desc_disponibilidade= " . $this->desc_disponibilidade;
}

if ($condicao)
$condicao = " WHERE " . $condicao;

return "SELECT d.id_disponibilidade, d.desc_disponibilidade FROM disponibilidade_turno d " . $condicao . " " . $this->ordem;
}
// &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
public function pesqOutroTemaInteresse() {
$this->ordem = "GROUP BY ot.id_outro_tema ORDER BY ot.desc_outro_tema LIMIT 20";

if ($this->id_outro_tema != '') {
$condicao .= " d.id_outro_tema= " . $this->id_outro_tema;
}

if ($this->desc_outro_tema != '') {
if ($condicao)
$condicao .= " AND ";
$condicao .= " ot.desc_outro_tema= " . $this->desc_outro_tema;
}

if ($condicao)
$condicao = " WHERE " . $condicao;

return "SELECT ot.id_outro_tema, ot.desc_outro_tema FROM outro_tema_interesse ot " . $condicao . " " . $this->ordem;
}
// &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
public function pesqCargaHrDesejada() {
$this->ordem = "GROUP BY ch.id_carga_horaria ORDER BY ch.desc_carga_horaria LIMIT 20";

if ($this->id_carga_horaria != '') {
$condicao .= " ch.id_carga_horaria= " . $this->id_carga_horaria;
}

if ($this->desc_carga_horaria != '') {
if ($condicao)
$condicao .= " AND ";
$condicao .= " ch.desc_carga_horaria= " . $this->desc_carga_horaria;
}

if ($condicao)
$condicao = " WHERE " . $condicao;

return "SELECT ch.id_carga_horaria, ch.desc_carga_horaria FROM carga_horaria_desejada ch " . $condicao . " " . $this->ordem;
}
// &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
public function pesqCursoRealizado() {
$this->ordem = "GROUP BY cr.id_curso_realizado ORDER BY cr.desc_curso_realizado LIMIT 20";
if ($this->id_carga_horaria != '') {
$condicao .= " ch.id_carga_horaria= " . $this->id_carga_horaria;
}

if ($this->desc_curso_realizado != '') {
if ($condicao)
$condicao .= " AND ";
$condicao .= " cr.desc_curso_realizado= " . $this->desc_curso_realizado;
}

if ($condicao)
$condicao = " WHERE " . $condicao;

return "SELECT cr.id_curso_realizado, cr.desc_curso_realizado FROM curso_realizado cr " . $condicao . " " . $this->ordem;
}
}
?>




Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts