Front End

14 mar, 2016

Gulp e FTP: atualizar um site “on the fly”

Publicidade

Neste artigo, vou explicar como usar o Gulp para interagir com os arquivos no servidor por meio de FTP. Você vai aprender como acompanhar os arquivos que está editando em sua máquina local e automaticamente sincronizá-los com o seu servidor assim que eles mudam e como configurar uma tarefa para lançar um FTP deploy sob demanda.

Premissa

No ano passado, eu fui designado para cuidar da atualização de algumas seções em um site legado em que o ambiente de desenvolvimento é atualmente acessível apenas por meio de FTP. Portanto, não há ambiente de desenvolvimento virtualizado local, nada de Git, nenhuma implantação automatizada, apenas a velha escola “FTP edição online e teste”!

Eu teria usado um aplicativo de FTP desktop para criar uma unidade virtual a fim de permitir editar arquivos facilmente e abrir o projeto inteiro em Sublime, mas eu não pude encontrar nenhum bom para a última versão do OS X (El Capitan), então eu decidi encontrar uma solução simples por mim mesmo, usando Gulp.

Se você já passou por uma situação semelhante ou só quer ter uma solução simples e rápida de linha de comando para editar um website que você pode acessar apenas por meio de FTP, continue lendo, este artigo é para você!

NOTA: Eu só quero salientar o fato de que esta solução não deve ser considerada uma das melhores práticas para o desenvolvimento e implantação, mas apenas um truque útil no caso de você ter que lidar com uma configuração muito básica, especialmente se você não está no controle dos ambientes de desenvolvimento e implantação.

Instalando Gulp

No caso de você não saber, Gulp é um sistema de construção muito popular escrito em NodeJS. Ele usa fluxos, por isso é bastante eficiente em lidar com transformações de dados e na gestão de fluxos de dados de diferentes fontes.

Gulp é um sistema de construção com base em fluxo muito popular escrito em NodeJS

gulp

Para ser capaz de executar o script que iremos escrever, você precisa ter o NodeJS e o Gulp instalados em sua máquina. Se você não tem o Gulp, pode instalá-lo com facilidade usando NPM:

npm install -g gulp

Preparando o projeto

Você precisa ter uma cópia do projeto completo na sua máquina local, por isso, se você não tem, precisa fazer o login no servidor e baixar uma cópia dos arquivos. Você pode usar qualquer software FTP para fazer isso, mas, se estiver em um Mac, há um truque rápido que lhe permite evitar a instalação de qualquer software adicional: você pode, com o finder aberto, pressionar ⌘ + k para iniciar a janela de conectar ao servidor e especificar a URL do FTP do seu projeto com a seguinte sintaxe: ftp://usuário:senha@host:port/path. Isso permitirá que você possa ver e copiar todos os arquivos de seu projeto e, caso esteja se perguntando, esse é um acesso só de leitura!

Uma vez que você copiou todos os arquivos necessários, você tem que inicializar o NPM no projeto copiado com:

npm init

Siga as instruções na tela e forneça todas as informações que faltam.

Em seguida, você precisa instalar Gulp também como uma dependência local:

npm install --save-dev gulp

Também precisamos usar algumas bibliotecas externas, então vamos instalá-las também:

npm install --save-dev gulp-util vinyl-ftp

gulp-util é um módulo que oferece uma série de funções de utilitários para gulp (vamos, principalmente, usar as funções relacionadas a log), e vinyl-ftp é uma biblioteca de FTP que permite acessar arquivos FTP e pastas como fluxos, e é uma combinação perfeita para o Gulp.

Ok, agora o último passo antes de ir para o código é inicializar um novo projeto gulp. Para fazer isso, basta executar:

gulp init

Ele vai criar um novo arquivo gulpfile.js, e vamos, finalmente, ir para algum código.

O gulpfile

Iremos implementar dois comandos Gulp diferentes: ftp-deploy e ftp-deploy-watch. O primeiro nos permite fazer o deploy de todas as alterações locais para o servidor; o segundo, por sua vez, ativa um monitoramento constante em nossos arquivos e faz a atualização imediatamente após qualquer alteração neles, o que é muito útil quando você quer código sincronizado com o servidor de desenvolvimento.

Para habilitar esses dois comandos, você precisa copiar e colar o seguinte código dentro do seu arquivo gulpfile.js.

'use strict';

var gulp = require('gulp');  
var gutil = require( 'gulp-util' );  
var ftp = require( 'vinyl-ftp' );

/** Configuration **/
var user = process.env.FTP_USER;  
var password = process.env.FTP_PWD;  
var host = 'your hostname or ip address';  
var port = 21;  
var localFilesGlob = ['./**/*'];  
var remoteFolder = '/myApp'


// helper function to build an FTP connection based on our configuration
function getFtpConnection() {  
    return ftp.create({
        host: host,
        port: port
        user: user,
        password: password,
        parallel: 5,
        log: gutil.log
    });
}

