Melhores práticas para um site mais rápido

Publicado por Ribamar FS em 25/03/2009

[ Hits: 8.887 ]

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

Modelagem de bancos de dados

Melhorando a segurança em sites Joomla

Plugin com controle de acesso para CakePHP 3

Site com bons recursos para Joomla

Lidando com nulos (NULL) em SQL

Leitura recomendada

Como personalizar o thumbnail de seu site no Facebook

CSS :: Bordas arredondadas

HTML sem tabelas (tableless)

Botões com imagem cambiável

CSS3 - Forçando quebra de linha em URL longa

  

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