Front End

27 out, 2014

React, Browserify & Gulp: a maneira mais simples

Publicidade

Este artigo é destinado para usuários com alguma experiência com Gulp.js.

Nos meus últimos dois dias úteis, estive lidando com um problema muito chato para executar minhas tarefas de Browserify e React.js no Gulp e vou compartilhar a solução que, na minha opinião, é a mais simples que encontrei até então. Vamos lá?

Background

Estou utilizando Bower para gerenciar as dependências que ficam no cliente e, portanto, me obrigo a fazer o shim delas para utilizá-las (facilmente) junto ao Browserify. O ponto é que eu estou utilizando o bundle de módulos gulp-browserify para solucionar o meu problema com Gulp + Browserify e não o módulo Browserify puro.

Vejam a minha task com gulp-browserify:

gulp.task('scripts', function () {  
  return gulp.src('./assets/js/main.js')
    .pipe(browserify({
        insertGlobals: true,
        shim: {
          jquery: {
            path: './assets/vendor/jquery/dist/jquery.js',
            exports: '#039;
          },
          underscore: {
            path: './assets/vendor/underscore/underscore.js',
            exports: '_',
            depends: {
              jquery: '#039;
            }
          },
          backbone: {
            path: './assets/vendor/backbone/backbone.js',
            exports: 'Backbone',
            depends: {
              underscore: '_'
            }
          }
        }
      }))
    .pipe(gulp.dest('./static/js'));
});

Tudo estava a funcionar muito bem até que decidi por utilizar o React: eis aqui quando a dor de cabeça veio à tona.

Background – II

O React possui duas diretrizes, sendo uma essencial e outra optativa. A essencial é o React em si e a optativa é a utilização da sua “sintaxe” JSX. Por questões pessoais e para facilitar a minha vida na escrita de código, decidi por ir de JSX, o que significa o seguinte:

“Preciso fazer shim do React; Preciso fazer com que arquivos .jsx se “transformem” em .js”.

Então, fui logo para a internet procurar uma solução para trabalhar com o Gulp e tudo o que eu achei se referia a utilização do falado módulo browserify para se utilizar com o gulp. Em nenhum momento encontrei algo para o gulp-browserify, que já traz consigo o browserify e o browserify-shim – que, como falado, é necessário para que eu possa lidar com as dependências instaladas através do Bower.

Background – III

Insisti em uma solução que utilizasse o gulp-browserify para que me poupasse de reinventar a roda, mas não encontrei nada. Então, fiz alguns testes com o módulo “vanilla” browserify utilizando reactify e browserify-shim como transformers, mas o resultado não foi satisfatório porque não entrava na minha cabeça como utilizá-los em conjunto.

Quando me dei conta de que estava “perdendo” muito tempo, comecei a seguir exatamente o que os guias me instruíam e, de novo, nenhum êxito.

Em seguida, “descobri” que o meu problema absoluto era o shiming. React e Browserify + shim não estavam conversando no mesmo idioma.

A solução!

giphy

Pode parecer óbvio – e definitivamente é! –, mas para mim foi um momento Eureka, porque durante dois dias inteiros eu não tinha pensado nisso: só pensei em procurar uma solução através de um módulo e pronto.

Vejam só a descrição do gulp-react: Precompile Facebook React JSX templates into JavaScript

Em português traduzido livremente: Pré-compila os templates JSX do React do Facebook em JavaScript

Pensando de forma sequencial, tenho o seguinte: Primeiro de tudo, compilo JSX em JS, depois, com o JS gerado, consigo fazer o que eu quiser através da minha anteriormente apresentada task scripts.

O que eu fiz, então, foi manter intacta a minha tarefa scripts e então criei uma nova para transformação de JSX em JS:

gulp.task('jsx', function () {  
  return gulp.src('./assets/jsx/**/*.jsx')
    .pipe(react())
    .pipe(gulp.dest('./assets/js/'));
});

E então, voi là! Simples, não?

Mas vamos fazer o seguinte: vou explicar o passo-a-passo, do zero, para você entender de maneira flat.

A solução – simples

Para baixar e instalar o gulp, gulp-browserify e gulp-react:

npm install --D gulp gulp-browserify gulp-react

Então, o seu gulpfile.js:

var gulp            = require ('gulp')  
    , browserify    = require ('gulp-browserify')
    , react         = require ('gulp-react');

gulp.task('jsx', function () {  
  return gulp.src('./assets/jsx/**/*.jsx')
    .pipe(react())
    .pipe(gulp.dest('./assets/js/'));
});

gulp.task('scripts', function () {  
  return gulp.src('./assets/js/main.js')
    .pipe(browserify({
        shim: {
          react: {
            path: './assets/vendor/react/react.js',
            exports: 'React'
          }
        }
      }))
    .pipe(gulp.dest('./static/js/'));
});

gulp.task('default', ['jsx', 'scripts']);

Lendo o arquivo, de cima para baixo e à grosso modo, teríamos:

  • O carregamento das três dependências;
  • A tarefa jsx, que acessa todas (**) as pastas de ./assets/jsx/ e itera entre os arquivos de extensão .jsx para transformá-los em .js, salvando-os na pasta ./assets/js/.
  • A tarefa scripts, que utiliza do gulp-browserify para gerenciar as dependências e fazer o shiming do react para finalmente salvar em um arquivo único, nomeado de main.js, na pasta ./static/js/.

Depois, via linha de comando:

gulp

Ou, individualmente:

gulp jsx

e

gulp scripts

Considerações finais

Por incrível que possa parecer, essa é a solução mais simples que eu pude encontrar. Me poupa de reinventar a roda utilizando o módulo browserifyno Gulp e faz exatamente o que eu quero. Para outros que enfrentam o mesmo problema, eis aqui a solução.