/**
 * Deploy task.
 * Copies the new files to the server
 *
 * Usage: `FTP_USER=someuser FTP_PWD=somepwd gulp ftp-deploy`
 */
gulp.task('ftp-deploy', function() {

    var conn = getFtpConnection();

    return gulp.src(localFilesGlob, { base: '.', buffer: false })
        .pipe( conn.newer( remoteFolder ) ) // only upload newer files 
        .pipe( conn.dest( remoteFolder ) )
    ;
});

/**
 * Watch deploy task.
 * Watches the local copy for changes and copies the new files to the server whenever an update is detected
 *
 * Usage: `FTP_USER=someuser FTP_PWD=somepwd gulp ftp-deploy-watch`
 */
gulp.task('ftp-deploy-watch', function() {

    var conn = getFtpConnection();

    gulp.watch(localFilesGlob)
    .on('change', function(event) {
      console.log('Changes detected! Uploading file "' + event.path + '", ' + event.type);

      return gulp.src( [event.path], { base: '.', buffer: false } )
        .pipe( conn.newer( remoteFolder ) ) // only upload newer files 
        .pipe( conn.dest( remoteFolder ) )
      ;
    });
});

O script Gulp é muito simples e autodescritivo, mas vamos tentar olhá-lo com mais detalhe.

Após importar nossos módulos, temos uma série de variáveis de configuração. As que você tem que definir são host, port, localFilesGlob e remoteFolder.

  • host é o nome do host ou o endereço IP do seu servidor FTP (por exemplo: myserver.com ou 123.124.125.126).
  • port é a porta em que o servidor FTP está escutando (geralmente é o padrão: 21).
  • localFilesGlob é um array contendo uma ou mais expressões glob. Essas expressões são usadas para determinar quais arquivos de sua cópia local devem ser acompanhados e em quais deve ser feito o deploy no servidor. A opção padrão é muito “aberta”, ele irá copiar todos os arquivos na pasta do projeto. Na maioria das vezes, é melhor ser mais específico, assim, certifique-se de construir seu próprio array customizado de glob, para evitar a cópia de dados desnecessários ou sensíveis.
  • remoteFolder é a pasta em seu servidor remoto que contém todo o projeto (onde os novos arquivos serão copiados).

Como você deve ter notado também, temos as variáveis username e password mapeadas para uma variável de ambiente. Geralmente é uma boa ideia não escrever senhas em arquivos de configuração, especialmente se você estiver pensando em publicar esse arquivo em algum lugar. Com essa abordagem, também podemos compartilhar o mesmo gulpfile com outras pessoas na equipe e permitir que todos possam usar suas credenciais pessoais.

Após o bloco de variáveis de configuração, nós temos a função getFtpConnection. Ela é usada como um helper para construir uma conexão FTP, usando as opções anteriormente especificadas. Você também pode adicionar algumas opções – por exemplo, parallel permite definir o número máximo de arquivos para upload em paralelo.

No final, nós temos nossos dois comandos reais do Gulp: ftp-deploy e ftp-deploy-watch.

Eles simplesmente definem um fluxo a partir das expressões Glob e as canalizam para o servidor de destino, por meio da conexão FTP. A única diferença entre os dois comandos é que no ftp-deploy lemos todos os arquivos a partir das expressões glob e as enviamos através da conexão; no segundo caso, monitoramos os arquivos e enviamos apenas os que mudam enquanto o comando está sendo executado.

Vale também lembrar que estamos canalizando os arquivos com a função conn.newer. Ela garante que apenas os arquivos que são diferentes dos que estão no servidor serão substituídos.

Executando os comandos

Para executar os comandos, você primeiro deve especificar as variáveis de ambiente FTP_USER e FTP_PWD. Por exemplo, você pode fazer desta maneira:

FTP_USER=someuser FTP_PWD=somepwd gulp ftp-deploy

ou

FTP_USER=someuser FTP_PWD=somepwd gulp ftp-deploy-watch

Ou, se preferir, você pode exportar as variáveis para o seu arquivo .bashrc ou .bash_profile (nesse caso, eu sugiro que você renomeie as variáveis para algo mais específico, a fim de evitar colisões).

Conclusões

Esta abordagem me permitiu resolver o problema com facilidade e rapidez, com um mecanismo que é bastante rápido de usar e fácil de manter.

Estou também mais e mais impressionado sobre quão fácil é ter soluções simples mas eficazes instalando e rodando o NodeJS e as ferramentas do seu ecossistema. Também estou impressionado com a versatilidade do Gulp e como a sua abordagem baseada em fluxo torna as coisas muito concisas e uniforme.

Espero que este artigo tenha sido útil e interessante para você.

Até a próxima!

***

Luciano Mammino faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: http://loige.co/gulp-and-ftp-update-a-website-on-the-fly/